| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- //
- // json_direct_map_binder.hpp
- // json
- //
- // Created by Sam Jaffe on 4/23/16.
- //
- #pragma once
- namespace json { namespace binder {
- template <typename T, typename V, typename C>
- class associative_binder : public binder_impl<T> {
- public:
- associative_binder(C T::*p) : ptr(p), impl(value_binder<V>()) {}
- associative_binder(C T::*p, binder<V> const & i) : ptr(p), impl(i) {}
- virtual binder_impl<T>* clone() const override { return new associative_binder(*this); }
-
- virtual void parse(T& val, char const*& data, parser::options opts) const override {
- const char ch = json::helper::get_next_element(data);
- if (ch != '{') {
- throw json::malformed_json_exception("Expected an object type");
- }
- ++data;
-
- V to_make;
- C & map = val.*ptr;
- std::string key;
- while (*data && *data != '}') {
- json::helper::parse_string(key, data);
- if (json::helper::get_next_element(data) != ':') {
- throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
- }
- impl.parse(to_make, ++data, opts);
- map.emplace(key, std::move(to_make));
- json::helper::advance_to_boundary('}', data);
- }
- if (*data) ++data;
- else throw json::unterminated_json_exception("Reached end of parse string without finding object end");
- }
-
- virtual void write(T const& val, std::ostream & data) const override {
- data << '{';
- std::map<std::string, V> const & map = val.*ptr;
- typename std::map<std::string, V>::const_iterator it = map.begin(), end = map.end();
- if (it != end) {
- data << '"' << it->first << '"' << ':';
- impl.write(it->second, data);
- for (++it; it != end; ++it) {
- data << ',';
- data << '"' << it->first << '"' << ':';
- impl.write(it->second, data);
- }
- }
- data << '}';
- }
- private:
- std::map<std::string, V> T::*ptr;
- binder<V> impl;
- };
-
- #define ASSOCIATIVE_DIRECT_BINDER( C ) \
- template <typename T, typename V, typename... O> \
- class direct_binder<T, C<std::string, V, O...> > : \
- public associative_binder<T, V, C<std::string, V, O...>> { \
- public: \
- using associative_binder<T, V, C<std::string, V, O...>>::associative_binder; \
- }
- ASSOCIATIVE_DIRECT_BINDER( std::map );
- // ASSOCIATIVE_DIRECT_BINDER( std::unordered_map );
- } }
|