#pragma once #include #include #include #include #include #include namespace jvalidate::adapter::detail { template > class SimpleObjectAdapter { public: using underlying_iterator_t = decltype(std::declval().begin()); using const_iterator = JsonObjectIterator; SimpleObjectAdapter(JSON * value) : value_(value) {} size_t size() const { return value_ ? value_->size() : 0; } const_iterator find(std::string const & key) const { return std::find_if(begin(), end(), [key](auto const & kv) { return kv.first == key; }); } bool contains(std::string const & key) const { return find(key) != end(); } Adapter operator[](std::string const & key) const { auto it = find(key); return it != end() ? it->second : Adapter(); } const_iterator begin() const { return value_ ? const_iterator(value_->begin()) : const_iterator(); } const_iterator end() const { return value_ ? const_iterator(value_->end()) : const_iterator(); } std::map operator*() const { using C = std::map; return value_ ? C(begin(), end()) : C(); } protected: JSON * value() const { return value_; } JSON const & const_value() const { return value_ ? *value_ : AdapterTraits::const_empty(); } private: JSON * value_; }; template > class SimpleArrayAdapter { public: using underlying_iterator_t = decltype(std::declval().begin()); using const_iterator = JsonArrayIterator; SimpleArrayAdapter(JSON * value) : value_(value) {} size_t size() const { return value_ ? value_->size() : 0; } Adapter operator[](size_t index) const { if (index > size()) { return Adapter(); } auto it = begin(); std::advance(it, index); return *it; } const_iterator begin() const { return value_ ? const_iterator(value_->begin()) : const_iterator(); } const_iterator end() const { return value_ ? const_iterator(value_->end()) : const_iterator(); } std::vector operator*() const { using C = std::vector; return value_ ? C(begin(), end()) : C(); } protected: JSON * value() const { return value_; } JSON const & const_value() const { return value_ ? *value_ : AdapterTraits::const_empty(); } private: JSON * value_; }; template > class SimpleAdapter : public Adapter { public: using value_type = std::remove_const_t; public: SimpleAdapter(JSON * value) : value_(value) {} SimpleAdapter(JSON & value) : value_(&value) {} size_t array_size() const { return self().as_array().size(); } CRTP operator[](size_t index) const { return self().as_array()[index]; } detail::SimpleArrayAdapter as_array() const { return value_; } bool apply_array(AdapterCallback const & cb) const final { bool result = true; for (auto const & child : self().as_array()) { result = cb(child) && result; } return result; } size_t object_size() const { return self().as_object().size(); } bool contains(std::string const & key) const { return self().as_object().contains(key); } CRTP operator[](std::string const & key) const { return self().as_object()[key]; } detail::SimpleObjectAdapter as_object() const { return value_; } bool apply_object(ObjectAdapterCallback const & cb) const final { bool result = true; for (auto const & [key, child] : self().as_object()) { result = cb(key, child) && result; } return result; } std::unique_ptr freeze() const final { return std::make_unique>(const_value()); } protected: JSON * value() const { return value_; } JSON const & const_value() const { return value_ ? *value_ : AdapterTraits::const_empty(); } private: CRTP const & self() const { return static_cast(*this); } private: JSON * value_; }; }