simple_adapter.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #pragma once
  2. #include <unordered_map>
  3. #include <vector>
  4. #include <jvalidate/adapter.h>
  5. #include <jvalidate/detail/array_iterator.h>
  6. #include <jvalidate/detail/object_iterator.h>
  7. #include <jvalidate/forward.h>
  8. namespace jvalidate::adapter::detail {
  9. template <typename JSON, typename Adapter = AdapterFor<JSON>> class SimpleObjectAdapter {
  10. public:
  11. using underlying_iterator_t = decltype(std::declval<JSON>().begin());
  12. using const_iterator = JsonObjectIterator<underlying_iterator_t, Adapter>;
  13. SimpleObjectAdapter(JSON * value) : value_(value) {}
  14. size_t size() const { return value_ ? value_->size() : 0; }
  15. const_iterator find(std::string const & key) const {
  16. return std::find_if(begin(), end(), [key](auto const & kv) { return kv.first == key; });
  17. }
  18. bool contains(std::string const & key) const { return find(key) != end(); }
  19. Adapter operator[](std::string const & key) const {
  20. auto it = find(key);
  21. return it != end() ? it->second : Adapter();
  22. }
  23. const_iterator begin() const {
  24. return value_ ? const_iterator(value_->begin()) : const_iterator();
  25. }
  26. const_iterator end() const { return value_ ? const_iterator(value_->end()) : const_iterator(); }
  27. std::map<std::string_view, Adapter> operator*() const {
  28. using C = std::map<std::string_view, Adapter>;
  29. return value_ ? C(begin(), end()) : C();
  30. }
  31. protected:
  32. JSON * value() const { return value_; }
  33. JSON const & const_value() const { return value_ ? *value_ : AdapterTraits<JSON>::const_empty(); }
  34. private:
  35. JSON * value_;
  36. };
  37. template <typename JSON, typename Adapter = AdapterFor<JSON>> class SimpleArrayAdapter {
  38. public:
  39. using underlying_iterator_t = decltype(std::declval<JSON>().begin());
  40. using const_iterator = JsonArrayIterator<underlying_iterator_t, Adapter>;
  41. SimpleArrayAdapter(JSON * value) : value_(value) {}
  42. size_t size() const { return value_ ? value_->size() : 0; }
  43. Adapter operator[](size_t index) const {
  44. if (index > size()) {
  45. return Adapter();
  46. }
  47. auto it = begin();
  48. std::advance(it, index);
  49. return *it;
  50. }
  51. const_iterator begin() const {
  52. return value_ ? const_iterator(value_->begin()) : const_iterator();
  53. }
  54. const_iterator end() const { return value_ ? const_iterator(value_->end()) : const_iterator(); }
  55. std::vector<Adapter> operator*() const {
  56. using C = std::vector<Adapter>;
  57. return value_ ? C(begin(), end()) : C();
  58. }
  59. protected:
  60. JSON * value() const { return value_; }
  61. JSON const & const_value() const { return value_ ? *value_ : AdapterTraits<JSON>::const_empty(); }
  62. private:
  63. JSON * value_;
  64. };
  65. template <typename JSON, typename CRTP = AdapterFor<JSON>> class SimpleAdapter : public Adapter {
  66. public:
  67. using value_type = std::remove_const_t<JSON>;
  68. public:
  69. SimpleAdapter(JSON * value = nullptr) : value_(value) {}
  70. SimpleAdapter(JSON & value) : value_(&value) {}
  71. size_t array_size() const final { return self().as_array().size(); }
  72. CRTP operator[](size_t index) const { return self().as_array()[index]; }
  73. detail::SimpleArrayAdapter<JSON> as_array() const { return value_; }
  74. Status apply_array(AdapterCallback const & cb) const final {
  75. Status result = Status::Noop;
  76. for (auto const & child : self().as_array()) {
  77. result = cb(child) & result;
  78. }
  79. return result;
  80. }
  81. size_t object_size() const final { return self().as_object().size(); }
  82. bool contains(std::string const & key) const { return self().as_object().contains(key); }
  83. CRTP operator[](std::string const & key) const { return self().as_object()[key]; }
  84. detail::SimpleObjectAdapter<JSON, CRTP> as_object() const { return value_; }
  85. Status apply_object(ObjectAdapterCallback const & cb) const final {
  86. Status result = Status::Noop;
  87. for (auto const & [key, child] : self().as_object()) {
  88. result = cb(key, child) & result;
  89. }
  90. return result;
  91. }
  92. std::unique_ptr<Const const> freeze() const final {
  93. return std::make_unique<GenericConst<value_type>>(const_value());
  94. }
  95. auto operator<=>(SimpleAdapter const & rhs) const requires std::totally_ordered<JSON> {
  96. using ord = std::strong_ordering;
  97. if (value_ == rhs.value_) {
  98. return ord::equal;
  99. }
  100. if (value_ && rhs.value_) {
  101. if (*value_ < *rhs.value_) {
  102. return ord::less;
  103. }
  104. if (*rhs.value_ < *value_) {
  105. return ord::greater;
  106. }
  107. return ord::equal;
  108. }
  109. if (value_) {
  110. return type() == Type::Null ? ord::equivalent : ord::greater;
  111. }
  112. return rhs.type() == Type::Null ? ord::equivalent : ord::less;
  113. }
  114. bool equals(Adapter const & rhs, bool strict = false) const final {
  115. Type const rhs_type = rhs.type();
  116. if (strict && rhs_type != type()) {
  117. return false;
  118. }
  119. // TODO(samjaffe): Needs type coercion
  120. switch (rhs_type) {
  121. case Type::Null:
  122. return const_value().isNull();
  123. case Type::Boolean:
  124. return rhs.as_boolean() == as_boolean();
  125. case Type::Integer:
  126. return rhs.as_integer() == as_integer();
  127. case Type::Number:
  128. return rhs.as_number() == as_number();
  129. case Type::String:
  130. return rhs.as_string() == as_string();
  131. case Type::Array: {
  132. auto array = this->as_array();
  133. if (rhs.array_size() != array.size()) {
  134. return false;
  135. }
  136. bool rval = true;
  137. size_t index = 0;
  138. rhs.apply_array([&, this](adapter::Adapter const & elem) {
  139. // Short-Circuit OK
  140. rval = rval && array[index].equals(elem, strict);
  141. ++index;
  142. return Status::Accept;
  143. });
  144. return rval;
  145. }
  146. case Type::Object: {
  147. auto object = this->as_object();
  148. if (rhs.object_size() != object.size()) {
  149. return false;
  150. }
  151. bool rval = true;
  152. rhs.apply_object([&, this](std::string const & key, adapter::Adapter const & elem) {
  153. // Short-Circuit OK
  154. rval = rval && object.contains(key) && object[key].equals(elem, strict);
  155. return Status::Accept;
  156. });
  157. return rval;
  158. }
  159. }
  160. }
  161. protected:
  162. JSON * value() const { return value_; }
  163. JSON const & const_value() const { return value_ ? *value_ : AdapterTraits<JSON>::const_empty(); }
  164. private:
  165. CRTP const & self() const { return static_cast<CRTP const &>(*this); }
  166. private:
  167. JSON * value_;
  168. };
  169. }