|
|
@@ -1,5 +1,6 @@
|
|
|
#pragma once
|
|
|
|
|
|
+#include <ostream>
|
|
|
#include <string>
|
|
|
#include <string_view>
|
|
|
|
|
|
@@ -11,12 +12,16 @@ namespace jvalidate::detail {
|
|
|
class RelativePointer {
|
|
|
public:
|
|
|
RelativePointer(std::string_view path) {
|
|
|
+ if (path == "0") {
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (auto pos = path.find('/'); pos != path.npos) {
|
|
|
pointer_ = Pointer(path.substr(pos));
|
|
|
path.remove_suffix(path.size() - pos);
|
|
|
} else {
|
|
|
EXPECT_M(not path.empty() && path.back() == '#',
|
|
|
- "RelativePointer must end in a pointer, or a '#'")
|
|
|
+ "RelativePointer must end in a pointer, or a '#'");
|
|
|
+ requests_key_ = true;
|
|
|
path.remove_suffix(1);
|
|
|
}
|
|
|
parent_steps_ = std::stoull(std::string(path));
|
|
|
@@ -24,14 +29,27 @@ public:
|
|
|
|
|
|
template <Adapter A>
|
|
|
std::variant<std::string, A> inspect(Pointer const & where, A const & root) const {
|
|
|
- if (pointer_) {
|
|
|
- return pointer_->walk(where.parent(parent_steps_).walk(root));
|
|
|
+ if (requests_key_) {
|
|
|
+ return where.parent(parent_steps_).back();
|
|
|
+ }
|
|
|
+ auto rval = where.parent(parent_steps_).walk(root);
|
|
|
+ return pointer_ ? pointer_->walk(rval) : rval;
|
|
|
+ }
|
|
|
+
|
|
|
+ friend std::ostream & operator<<(std::ostream & os, RelativePointer const & rel) {
|
|
|
+ os << rel.parent_steps_;
|
|
|
+ if (rel.requests_key_) {
|
|
|
+ return os << '#';
|
|
|
+ }
|
|
|
+ if (rel.pointer_) {
|
|
|
+ os << *rel.pointer_;
|
|
|
}
|
|
|
- return where.parent(parent_steps_).back();
|
|
|
+ return os;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- size_t parent_steps_;
|
|
|
- std::optional<Pointer> pointer_;
|
|
|
+ size_t parent_steps_ = 0;
|
|
|
+ bool requests_key_ = false;
|
|
|
+ std::optional<Pointer> pointer_ = std::nullopt;
|
|
|
};
|
|
|
}
|