// // json_tuple_binder.hpp // json // // Created by Sam Jaffe on 4/23/16. // #pragma once namespace json { namespace binder { template class tuple_binder : public binder_impl { public: virtual binder_impl* clone() const override { return new tuple_binder(*this); } tuple_binder& operator()(binder const&b) { members.push_back(b); return *this; } virtual void parse(T& object, char const*& data, parser::options opts) const override { const char ch = json::helper::get_next_element(data); if (ch == '[') { parse_tuple(object, ++data, opts); } else { throw json::malformed_json_exception(std::string("Expected an array type for binding to ") + typeid(T).name()); } } virtual void write(T const& val, std::ostream & data) const override { data << '['; typename std::vector>::const_iterator it = members.begin(), end = members.end(); if (it != end) { it->write(val, data); for (++it; it != end; ++it) { data << ','; it->write(val, data); } } data << ']'; } void parse_tuple(T& object, char const*& data, parser::options opts) const { auto it = members.begin(); while (*data && *data != ']' && it != members.end()) { it->parse(object, data, opts); json::helper::advance_to_boundary(']', data); ++it; } if (it != members.end()) { throw json::malformed_json_exception("Failed to parse every member of tuple"); } if (*data != ']') throw json::malformed_json_exception("Parsed every tuple element, but did not reach end"); else if (*data) ++data; else throw json::unterminated_json_exception("Reached end of parse string without finding array end"); } template tuple_binder& operator()(E T::*p) { return operator()(binder(new direct_binder(p))); } private: std::vector> members; }; } }