#pragma once #include #include #include #include namespace jvalidate::detail { class Reference { public: Reference() = default; Reference(std::string const & anchor, Pointer const & pointer) : anchor_(anchor), pointer_(pointer) {} Reference(std::string_view fragment, bool allow_anchor = true) { EXPECT_M(fragment.find('#') != std::string::npos, "Reference requires a fragment token '#'"); size_t const index = fragment.find('/'); anchor_ = std::string(fragment.substr(0, index)); EXPECT_M(allow_anchor && anchor_.back() == '#', "Anchoring is not allowed in this context"); if (index != std::string::npos) { pointer_ = fragment.substr(index + 1); } } std::string const & anchor() const { return anchor_; } Pointer const & pointer() const { return pointer_; } Reference parent() const { return {anchor_, pointer_.parent()}; } Reference & operator/=(Pointer const & relative) { pointer_ /= relative; return *this; } Reference operator/(Pointer const & relative) const { return Reference(*this) /= relative; } Reference & operator/=(std::string_view key) { pointer_ /= key; return *this; } Reference operator/(std::string_view key) const { return Reference(*this) /= key; } Reference & operator/=(size_t index) { pointer_ /= index; return *this; } Reference operator/(size_t index) const { return Reference(*this) /= index; } friend std::ostream & operator<<(std::ostream & os, Reference const & self) { return os << self.anchor_ << self.pointer_; } auto operator<=>(Reference const &) const = default; private: std::string anchor_; Pointer pointer_; }; }