#pragma once #include #include #include #include #include #include namespace jvalidate::detail { class Reference { public: Reference() = default; Reference(URI const & uri, Anchor const & anchor = {}, Pointer const & pointer = {}) : uri_(uri), anchor_(anchor), pointer_(pointer) {} Reference(std::string_view ref, bool allow_anchor = true) { size_t end_of_uri = ref.find('#'); EXPECT(end_of_uri != std::string::npos); uri_ = URI(ref.substr(0, end_of_uri)); ref.remove_prefix(end_of_uri + 1); size_t const pointer_start = ref.find('/'); anchor_ = Anchor(ref.substr(0, pointer_start)); EXPECT_M(allow_anchor || anchor_.empty(), "Anchoring is not allowed in this context"); ref.remove_prefix(pointer_start); pointer_ = ref; } URI const & uri() const { return uri_; } Anchor const & anchor() const { return anchor_; } Pointer const & pointer() const { return pointer_; } Reference root() const { return {uri_, anchor_}; } Reference parent() const { return {uri_, 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.uri_ << '#' << self.anchor_ << self.pointer_; } auto operator<=>(Reference const &) const = default; private: URI uri_; Anchor anchor_; Pointer pointer_; }; }