| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- //
- // json_direct_tuple_binder.hpp
- // json
- //
- // Created by Sam Jaffe on 2/26/17.
- //
- #pragma once
- #include "json_binder.hpp"
- #include "json_direct_binder.hpp"
- #include "json_tuple_binder.hpp"
- #include <array>
- #include <tuple>
- namespace json { namespace binder {
- template <typename T, std::size_t I>
- class get_binder : public binder_impl<T> {
- // Maybe a reference type
- using ith_type = decltype(std::get<I>(std::declval<T>()));
- public:
- using value_type = typename std::remove_reference<ith_type>::type;
- get_binder() : impl(value_binder<value_type>()) {}
- get_binder(binder<value_type> val_binder) : impl(std::move(val_binder)) {}
- get_binder(binder_impl<value_type> const & val_binder) : impl(val_binder) {}
- virtual binder_impl<T> * clone() const override {
- return new get_binder(*this);
- }
- virtual void parse(T & object, char const *& data,
- parser::options opts) const override {
- impl.parse(std::get<I>(object), data, opts);
- }
- virtual void write(T const & val, std::ostream & data) const override {
- impl.write(std::get<I>(val), data);
- }
- private:
- binder<value_type> impl;
- };
- #if __cpluscplus >= 201402L
- namespace detail {
- template <typename TupleOut, typename TupleIn, std::size_t... Indexes>
- tuple_binder<TupleOut> make_tuple_binder(TupleIn && binds,
- std::index_sequence<Indexes...>) {
- tuple_binder<TupleOut> binder;
- using swallow = int[];
- (void)swallow{0, (void(binder(get_binder<TupleOut, Indexes>(
- std::get<Indexes>(binds)))),
- 0)...};
- return binder;
- }
- template <typename TupleOut, typename T, std::size_t... Indexes>
- tuple_binder<TupleOut> make_array_binder(binder<T> && binds,
- std::index_sequence<Indexes...>) {
- tuple_binder<TupleOut> binder;
- using swallow = int[];
- (void)swallow{0,
- (void(binder(get_binder<TupleOut, Indexes>(binds))), 0)...};
- return binder;
- }
- }
- template <typename... Ts>
- tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
- return detail::make_tuple_binder<std::tuple<Ts...>>(
- std::make_tuple(binds...), std::make_index_sequence<sizeof...(Ts)>());
- }
- template <typename... Ts>
- tuple_binder<std::tuple<Ts...>>
- make_tuple_binder(binder_impl<Ts> &&... binds) {
- return detail::make_tuple_binder<std::tuple<Ts...>>(
- std::make_tuple(binder<Ts>(binds)...),
- std::make_index_sequence<sizeof...(Ts)>());
- }
- template <typename... Ts>
- tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
- return detail::make_tuple_binder<std::tuple<Ts...>>(
- std::make_tuple(binder<Ts>(value_binder<Ts>())...),
- std::make_index_sequence<sizeof...(Ts)>());
- }
- template <typename T, std::size_t N>
- tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
- return detail::make_array_binder<std::array<T, N>>(
- binds, std::make_index_sequence<N>());
- }
- template <typename T, std::size_t N>
- tuple_binder<std::array<T, N>>
- make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
- return detail::make_array_binder<std::array<T, N>>(
- binder<T>(binds), std::make_index_sequence<N>());
- }
- #else
- namespace detail {
- template <std::size_t> struct tuple_binder_helper;
- template <> struct tuple_binder_helper<0> {
- template <typename BindOut>
- tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind) const {
- return bind;
- }
- };
- template <std::size_t N> struct tuple_binder_helper {
- template <typename BindOut, typename BindIn, typename... Ts>
- tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
- BindIn && ith,
- Ts &&... binders) const {
- constexpr auto get_index = std::tuple_size<BindOut>::value - N;
- using get_binder_t = get_binder<BindOut, get_index>;
- return tuple_binder_helper<N - 1>()(
- bind(get_binder_t(std::forward<BindIn>(ith))),
- std::forward<Ts>(binders)...);
- }
- };
- template <std::size_t> struct array_binder_helper;
- template <> struct array_binder_helper<1> {
- template <typename BindOut, typename BindIn>
- tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
- BindIn &&) const {
- return bind;
- }
- };
- template <std::size_t N> struct array_binder_helper {
- template <typename BindOut, typename BindIn>
- tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind,
- BindIn && ith) const {
- return array_binder_helper<N - 1>()(
- bind(get_binder<BindOut, N - 1>(ith)), std::forward<BindIn>(ith));
- }
- };
- }
- template <typename... Ts>
- tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
- tuple_binder<std::tuple<Ts...>> binder;
- return detail::tuple_binder_helper<sizeof...(Ts)>()(
- binder, std::forward<Ts>(binds)...);
- }
- template <typename... Ts>
- tuple_binder<std::tuple<Ts...>>
- make_tuple_binder(binder_impl<Ts> &&... binds) {
- tuple_binder<std::tuple<Ts...>> binder;
- return detail::tuple_binder_helper<sizeof...(Ts)>()(
- binder, json::binder::binder<Ts>(binds)...);
- }
- template <typename... Ts>
- tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
- tuple_binder<std::tuple<Ts...>> binder;
- return detail::tuple_binder_helper<sizeof...(Ts)>()(
- binder, json::binder::binder<Ts>(value_binder<Ts>())...);
- }
- template <typename T, std::size_t N>
- tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
- tuple_binder<std::array<T, N>> binder;
- return detail::array_binder_helper<N>(binder, binds);
- }
- template <typename T, std::size_t N>
- tuple_binder<std::array<T, N>>
- make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
- tuple_binder<std::array<T, N>> binder;
- return detail::array_binder_helper<N>(binder,
- json::binder::binder<T>(binds));
- }
- #endif
- }}
|