#pragma once #include #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 if (path.ends_with('#')) { requests_key_ = true; path.remove_suffix(1); } EXPECT_M(path == "0" || not path.starts_with("0"), "Cannot zero-prefix a relative pointer"); parent_steps_ = from_str(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_.walk(rval); } friend std::ostream & operator<<(std::ostream & os, RelativePointer const & rel) { os << rel.parent_steps_; if (rel.requests_key_) { return os << '#'; } os << rel.pointer_; return os; } private: size_t parent_steps_ = 0; bool requests_key_ = false; Pointer pointer_ = {}; }; }