json_direct_vector_binder.hpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. //
  2. // json_direct_vector_binder.hpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 4/23/16.
  6. //
  7. #pragma once
  8. #include "json_binder.hpp"
  9. #include "json_direct_binder.hpp"
  10. #include <list>
  11. #include <set>
  12. #include <vector>
  13. namespace json { namespace binder {
  14. template <typename T, typename V, typename C>
  15. class non_associative_binder : public binder_impl<T> {
  16. public:
  17. non_associative_binder(C T::*p) : ptr(p), impl(value_binder<V>()) {}
  18. non_associative_binder(C T::*p, binder<V> const & i) : ptr(p), impl(i) {}
  19. virtual binder_impl<T> * clone() const override {
  20. return new non_associative_binder(*this);
  21. }
  22. virtual void parse(T & val, char const *& data,
  23. parser::options opts) const override {
  24. const char ch = json::helper::get_next_element(data);
  25. if (ch != '[') { throw not_an_array_exception(val); }
  26. ++data;
  27. V to_make;
  28. C & vec = val.*ptr;
  29. while (*data && *data != ']') {
  30. impl.parse(to_make, data, opts);
  31. vec.emplace_back(to_make);
  32. json::helper::advance_to_boundary(']', data);
  33. }
  34. if (*data)
  35. ++data;
  36. else
  37. throw unterminated_json_array();
  38. }
  39. virtual void write(T const & val, std::ostream & data) const override {
  40. data << '[';
  41. std::vector<V> const & vec = val.*ptr;
  42. auto it = vec.begin(), end = vec.end();
  43. if (it != end) {
  44. impl.write(*it, data);
  45. for (++it; it != end; ++it) {
  46. data << ",";
  47. impl.write(*it, data);
  48. }
  49. }
  50. data << ']';
  51. }
  52. private:
  53. std::vector<V> T::*ptr;
  54. binder<V> impl;
  55. };
  56. #define NON_ASSOCIATIVE_DIRECT_BINDER(C) \
  57. template <typename T, typename V, typename... O> \
  58. class direct_binder<T, C<V, O...>> \
  59. : public non_associative_binder<T, V, C<V, O...>> { \
  60. public: \
  61. using non_associative_binder<T, V, C<V, O...>>::non_associative_binder; \
  62. }
  63. NON_ASSOCIATIVE_DIRECT_BINDER(std::vector);
  64. NON_ASSOCIATIVE_DIRECT_BINDER(std::list);
  65. NON_ASSOCIATIVE_DIRECT_BINDER(std::set);
  66. // NON_ASSOCIATIVE_DIRECT_BINDER( std::unordered_set );
  67. }}