MessagePack for C++
msgpack_variant.hpp
Go to the documentation of this file.
1 //
2 // MessagePack for C++ static resolution routine
3 //
4 // Copyright (C) 2015-2016 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_BOOST_MSGPACK_VARIANT_HPP
11 #define MSGPACK_V1_TYPE_BOOST_MSGPACK_VARIANT_HPP
12 
13 #if defined(MSGPACK_USE_BOOST)
14 
16 
19 
20 #include "msgpack/adaptor/nil.hpp"
21 #include "msgpack/adaptor/bool.hpp"
22 #include "msgpack/adaptor/int.hpp"
26 #include "msgpack/adaptor/raw.hpp"
27 #include "msgpack/adaptor/ext.hpp"
29 #include "msgpack/adaptor/map.hpp"
30 
31 #include <boost/variant.hpp>
32 #include <boost/operators.hpp>
33 
34 namespace msgpack {
35 
39 
40 namespace type {
41 
42 
43 template <typename STR, typename BIN, typename EXT>
44 struct basic_variant :
45  boost::variant<
46  nil_t, // NIL
47  bool, // BOOL
48  int64_t, // NEGATIVE_INTEGER
49  uint64_t, // POSITIVE_INTEGER
50  double, // FLOAT
51  std::string, // STR
52 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
53  boost::string_ref, // STR
54 #endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
55  std::vector<char>, // BIN
57  msgpack::type::ext, // EXT
59  boost::recursive_wrapper<std::vector<basic_variant<STR, BIN, EXT> > >, // ARRAY
60  boost::recursive_wrapper<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >, // MAP
61  boost::recursive_wrapper<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >// MAP
62  >,
63  private boost::totally_ordered<basic_variant<STR, BIN, EXT> > {
64  typedef boost::variant<
65  nil_t, // NIL
66  bool, // BOOL
67  int64_t, // NEGATIVE_INTEGER
68  uint64_t, // POSITIVE_INTEGER
69  double, // FLOAT
70  std::string, // STR
71 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
72  boost::string_ref, // STR
73 #endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
74  std::vector<char>, // BIN
76  msgpack::type::ext, // EXT
78  boost::recursive_wrapper<std::vector<basic_variant<STR, BIN, EXT> > >, // ARRAY
79  boost::recursive_wrapper<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >, // MAP
80  boost::recursive_wrapper<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >// MAP
81  > base;
82  basic_variant() {}
83  template <typename T>
84  basic_variant(T const& t):base(t) {}
85  basic_variant(char const* p):base(std::string(p)) {}
86  basic_variant(char v) {
87  int_init(v);
88  }
89  basic_variant(signed char v) {
90  int_init(v);
91  }
92  basic_variant(unsigned char v):base(uint64_t(v)) {}
93  basic_variant(signed int v) {
94  int_init(v);
95  }
96  basic_variant(unsigned int v):base(uint64_t(v)) {}
97  basic_variant(signed long v) {
98  int_init(v);
99  }
100  basic_variant(unsigned long v):base(uint64_t(v)) {}
101  basic_variant(signed long long v) {
102  int_init(v);
103  }
104  basic_variant(unsigned long long v):base(uint64_t(v)) {}
105 
106  bool is_nil() const {
107  return boost::get<msgpack::type::nil_t>(this);
108  }
109  bool is_bool() const {
110  return boost::get<bool>(this);
111  }
112  bool is_int64_t() const {
113  return boost::get<int64_t>(this);
114  }
115  bool is_uint64_t() const {
116  return boost::get<uint64_t>(this);
117  }
118  bool is_double() const {
119  return boost::get<double>(this);
120  }
121  bool is_string() const {
122  return boost::get<std::string>(this);
123  }
124 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
125  bool is_boost_string_ref() const {
126  return boost::get<boost::string_ref>(this);
127  }
128 #endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
129  bool is_vector_char() const {
130  return boost::get<std::vector<char> >(this);
131  }
132  bool is_vector_char() {
133  return boost::get<std::vector<char> >(this);
134  }
135  bool is_raw_ref() const {
136  return boost::get<raw_ref>(this);
137  }
138  bool is_ext() const {
139  return boost::get<ext>(this);
140  }
141  bool is_ext_ref() const {
142  return boost::get<ext_ref>(this);
143  }
144  bool is_vector() const {
145  return boost::get<std::vector<basic_variant<STR, BIN, EXT> > >(this);
146  }
147  bool is_map() const {
148  return boost::get<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(this);
149  }
150  bool is_multimap() const {
151  return boost::get<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(this);
152  }
153 
154  bool as_bool() const {
155  return boost::get<bool>(*this);
156  }
157  int64_t as_int64_t() const {
158  return boost::get<int64_t>(*this);
159  }
160  int64_t& as_int64_t() {
161  return boost::get<int64_t>(*this);
162  }
163  uint64_t as_uint64_t() const {
164  return boost::get<uint64_t>(*this);
165  }
166  uint64_t& as_uint64_t() {
167  return boost::get<uint64_t>(*this);
168  }
169  double as_double() const {
170  return boost::get<double>(*this);
171  }
172  double& as_double() {
173  return boost::get<double>(*this);
174  }
175  std::string const& as_string() const {
176  return boost::get<std::string>(*this);
177  }
178  std::string& as_string() {
179  return boost::get<std::string>(*this);
180  }
181 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
182  boost::string_ref const& as_boost_string_ref() const {
183  return boost::get<boost::string_ref>(*this);
184  }
185  boost::string_ref& as_boost_string_ref() {
186  return boost::get<boost::string_ref>(*this);
187  }
188 #endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
189  std::vector<char> const& as_vector_char() const {
190  return boost::get<std::vector<char> >(*this);
191  }
192  std::vector<char>& as_vector_char() {
193  return boost::get<std::vector<char> >(*this);
194  }
195  raw_ref const& as_raw_ref() const {
196  return boost::get<raw_ref>(*this);
197  }
198  ext const& as_ext() const {
199  return boost::get<ext>(*this);
200  }
201  ext& as_ext() {
202  return boost::get<ext>(*this);
203  }
204  ext_ref const& as_ext_ref() const {
205  return boost::get<ext_ref>(*this);
206  }
207  std::vector<basic_variant<STR, BIN, EXT> > const& as_vector() const {
208  return boost::get<std::vector<basic_variant<STR, BIN, EXT> > >(*this);
209  }
210  std::vector<basic_variant<STR, BIN, EXT> >& as_vector() {
211  return boost::get<std::vector<basic_variant<STR, BIN, EXT> > >(*this);
212  }
213  std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > const& as_map() const {
214  return boost::get<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
215  }
216  std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> >& as_map() {
217  return boost::get<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
218  }
219  std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > const& as_multimap() const {
220  return boost::get<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
221  }
222  std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> >& as_multimap() {
223  return boost::get<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(*this);
224  }
225 private:
226  template <typename T>
227  void int_init(T v) {
228  if (v < 0) {
229  static_cast<base&>(*this) = int64_t(v);
230  }
231  else {
232  static_cast<base&>(*this) = uint64_t(v);
233  }
234  }
235 };
236 
237 template <typename STR, typename BIN, typename EXT>
238 inline bool operator<(basic_variant<STR, BIN, EXT> const& lhs, basic_variant<STR, BIN, EXT> const& rhs) {
239  return
240  static_cast<typename basic_variant<STR, BIN, EXT>::base const&>(lhs) <
241  static_cast<typename basic_variant<STR, BIN, EXT>::base const&>(rhs);
242 }
243 
244 template <typename STR, typename BIN, typename EXT>
245 inline bool operator==(basic_variant<STR, BIN, EXT> const& lhs, basic_variant<STR, BIN, EXT> const& rhs) {
246  return
247  static_cast<typename basic_variant<STR, BIN, EXT>::base const&>(lhs) ==
248  static_cast<typename basic_variant<STR, BIN, EXT>::base const&>(rhs);
249 }
250 
251 typedef basic_variant<std::string, std::vector<char>, ext> variant;
252 typedef basic_variant<
253 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
254  boost::string_ref,
255 #else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
256  std::string,
257 #endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53
258  raw_ref, ext_ref> variant_ref;
259 
260 } // namespace type
261 
262 namespace adaptor {
263 
264 #if !defined (MSGPACK_USE_CPP03)
265 
266 template <typename STR, typename BIN, typename EXT>
267 struct as<type::basic_variant<STR, BIN, EXT> > {
268  type::basic_variant<STR, BIN, EXT> operator()(msgpack::object const& o) const {
269  switch(o.type) {
270  case type::NIL:
271  return o.as<msgpack::type::nil_t>();
272  case type::BOOLEAN:
273  return o.as<bool>();
275  return o.as<uint64_t>();
277  return o.as<int64_t>();
278  case type::FLOAT:
279  return o.as<double>();
280  case type::STR:
281  return o.as<STR>();
282  case type::BIN:
283  return o.as<BIN>();
284  case type::EXT:
285  return o.as<EXT>();
286  case type::ARRAY:
287  return o.as<std::vector<type::basic_variant<STR, BIN, EXT> > >();
288  case type::MAP:
289  return o.as<std::multimap<type::basic_variant<STR, BIN, EXT>, type::basic_variant<STR, BIN, EXT> > >();
290  default:
291  break;
292  }
293  return type::basic_variant<STR, BIN, EXT>();
294  }
295 };
296 
297 #endif // !defined (MSGPACK_USE_CPP03)
298 
299 
300 template <typename STR, typename BIN, typename EXT>
301 struct convert<type::basic_variant<STR, BIN, EXT> > {
302  msgpack::object const& operator()(
303  msgpack::object const& o,
304  type::basic_variant<STR, BIN, EXT>& v) const {
305  switch(o.type) {
306  case type::NIL:
307  v = o.as<msgpack::type::nil_t>();
308  break;
309  case type::BOOLEAN:
310  v = o.as<bool>();
311  break;
313  v = o.as<uint64_t>();
314  break;
316  v = o.as<int64_t>();
317  break;
318  case type::FLOAT:
319  v = o.as<double>();
320  break;
321  case type::STR:
322  v = o.as<STR>();
323  break;
324  case type::BIN:
325  v = o.as<BIN>();
326  break;
327  case type::EXT:
328  v = o.as<EXT>();
329  break;
330  case type::ARRAY:
331  v = o.as<std::vector<type::basic_variant<STR, BIN, EXT> > >();
332  break;
333  case type::MAP:
334  v = o.as<std::multimap<type::basic_variant<STR, BIN, EXT>, type::basic_variant<STR, BIN, EXT> > >();
335  break;
336  default:
337  break;
338  }
339  return o;
340  }
341 };
342 
343 namespace detail {
344 
345 template <typename Stream>
346 struct pack_imp : boost::static_visitor<void> {
347  template <typename T>
348  void operator()(T const& value) const {
349  pack<T>()(o_, value);
350  }
351  pack_imp(packer<Stream>& o):o_(o) {}
352  packer<Stream>& o_;
353 };
354 
355 } // namespace detail
356 
357 template <typename STR, typename BIN, typename EXT>
358 struct pack<type::basic_variant<STR, BIN, EXT> > {
359  template <typename Stream>
360  msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const type::basic_variant<STR, BIN, EXT>& v) const {
361  boost::apply_visitor(detail::pack_imp<Stream>(o), v);
362  return o;
363  }
364 };
365 
366 namespace detail {
367 
368 struct object_imp : boost::static_visitor<void> {
369  void operator()(msgpack::type::nil_t const& v) const {
370  object<msgpack::type::nil_t>()(o_, v);
371  }
372  void operator()(bool const& v) const {
373  object<bool>()(o_, v);
374  }
375  void operator()(uint64_t const& v) const {
376  object<uint64_t>()(o_, v);
377  }
378  void operator()(int64_t const& v) const {
379  object<int64_t>()(o_, v);
380  }
381  void operator()(double const& v) const {
382  object<double>()(o_, v);
383  }
384  template <typename T>
385  void operator()(T const&) const {
386  throw msgpack::type_error();
387  }
388  object_imp(msgpack::object& o):o_(o) {}
389  msgpack::object& o_;
390 };
391 
392 } // namespace detail
393 
394 template <typename STR, typename BIN, typename EXT>
395 struct object<type::basic_variant<STR, BIN, EXT> > {
396  void operator()(msgpack::object& o, const type::basic_variant<STR, BIN, EXT>& v) const {
397  boost::apply_visitor(detail::object_imp(o), v);
398  }
399 };
400 
401 namespace detail {
402 
403 struct object_with_zone_imp : boost::static_visitor<void> {
404  template <typename T>
405  void operator()(T const& v) const {
406  object_with_zone<T>()(o_, v);
407  }
408  object_with_zone_imp(msgpack::object::with_zone& o):o_(o) {}
410 };
411 
412 } // namespace detail
413 
414 template <typename STR, typename BIN, typename EXT>
415 struct object_with_zone<type::basic_variant<STR, BIN, EXT> > {
416  void operator()(msgpack::object::with_zone& o, const type::basic_variant<STR, BIN, EXT>& v) const {
417  boost::apply_visitor(detail::object_with_zone_imp(o), v);
418  }
419 };
420 
421 } // namespace adaptor
422 
424 } // MSGPACK_API_VERSION_NAMESPACE(v1)
426 
427 } // namespace msgpack
428 
429 #endif // MSGPACK_USE_BOOST
430 #endif // MSGPACK_V1_TYPE_BOOST_MSGPACK_VARIANT_HPP
Definition: object_fwd_decl.hpp:37
Definition: nil.hpp:23
Definition: object_fwd_decl.hpp:30
Definition: raw.hpp:26
Definition: object_fwd_decl.hpp:38
Definition: ext.hpp:27
Definition: adaptor_base.hpp:15
Definition: object_fwd_decl.hpp:33
void convert(T &v, msgpack::object const &o)
Definition: object.hpp:640
Definition: object.hpp:34
Definition: object_fwd_decl.hpp:29
Definition: object_fwd_decl.hpp:32
std::enable_if< msgpack::has_as< T >::value, T >::type as() const
Get value as T.
Definition: object.hpp:567
Definition: object_fwd.hpp:222
Definition: object_fwd_decl.hpp:41
void pack(msgpack::packer< Stream > &o, const T &v)
Definition: object.hpp:647
Object class that corresponding to MessagePack format object.
Definition: object_fwd.hpp:75
msgpack::type::object_type type
Definition: object_fwd.hpp:91
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:58
Definition: object_fwd_decl.hpp:39
Definition: ext.hpp:119
Definition: object_fwd_decl.hpp:40
bool operator==(nil_t const &lhs, nil_t const &rhs)
Definition: nil.hpp:29
The class template that supports continuous packing.
Definition: adaptor_base_decl.hpp:23
Definition: object_fwd_decl.hpp:31