| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- //
- // json_direct_tuple_binder.hpp
- // json
- //
- // Created by Sam Jaffe on 2/26/17.
- //
- #pragma once
- #include <tuple>
- namespace json { namespace binder {
- template <typename T, std::size_t I>
- class get_binder : public binder_impl<T> {
- public:
- using value_type = typename std::remove_reference<decltype(std::get<I>(std::declval<T>()))>::type;
-
- get_binder(binder<value_type> val_binder)
- : impl(std::move(val_binder)) {
-
- }
-
- get_binder(binder_impl<value_type> const & val_binder = value_binder<value_type>())
- : 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 {
- using get_binder_t = get_binder<BindOut, std::tuple_size<BindOut>::value-N>;
- 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 && ith) 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
- } }
|