reference.h 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #pragma once
  2. #include <string>
  3. #include <string_view>
  4. #include <jvalidate/detail/expect.h>
  5. #include <jvalidate/detail/pointer.h>
  6. namespace jvalidate::detail {
  7. class Reference {
  8. public:
  9. Reference() = default;
  10. Reference(std::string const & anchor, Pointer const & pointer)
  11. : anchor_(anchor), pointer_(pointer) {}
  12. Reference(std::string_view fragment, bool allow_anchor = true) {
  13. EXPECT_M(fragment.find('#') != std::string::npos, "Reference requires a fragment token '#'");
  14. size_t const index = fragment.find('/');
  15. anchor_ = std::string(fragment.substr(0, index));
  16. EXPECT_M(allow_anchor && anchor_.back() == '#', "Anchoring is not allowed in this context");
  17. if (index != std::string::npos) {
  18. pointer_ = fragment.substr(index + 1);
  19. }
  20. }
  21. std::string const & anchor() const { return anchor_; }
  22. Pointer const & pointer() const { return pointer_; }
  23. Reference parent() const { return {anchor_, pointer_.parent()}; }
  24. Reference & operator/=(Pointer const & relative) {
  25. pointer_ /= relative;
  26. return *this;
  27. }
  28. Reference operator/(Pointer const & relative) const { return Reference(*this) /= relative; }
  29. Reference & operator/=(std::string_view key) {
  30. pointer_ /= key;
  31. return *this;
  32. }
  33. Reference operator/(std::string_view key) const { return Reference(*this) /= key; }
  34. Reference & operator/=(size_t index) {
  35. pointer_ /= index;
  36. return *this;
  37. }
  38. Reference operator/(size_t index) const { return Reference(*this) /= index; }
  39. friend std::ostream & operator<<(std::ostream & os, Reference const & self) {
  40. return os << self.anchor_ << self.pointer_;
  41. }
  42. auto operator<=>(Reference const &) const = default;
  43. private:
  44. std::string anchor_;
  45. Pointer pointer_;
  46. };
  47. }