json_direct_get_binder.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 <tuple>
  9. namespace json { namespace binder {
  10. template <typename T, std::size_t I>
  11. class get_binder : public binder_impl<T> {
  12. public:
  13. using value_type = typename std::remove_reference<decltype(std::get<I>(std::declval<T>()))>::type;
  14. get_binder(binder<value_type> val_binder)
  15. : impl(std::move(val_binder)) {
  16. }
  17. get_binder(binder_impl<value_type> const & val_binder = value_binder<value_type>())
  18. : impl(val_binder) {
  19. }
  20. virtual binder_impl<T>* clone() const override { return new get_binder(*this); }
  21. virtual void parse(T& object, char const*& data, parser::options opts) const override {
  22. impl.parse(std::get<I>(object), data, opts);
  23. }
  24. virtual void write(T const& val, std::ostream & data) const override {
  25. impl.write(std::get<I>(val), data);
  26. }
  27. private:
  28. binder<value_type> impl;
  29. };
  30. #if __cpluscplus >= 201402L
  31. namespace detail {
  32. template <typename TupleOut, typename TupleIn, std::size_t... Indexes>
  33. tuple_binder<TupleOut> make_tuple_binder(TupleIn && binds, std::index_sequence<Indexes...>) {
  34. tuple_binder<TupleOut> binder;
  35. using swallow = int[];
  36. (void) swallow{ 0, (void(binder(get_binder<TupleOut, Indexes>(std::get<Indexes>(binds)))), 0)... };
  37. return binder;
  38. }
  39. template <typename TupleOut, typename T, std::size_t... Indexes>
  40. tuple_binder<TupleOut> make_array_binder(binder<T> && binds, std::index_sequence<Indexes...>) {
  41. tuple_binder<TupleOut> binder;
  42. using swallow = int[];
  43. (void) swallow{ 0, (void(binder(get_binder<TupleOut, Indexes>(binds))), 0)... };
  44. return binder;
  45. }
  46. }
  47. template <typename... Ts>
  48. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
  49. return detail::make_tuple_binder<std::tuple<Ts...>>(std::make_tuple(binds...), std::make_index_sequence<sizeof...(Ts)>());
  50. }
  51. template <typename... Ts>
  52. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder_impl<Ts> &&... binds) {
  53. return detail::make_tuple_binder<std::tuple<Ts...>>(std::make_tuple(binder<Ts>(binds)...), std::make_index_sequence<sizeof...(Ts)>());
  54. }
  55. template <typename... Ts>
  56. tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
  57. return detail::make_tuple_binder<std::tuple<Ts...>>(std::make_tuple(binder<Ts>(value_binder<Ts>())...), std::make_index_sequence<sizeof...(Ts)>());
  58. }
  59. template <typename T, std::size_t N>
  60. tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
  61. return detail::make_array_binder<std::array<T, N>>(binds, std::make_index_sequence<N>());
  62. }
  63. template <typename T, std::size_t N>
  64. tuple_binder<std::array<T, N>> make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
  65. return detail::make_array_binder<std::array<T, N>>(binder<T>(binds), std::make_index_sequence<N>());
  66. }
  67. #else
  68. namespace detail {
  69. template <std::size_t> struct tuple_binder_helper;
  70. template <>
  71. struct tuple_binder_helper<0> {
  72. template <typename BindOut>
  73. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind) const { return bind; }
  74. };
  75. template <std::size_t N>
  76. struct tuple_binder_helper {
  77. template <typename BindOut, typename BindIn, typename... Ts>
  78. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind, BindIn && ith, Ts &&... binders) const {
  79. using get_binder_t = get_binder<BindOut, std::tuple_size<BindOut>::value-N>;
  80. return tuple_binder_helper<N-1>()(bind(get_binder_t(std::forward<BindIn>(ith))),
  81. std::forward<Ts>(binders)...);
  82. }
  83. };
  84. template <std::size_t> struct array_binder_helper;
  85. template <>
  86. struct array_binder_helper<1> {
  87. template <typename BindOut, typename BindIn>
  88. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind, BindIn &&) const { return bind; }
  89. };
  90. template <std::size_t N>
  91. struct array_binder_helper {
  92. template <typename BindOut, typename BindIn>
  93. tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind, BindIn && ith) const {
  94. return array_binder_helper<N-1>()(bind(get_binder<BindOut, N-1>(ith)), std::forward<BindIn>(ith));
  95. }
  96. };
  97. }
  98. template <typename... Ts>
  99. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
  100. tuple_binder<std::tuple<Ts...>> binder;
  101. return detail::tuple_binder_helper<sizeof...(Ts)>()(binder, std::forward<Ts>(binds)...);
  102. }
  103. template <typename... Ts>
  104. tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder_impl<Ts> &&... binds) {
  105. tuple_binder<std::tuple<Ts...>> binder;
  106. return detail::tuple_binder_helper<sizeof...(Ts)>()(binder, json::binder::binder<Ts>(binds)...);
  107. }
  108. template <typename... Ts>
  109. tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
  110. tuple_binder<std::tuple<Ts...>> binder;
  111. return detail::tuple_binder_helper<sizeof...(Ts)>()(binder, json::binder::binder<Ts>(value_binder<Ts>())...);
  112. }
  113. template <typename T, std::size_t N>
  114. tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
  115. tuple_binder<std::array<T, N>> binder;
  116. return detail::array_binder_helper<N>(binder, binds);
  117. }
  118. template <typename T, std::size_t N>
  119. tuple_binder<std::array<T, N>> make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
  120. tuple_binder<std::array<T, N>> binder;
  121. return detail::array_binder_helper<N>(binder, json::binder::binder<T>(binds));
  122. }
  123. #endif
  124. } }