json_direct_get_binder.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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)
  22. : impl(std::move(val_binder)) {}
  23. get_binder(binder_impl<value_type> const & val_binder)
  24. : impl(val_binder) {}
  25. virtual binder_impl<T>* clone() const override {
  26. return new get_binder(*this);
  27. }
  28. virtual void parse(T& object, char const*& data,
  29. parser::options opts) const override {
  30. impl.parse(std::get<I>(object), data, opts);
  31. }
  32. virtual void write(T const& val, std::ostream & data) const override {
  33. impl.write(std::get<I>(val), data);
  34. }
  35. private:
  36. binder<value_type> impl;
  37. };
  38. #if __cpluscplus >= 201402L
  39. namespace detail {
  40. template <typename TupleOut, typename TupleIn, std::size_t... Indexes>
  41. tuple_binder<TupleOut> make_tuple_binder(TupleIn && binds,
  42. std::index_sequence<Indexes...>) {
  43. tuple_binder<TupleOut> binder;
  44. using swallow = int[];
  45. (void) swallow{
  46. 0,
  47. (void(binder(get_binder<TupleOut, Indexes>(std::get<Indexes>(binds)))),
  48. 0)...
  49. };
  50. return binder;
  51. }
  52. template <typename TupleOut, typename T, std::size_t... Indexes>
  53. tuple_binder<TupleOut> make_array_binder(binder<T> && binds,
  54. std::index_sequence<Indexes...>) {
  55. tuple_binder<TupleOut> binder;
  56. using swallow = int[];
  57. (void) swallow{
  58. 0,
  59. (void(binder(get_binder<TupleOut, Indexes>(binds))), 0)...
  60. };
  61. return binder;
  62. }
  63. }
  64. template <typename... Ts>
  65. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
  66. return detail::make_tuple_binder<std::tuple<Ts...>>
  67. (std::make_tuple(binds...),
  68. std::make_index_sequence<sizeof...(Ts)>());
  69. }
  70. template <typename... Ts>
  71. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder_impl<Ts> &&... binds) {
  72. return detail::make_tuple_binder<std::tuple<Ts...>>
  73. (std::make_tuple(binder<Ts>(binds)...),
  74. std::make_index_sequence<sizeof...(Ts)>());
  75. }
  76. template <typename... Ts>
  77. tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
  78. return detail::make_tuple_binder<std::tuple<Ts...>>
  79. (std::make_tuple(binder<Ts>(value_binder<Ts>())...),
  80. std::make_index_sequence<sizeof...(Ts)>());
  81. }
  82. template <typename T, std::size_t N>
  83. tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
  84. return detail::make_array_binder<std::array<T, N>>
  85. (binds, std::make_index_sequence<N>());
  86. }
  87. template <typename T, std::size_t N>
  88. tuple_binder<std::array<T, N>> make_array_binder(binder_impl<T> const & binds
  89. = value_binder<T>()) {
  90. return detail::make_array_binder<std::array<T, N>>
  91. (binder<T>(binds), std::make_index_sequence<N>());
  92. }
  93. #else
  94. namespace detail {
  95. template <std::size_t> struct tuple_binder_helper;
  96. template <>
  97. struct tuple_binder_helper<0> {
  98. template <typename BindOut>
  99. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind) const {
  100. return bind;
  101. }
  102. };
  103. template <std::size_t N>
  104. struct tuple_binder_helper {
  105. template <typename BindOut, typename BindIn, typename... Ts>
  106. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
  107. BindIn && ith,
  108. Ts &&... binders) const {
  109. constexpr auto get_index = std::tuple_size<BindOut>::value-N;
  110. using get_binder_t = get_binder<BindOut, get_index>;
  111. return tuple_binder_helper<N-1>()
  112. (bind(get_binder_t(std::forward<BindIn>(ith))),
  113. std::forward<Ts>(binders)...);
  114. }
  115. };
  116. template <std::size_t> struct array_binder_helper;
  117. template <>
  118. struct array_binder_helper<1> {
  119. template <typename BindOut, typename BindIn>
  120. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
  121. BindIn &&) const {
  122. return bind;
  123. }
  124. };
  125. template <std::size_t N>
  126. struct array_binder_helper {
  127. template <typename BindOut, typename BindIn>
  128. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
  129. BindIn && ith) const {
  130. return array_binder_helper<N-1>()(bind(get_binder<BindOut, N-1>(ith)),
  131. std::forward<BindIn>(ith));
  132. }
  133. };
  134. }
  135. template <typename... Ts>
  136. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
  137. tuple_binder<std::tuple<Ts...>> binder;
  138. return detail::tuple_binder_helper<sizeof...(Ts)>()
  139. (binder, std::forward<Ts>(binds)...);
  140. }
  141. template <typename... Ts>
  142. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder_impl<Ts> &&... binds) {
  143. tuple_binder<std::tuple<Ts...>> binder;
  144. return detail::tuple_binder_helper<sizeof...(Ts)>()
  145. (binder, json::binder::binder<Ts>(binds)...);
  146. }
  147. template <typename... Ts>
  148. tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
  149. tuple_binder<std::tuple<Ts...>> binder;
  150. return detail::tuple_binder_helper<sizeof...(Ts)>()
  151. (binder, json::binder::binder<Ts>(value_binder<Ts>())...);
  152. }
  153. template <typename T, std::size_t N>
  154. tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
  155. tuple_binder<std::array<T, N>> binder;
  156. return detail::array_binder_helper<N>(binder, binds);
  157. }
  158. template <typename T, std::size_t N>
  159. tuple_binder<std::array<T, N>> make_array_binder(binder_impl<T> const & binds
  160. = value_binder<T>()) {
  161. tuple_binder<std::array<T, N>> binder;
  162. return detail::array_binder_helper<N>(binder,
  163. json::binder::binder<T>(binds));
  164. }
  165. #endif
  166. } }