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