json_direct_get_binder.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. //
  2. // json_direct_tuple_binder.hpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 2/26/17.
  6. //
  7. #pragma once
  8. #include "json_binder.hpp"
  9. #include "json_direct_binder.hpp"
  10. #include "json_tuple_binder.hpp"
  11. #include <array>
  12. #include <tuple>
  13. namespace json { namespace binder {
  14. template <typename T, std::size_t I>
  15. class get_binder : public binder_impl<T> {
  16. // Maybe a reference type
  17. using ith_type = decltype(std::get<I>(std::declval<T>()));
  18. public:
  19. using value_type = typename std::remove_reference<ith_type>::type;
  20. get_binder() : impl(value_binder<value_type>()) {}
  21. get_binder(binder<value_type> val_binder) : impl(std::move(val_binder)) {}
  22. get_binder(binder_impl<value_type> const & val_binder) : impl(val_binder) {}
  23. virtual binder_impl<T> * clone() const override {
  24. return new get_binder(*this);
  25. }
  26. virtual void parse(T & object, char const *& data,
  27. parser::options opts) const override {
  28. impl.parse(std::get<I>(object), data, opts);
  29. }
  30. virtual void write(T const & val, std::ostream & data) const override {
  31. impl.write(std::get<I>(val), data);
  32. }
  33. private:
  34. binder<value_type> impl;
  35. };
  36. #if __cpluscplus >= 201402L
  37. namespace detail {
  38. template <typename TupleOut, typename TupleIn, std::size_t... Indexes>
  39. tuple_binder<TupleOut> make_tuple_binder(TupleIn && binds,
  40. std::index_sequence<Indexes...>) {
  41. tuple_binder<TupleOut> binder;
  42. using swallow = int[];
  43. (void)swallow{0, (void(binder(get_binder<TupleOut, Indexes>(
  44. std::get<Indexes>(binds)))),
  45. 0)...};
  46. return binder;
  47. }
  48. template <typename TupleOut, typename T, std::size_t... Indexes>
  49. tuple_binder<TupleOut> make_array_binder(binder<T> && binds,
  50. std::index_sequence<Indexes...>) {
  51. tuple_binder<TupleOut> binder;
  52. using swallow = int[];
  53. (void)swallow{0,
  54. (void(binder(get_binder<TupleOut, Indexes>(binds))), 0)...};
  55. return binder;
  56. }
  57. }
  58. template <typename... Ts>
  59. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
  60. return detail::make_tuple_binder<std::tuple<Ts...>>(
  61. std::make_tuple(binds...), std::make_index_sequence<sizeof...(Ts)>());
  62. }
  63. template <typename... Ts>
  64. tuple_binder<std::tuple<Ts...>>
  65. make_tuple_binder(binder_impl<Ts> &&... binds) {
  66. return detail::make_tuple_binder<std::tuple<Ts...>>(
  67. std::make_tuple(binder<Ts>(binds)...),
  68. std::make_index_sequence<sizeof...(Ts)>());
  69. }
  70. template <typename... Ts>
  71. tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
  72. return detail::make_tuple_binder<std::tuple<Ts...>>(
  73. std::make_tuple(binder<Ts>(value_binder<Ts>())...),
  74. std::make_index_sequence<sizeof...(Ts)>());
  75. }
  76. template <typename T, std::size_t N>
  77. tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
  78. return detail::make_array_binder<std::array<T, N>>(
  79. binds, std::make_index_sequence<N>());
  80. }
  81. template <typename T, std::size_t N>
  82. tuple_binder<std::array<T, N>>
  83. make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
  84. return detail::make_array_binder<std::array<T, N>>(
  85. binder<T>(binds), std::make_index_sequence<N>());
  86. }
  87. #else
  88. namespace detail {
  89. template <std::size_t> struct tuple_binder_helper;
  90. template <> struct tuple_binder_helper<0> {
  91. template <typename BindOut>
  92. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind) const {
  93. return bind;
  94. }
  95. };
  96. template <std::size_t N> struct tuple_binder_helper {
  97. template <typename BindOut, typename BindIn, typename... Ts>
  98. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
  99. BindIn && ith,
  100. Ts &&... binders) const {
  101. constexpr auto get_index = std::tuple_size<BindOut>::value - N;
  102. using get_binder_t = get_binder<BindOut, get_index>;
  103. return tuple_binder_helper<N - 1>()(
  104. bind(get_binder_t(std::forward<BindIn>(ith))),
  105. std::forward<Ts>(binders)...);
  106. }
  107. };
  108. template <std::size_t> struct array_binder_helper;
  109. template <> struct array_binder_helper<1> {
  110. template <typename BindOut, typename BindIn>
  111. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
  112. BindIn &&) const {
  113. return bind;
  114. }
  115. };
  116. template <std::size_t N> struct array_binder_helper {
  117. template <typename BindOut, typename BindIn>
  118. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
  119. BindIn && ith) const {
  120. return array_binder_helper<N - 1>()(
  121. bind(get_binder<BindOut, N - 1>(ith)), std::forward<BindIn>(ith));
  122. }
  123. };
  124. }
  125. template <typename... Ts>
  126. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
  127. tuple_binder<std::tuple<Ts...>> binder;
  128. return detail::tuple_binder_helper<sizeof...(Ts)>()(
  129. binder, std::forward<Ts>(binds)...);
  130. }
  131. template <typename... Ts>
  132. tuple_binder<std::tuple<Ts...>>
  133. make_tuple_binder(binder_impl<Ts> &&... binds) {
  134. tuple_binder<std::tuple<Ts...>> binder;
  135. return detail::tuple_binder_helper<sizeof...(Ts)>()(
  136. binder, json::binder::binder<Ts>(binds)...);
  137. }
  138. template <typename... Ts>
  139. tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
  140. tuple_binder<std::tuple<Ts...>> binder;
  141. return detail::tuple_binder_helper<sizeof...(Ts)>()(
  142. binder, json::binder::binder<Ts>(value_binder<Ts>())...);
  143. }
  144. template <typename T, std::size_t N>
  145. tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
  146. tuple_binder<std::array<T, N>> binder;
  147. return detail::array_binder_helper<N>(binder, binds);
  148. }
  149. template <typename T, std::size_t N>
  150. tuple_binder<std::array<T, N>>
  151. make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
  152. tuple_binder<std::array<T, N>> binder;
  153. return detail::array_binder_helper<N>(binder,
  154. json::binder::binder<T>(binds));
  155. }
  156. #endif
  157. }}