1 //
2 // MessagePack for C++ static resolution routine
3 //
4 // Copyright (C) 2008-2015 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_TYPE_CPP11_TUPLE_HPP
11 #define MSGPACK_V1_TYPE_CPP11_TUPLE_HPP
12
13 #include "msgpack/versioning.hpp"
14 #include "msgpack/adaptor/adaptor_base.hpp"
15 #include "msgpack/adaptor/check_container_size.hpp"
16 #include "msgpack/meta.hpp"
17
18 #include <tuple>
19
20 namespace msgpack {
21
22 /// @cond
MSGPACK_API_VERSION_NAMESPACE(v1)23 MSGPACK_API_VERSION_NAMESPACE(v1) {
24 /// @endcond
25
26 // --- Pack from tuple to packer stream ---
27 template <typename Stream, typename Tuple, std::size_t N>
28 struct StdTuplePacker {
29 static void pack(
30 msgpack::packer<Stream>& o,
31 const Tuple& v) {
32 StdTuplePacker<Stream, Tuple, N-1>::pack(o, v);
33 o.pack(std::get<N-1>(v));
34 }
35 };
36
37 template <typename Stream, typename Tuple>
38 struct StdTuplePacker<Stream, Tuple, 0> {
39 static void pack (
40 msgpack::packer<Stream>&,
41 const Tuple&) {
42 }
43 };
44
45 namespace adaptor {
46
47 template <typename... Args>
48 struct pack<std::tuple<Args...>> {
49 template <typename Stream>
50 msgpack::packer<Stream>& operator()(
51 msgpack::packer<Stream>& o,
52 const std::tuple<Args...>& v) const {
53 uint32_t size = checked_get_container_size(sizeof...(Args));
54 o.pack_array(size);
55 StdTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v);
56 return o;
57 }
58 };
59
60 } // namespace adaptor
61
62 // --- Convert from tuple to object ---
63
64 template <typename... Args>
65 struct StdTupleAs;
66
67 template <typename T, typename... Args>
68 struct StdTupleAsImpl {
69 static std::tuple<T, Args...> as(msgpack::object const& o) {
70 return std::tuple_cat(
71 std::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()),
72 StdTupleAs<Args...>::as(o));
73 }
74 };
75
76 template <typename... Args>
77 struct StdTupleAs {
78 static std::tuple<Args...> as(msgpack::object const& o) {
79 return StdTupleAsImpl<Args...>::as(o);
80 }
81 };
82
83 template <>
84 struct StdTupleAs<> {
85 static std::tuple<> as (msgpack::object const&) {
86 return std::tuple<>();
87 }
88 };
89
90 template <typename Tuple, std::size_t N>
91 struct StdTupleConverter {
92 static void convert(
93 msgpack::object const& o,
94 Tuple& v) {
95 StdTupleConverter<Tuple, N-1>::convert(o, v);
96 if (o.via.array.size >= N)
97 o.via.array.ptr[N-1].convert<typename std::remove_reference<decltype(std::get<N-1>(v))>::type>(std::get<N-1>(v));
98 }
99 };
100
101 template <typename Tuple>
102 struct StdTupleConverter<Tuple, 0> {
103 static void convert (
104 msgpack::object const&,
105 Tuple&) {
106 }
107 };
108
109 namespace adaptor {
110
111 template <typename... Args>
112 struct as<std::tuple<Args...>, typename std::enable_if<msgpack::any_of<msgpack::has_as, Args...>::value>::type> {
113 std::tuple<Args...> operator()(
114 msgpack::object const& o) const {
115 if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
116 return StdTupleAs<Args...>::as(o);
117 }
118 };
119
120 template <typename... Args>
121 struct convert<std::tuple<Args...>> {
122 msgpack::object const& operator()(
123 msgpack::object const& o,
124 std::tuple<Args...>& v) const {
125 if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
126 StdTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v);
127 return o;
128 }
129 };
130
131 } // namespace adaptor
132
133 // --- Convert from tuple to object with zone ---
134 template <typename Tuple, std::size_t N>
135 struct StdTupleToObjectWithZone {
136 static void convert(
137 msgpack::object::with_zone& o,
138 const Tuple& v) {
139 StdTupleToObjectWithZone<Tuple, N-1>::convert(o, v);
140 o.via.array.ptr[N-1] = msgpack::object(std::get<N-1>(v), o.zone);
141 }
142 };
143
144 template <typename Tuple>
145 struct StdTupleToObjectWithZone<Tuple, 0> {
146 static void convert (
147 msgpack::object::with_zone&,
148 const Tuple&) {
149 }
150 };
151
152 namespace adaptor {
153
154 template <typename... Args>
155 struct object_with_zone<std::tuple<Args...>> {
156 void operator()(
157 msgpack::object::with_zone& o,
158 std::tuple<Args...> const& v) const {
159 uint32_t size = checked_get_container_size(sizeof...(Args));
160 o.type = msgpack::type::ARRAY;
161 o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size, MSGPACK_ZONE_ALIGNOF(msgpack::object)));
162 o.via.array.size = size;
163 StdTupleToObjectWithZone<decltype(v), sizeof...(Args)>::convert(o, v);
164 }
165 };
166
167 } // namespace adaptor
168
169 /// @cond
170 } // MSGPACK_API_VERSION_NAMESPACE(v1)
171 /// @endcond
172
173 } // namespace msgpack
174
175 #endif // MSGPACK_V1_TYPE_CPP11_TUPLE_HPP
176