#pragma once #include #include #include #include #include #include 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 '#'"); requests_key_ = true; path.remove_suffix(1); } parent_steps_ = std::stoull(std::string(path)); } template std::variant inspect(Pointer const & where, A const & root) const { 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 os; } private: size_t parent_steps_ = 0; bool requests_key_ = false; std::optional pointer_ = std::nullopt; }; }