1 //
2 // MessagePack for C++ static resolution routine
3 //
4 // Copyright (C) 2008-2016 FURUHASHI Sadayuki and KONDO Takatoshi
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 #ifndef MSGPACK_V1_CPP11_MSGPACK_TUPLE_HPP
11 #define MSGPACK_V1_CPP11_MSGPACK_TUPLE_HPP
12
13 #include "msgpack/v1/adaptor/detail/cpp11_msgpack_tuple_decl.hpp"
14 #include "msgpack/adaptor/adaptor_base.hpp"
15 #include "msgpack/pack.hpp"
16
17 namespace msgpack {
18
19 /// @cond
MSGPACK_API_VERSION_NAMESPACE(v1)20 MSGPACK_API_VERSION_NAMESPACE(v1) {
21 /// @endcond
22
23 namespace type {
24
25 template <class... Args>
26 inline tuple<Args...> make_tuple(Args&&... args) {
27 return tuple<Args...>(std::forward<Args>(args)...);
28 }
29
30 template<class... Args>
31 inline tuple<Args&&...> forward_as_tuple (Args&&... args) noexcept {
32 return tuple<Args&&...>(std::forward<Args>(args)...);
33 }
34
35 template <class... Tuples>
36 inline auto tuple_cat(Tuples&&... args) ->
37 decltype(
38 std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...)
39 ) {
40 return std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...);
41 }
42
43 template <class... Args>
44 inline tuple<Args&...> tie(Args&... args) {
45 return tuple<Args&...>(args...);
46 }
47 } // namespace type
48
49 // --- Pack from tuple to packer stream ---
50 template <typename Stream, typename Tuple, std::size_t N>
51 struct MsgpackTuplePacker {
52 static void pack(
53 msgpack::packer<Stream>& o,
54 const Tuple& v) {
55 MsgpackTuplePacker<Stream, Tuple, N-1>::pack(o, v);
56 o.pack(type::get<N-1>(v));
57 }
58 };
59
60 template <typename Stream, typename Tuple>
61 struct MsgpackTuplePacker<Stream, Tuple, 1> {
62 static void pack (
63 msgpack::packer<Stream>& o,
64 const Tuple& v) {
65 o.pack(type::get<0>(v));
66 }
67 };
68
69 template <typename Stream, typename Tuple>
70 struct MsgpackTuplePacker<Stream, Tuple, 0> {
71 static void pack (
72 msgpack::packer<Stream>&,
73 const Tuple&) {
74 }
75 };
76
77 namespace adaptor {
78
79 template <typename... Args>
80 struct pack<msgpack::type::tuple<Args...>> {
81 template <typename Stream>
82 msgpack::packer<Stream>& operator()(
83 msgpack::packer<Stream>& o,
84 const msgpack::type::tuple<Args...>& v) const {
85 o.pack_array(sizeof...(Args));
86 MsgpackTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v);
87 return o;
88 }
89 };
90
91 } // namespace adaptor
92
93 // --- Convert from tuple to object ---
94
95 template <typename T, typename... Args>
96 struct MsgpackTupleAsImpl {
97 static msgpack::type::tuple<T, Args...> as(msgpack::object const& o) {
98 return msgpack::type::tuple_cat(
99 msgpack::type::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()),
100 MsgpackTupleAs<Args...>::as(o));
101 }
102 };
103
104 template <typename... Args>
105 struct MsgpackTupleAs {
106 static msgpack::type::tuple<Args...> as(msgpack::object const& o) {
107 return MsgpackTupleAsImpl<Args...>::as(o);
108 }
109 };
110
111 template <>
112 struct MsgpackTupleAs<> {
113 static msgpack::type::tuple<> as (msgpack::object const&) {
114 return msgpack::type::tuple<>();
115 }
116 };
117
118 template <typename Tuple, std::size_t N>
119 struct MsgpackTupleConverter {
120 static void convert(
121 msgpack::object const& o,
122 Tuple& v) {
123 MsgpackTupleConverter<Tuple, N-1>::convert(o, v);
124 if (o.via.array.size >= N)
125 o.via.array.ptr[N-1].convert<typename std::remove_reference<decltype(type::get<N-1>(v))>::type>(type::get<N-1>(v));
126 }
127 };
128
129 template <typename Tuple>
130 struct MsgpackTupleConverter<Tuple, 1> {
131 static void convert (
132 msgpack::object const& o,
133 Tuple& v) {
134 o.via.array.ptr[0].convert<typename std::remove_reference<decltype(type::get<0>(v))>::type>(type::get<0>(v));
135 }
136 };
137
138 template <typename Tuple>
139 struct MsgpackTupleConverter<Tuple, 0> {
140 static void convert (
141 msgpack::object const&,
142 Tuple&) {
143 }
144 };
145
146 namespace adaptor {
147
148 template <typename... Args>
149 struct as<msgpack::type::tuple<Args...>, typename std::enable_if<msgpack::any_of<msgpack::has_as, Args...>::value>::type> {
150 msgpack::type::tuple<Args...> operator()(
151 msgpack::object const& o) const {
152 if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
153 return MsgpackTupleAs<Args...>::as(o);
154 }
155 };
156
157 template <typename... Args>
158 struct convert<msgpack::type::tuple<Args...>> {
159 msgpack::object const& operator()(
160 msgpack::object const& o,
161 msgpack::type::tuple<Args...>& v) const {
162 if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
163 MsgpackTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v);
164 return o;
165 }
166 };
167
168 } // namespace adaptor
169
170 // --- Convert from tuple to object with zone ---
171 template <typename Tuple, std::size_t N>
172 struct MsgpackTupleToObjectWithZone {
173 static void convert(
174 msgpack::object::with_zone& o,
175 const Tuple& v) {
176 MsgpackTupleToObjectWithZone<Tuple, N-1>::convert(o, v);
177 o.via.array.ptr[N-1] = msgpack::object(type::get<N-1>(v), o.zone);
178 }
179 };
180
181 template <typename Tuple>
182 struct MsgpackTupleToObjectWithZone<Tuple, 1> {
183 static void convert (
184 msgpack::object::with_zone& o,
185 const Tuple& v) {
186 o.via.array.ptr[0] = msgpack::object(type::get<0>(v), o.zone);
187 }
188 };
189
190 template <typename Tuple>
191 struct MsgpackTupleToObjectWithZone<Tuple, 0> {
192 static void convert (
193 msgpack::object::with_zone&,
194 const Tuple&) {
195 }
196 };
197
198 namespace adaptor {
199
200 template <typename... Args>
201 struct object_with_zone<msgpack::type::tuple<Args...>> {
202 void operator()(
203 msgpack::object::with_zone& o,
204 msgpack::type::tuple<Args...> const& v) const {
205 o.type = msgpack::type::ARRAY;
206 o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*sizeof...(Args), MSGPACK_ZONE_ALIGNOF(msgpack::object)));
207 o.via.array.size = sizeof...(Args);
208 MsgpackTupleToObjectWithZone<decltype(v), sizeof...(Args)>::convert(o, v);
209 }
210 };
211
212 } // namespace adaptor
213
214 /// @cond
215 } // MSGPACK_API_VERSION_NAMESPACE(v1)
216 ///@endcond
217
218 } // namespace msgpack
219
220 #endif // MSGPACK_CPP11_MSGPACK_TUPLE_HPP
221