reference.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #pragma once
  2. #include <string>
  3. #include <string_view>
  4. #include <jvalidate/detail/anchor.h>
  5. #include <jvalidate/detail/expect.h>
  6. #include <jvalidate/detail/out.h>
  7. #include <jvalidate/detail/pointer.h>
  8. #include <jvalidate/uri.h>
  9. namespace jvalidate::detail {
  10. class Reference;
  11. class RootReference {
  12. private:
  13. friend class Reference;
  14. URI uri_;
  15. Anchor anchor_;
  16. public:
  17. RootReference() = default;
  18. explicit RootReference(URI const & uri, Anchor const & anchor = {})
  19. : uri_(uri), anchor_(anchor) {}
  20. explicit RootReference(std::string_view ref) : RootReference(ref, discard_out) {}
  21. bool is_relative() const { return uri_.is_relative(); }
  22. URI const & uri() const { return uri_; }
  23. Anchor const & anchor() const { return anchor_; }
  24. friend std::ostream & operator<<(std::ostream & os, RootReference const & self) {
  25. return os << self.uri_ << '#' << self.anchor_;
  26. }
  27. auto operator<=>(RootReference const &) const = default;
  28. private:
  29. RootReference(std::string_view ref, out<size_t> end) {
  30. end = std::string::npos;
  31. size_t end_of_uri = ref.find('#');
  32. uri_ = URI(ref.substr(0, end_of_uri));
  33. if (end_of_uri == std::string::npos) {
  34. return;
  35. }
  36. ref.remove_prefix(end_of_uri + 1);
  37. size_t const pointer_start = ref.find('/');
  38. anchor_ = Anchor(ref.substr(0, pointer_start));
  39. EXPECT_M(end || pointer_start == std::string::npos, "JSON-Pointer is illegal in this context");
  40. if (pointer_start != std::string::npos) {
  41. end = pointer_start + end_of_uri + 1;
  42. }
  43. }
  44. };
  45. class Reference {
  46. private:
  47. RootReference root_;
  48. Pointer pointer_;
  49. public:
  50. Reference() = default;
  51. explicit Reference(URI const & uri, Pointer const & pointer = {})
  52. : root_(uri), pointer_(pointer) {}
  53. explicit Reference(URI const & uri, Anchor const & anchor, Pointer const & pointer = {})
  54. : root_(uri, anchor), pointer_(pointer) {}
  55. explicit Reference(RootReference const & root, Pointer const & pointer = {})
  56. : root_(root), pointer_(pointer) {}
  57. explicit Reference(std::string_view ref) {
  58. size_t pointer_start = 0;
  59. root_ = RootReference(ref, pointer_start);
  60. if (pointer_start != std::string::npos) {
  61. pointer_ = ref.substr(pointer_start);
  62. }
  63. }
  64. URI const & uri() const { return root_.uri(); }
  65. Anchor const & anchor() const { return root_.anchor(); }
  66. Pointer const & pointer() const { return pointer_; }
  67. RootReference const & root() const { return root_; }
  68. Reference parent() const { return Reference(root_, pointer_.parent()); }
  69. Reference & operator/=(Pointer const & relative) {
  70. pointer_ /= relative;
  71. return *this;
  72. }
  73. Reference operator/(Pointer const & relative) const { return Reference(*this) /= relative; }
  74. Reference & operator/=(std::string_view key) {
  75. pointer_ /= key;
  76. return *this;
  77. }
  78. Reference operator/(std::string_view key) const { return Reference(*this) /= key; }
  79. Reference & operator/=(size_t index) {
  80. pointer_ /= index;
  81. return *this;
  82. }
  83. Reference operator/(size_t index) const { return Reference(*this) /= index; }
  84. friend std::ostream & operator<<(std::ostream & os, Reference const & self) {
  85. return os << self.root_ << self.pointer_;
  86. }
  87. auto operator<=>(Reference const &) const = default;
  88. };
  89. }