| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- #pragma once
- #include <string>
- #include <string_view>
- #include <jvalidate/detail/anchor.h>
- #include <jvalidate/detail/expect.h>
- #include <jvalidate/detail/out.h>
- #include <jvalidate/detail/pointer.h>
- #include <jvalidate/uri.h>
- namespace jvalidate::detail {
- class Reference;
- class RootReference {
- private:
- friend class Reference;
- URI uri_;
- Anchor anchor_;
- public:
- RootReference() = default;
- explicit RootReference(URI const & uri, Anchor const & anchor = {})
- : uri_(uri), anchor_(anchor) {}
- explicit RootReference(std::string_view ref) : RootReference(ref, discard_out) {}
- bool is_relative() const { return uri_.is_relative(); }
- URI const & uri() const { return uri_; }
- Anchor const & anchor() const { return anchor_; }
- friend std::ostream & operator<<(std::ostream & os, RootReference const & self) {
- return os << self.uri_ << '#' << self.anchor_;
- }
- auto operator<=>(RootReference const &) const = default;
- private:
- RootReference(std::string_view ref, out<size_t> end) {
- end = std::string::npos;
- size_t end_of_uri = ref.find('#');
- uri_ = URI(ref.substr(0, end_of_uri));
- if (end_of_uri == std::string::npos) {
- return;
- }
- ref.remove_prefix(end_of_uri + 1);
- size_t const pointer_start = ref.find('/');
- anchor_ = Anchor(ref.substr(0, pointer_start));
- EXPECT_M(end || pointer_start == std::string::npos, "JSON-Pointer is illegal in this context");
- if (pointer_start != std::string::npos) {
- end = pointer_start + end_of_uri + 1;
- }
- }
- };
- class Reference {
- private:
- RootReference root_;
- Pointer pointer_;
- public:
- Reference() = default;
- explicit Reference(URI const & uri, Pointer const & pointer = {})
- : root_(uri), pointer_(pointer) {}
- explicit Reference(URI const & uri, Anchor const & anchor, Pointer const & pointer = {})
- : root_(uri, anchor), pointer_(pointer) {}
- explicit Reference(RootReference const & root, Pointer const & pointer = {})
- : root_(root), pointer_(pointer) {}
- explicit Reference(std::string_view ref) {
- size_t pointer_start = 0;
- root_ = RootReference(ref, pointer_start);
- if (pointer_start != std::string::npos) {
- pointer_ = ref.substr(pointer_start);
- }
- }
- URI const & uri() const { return root_.uri(); }
- Anchor const & anchor() const { return root_.anchor(); }
- Pointer const & pointer() const { return pointer_; }
- RootReference const & root() const { return root_; }
- Reference parent() const { return Reference(root_, 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.root_ << self.pointer_;
- }
- auto operator<=>(Reference const &) const = default;
- };
- }
|