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 
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) != nullptr;
119  }
120  bool is_bool() const {
121  return boost::get<bool>(this) != nullptr;
122  }
123  bool is_int64_t() const {
124  return boost::get<int64_t>(this) != nullptr;
125  }
126  bool is_uint64_t() const {
127  return boost::get<uint64_t>(this) != nullptr;
128  }
129  bool is_double() const {
130  return boost::get<double>(this) != nullptr;
131  }
132  bool is_string() const {
133  return boost::get<std::string>(this) != 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) != 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) != nullptr;
142  }
143  bool is_vector_char() {
144  return boost::get<std::vector<char> >(this) != nullptr;
145  }
146  bool is_raw_ref() const {
147  return boost::get<raw_ref>(this) != nullptr;
148  }
149  bool is_ext() const {
150  return boost::get<ext>(this) != nullptr;
151  }
152  bool is_ext_ref() const {
153  return boost::get<ext_ref>(this) != nullptr;
154  }
155  bool is_vector() const {
156  return boost::get<std::vector<basic_variant<STR, BIN, EXT> > >(this) != nullptr;
157  }
158  bool is_map() const {
159  return boost::get<std::map<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(this) != nullptr;
160  }
161  bool is_multimap() const {
162  return boost::get<std::multimap<basic_variant<STR, BIN, EXT>, basic_variant<STR, BIN, EXT> > >(this) != 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::FLOAT:
290  return o.as<double>();
291  case type::STR:
292  return o.as<STR>();
293  case type::BIN:
294  return o.as<BIN>();
295  case type::EXT:
296  return o.as<EXT>();
297  case type::ARRAY:
298  return o.as<std::vector<type::basic_variant<STR, BIN, EXT> > >();
299  case type::MAP:
300  return o.as<std::multimap<type::basic_variant<STR, BIN, EXT>, type::basic_variant<STR, BIN, EXT> > >();
301  default:
302  break;
303  }
304  return type::basic_variant<STR, BIN, EXT>();
305  }
306 };
307 
308 #endif // !defined (MSGPACK_USE_CPP03)
309 
310 
311 template <typename STR, typename BIN, typename EXT>
312 struct convert<type::basic_variant<STR, BIN, EXT> > {
313  msgpack::object const& operator()(
314  msgpack::object const& o,
315  type::basic_variant<STR, BIN, EXT>& v) const {
316  switch(o.type) {
317  case type::NIL:
318  v = o.as<msgpack::type::nil_t>();
319  break;
320  case type::BOOLEAN:
321  v = o.as<bool>();
322  break;
324  v = o.as<uint64_t>();
325  break;
327  v = o.as<int64_t>();
328  break;
329  case type::FLOAT:
330  v = o.as<double>();
331  break;
332  case type::STR:
333  v = o.as<STR>();
334  break;
335  case type::BIN:
336  v = o.as<BIN>();
337  break;
338  case type::EXT:
339  v = o.as<EXT>();
340  break;
341  case type::ARRAY:
342  v = o.as<std::vector<type::basic_variant<STR, BIN, EXT> > >();
343  break;
344  case type::MAP:
345  v = o.as<std::multimap<type::basic_variant<STR, BIN, EXT>, type::basic_variant<STR, BIN, EXT> > >();
346  break;
347  default:
348  break;
349  }
350  return o;
351  }
352 };
353 
354 namespace detail {
355 
356 template <typename Stream>
357 struct pack_imp : boost::static_visitor<void> {
358  template <typename T>
359  void operator()(T const& value) const {
360  pack<T>()(o_, value);
361  }
362  pack_imp(packer<Stream>& o):o_(o) {}
363  packer<Stream>& o_;
364 };
365 
366 } // namespace detail
367 
368 template <typename STR, typename BIN, typename EXT>
369 struct pack<type::basic_variant<STR, BIN, EXT> > {
370  template <typename Stream>
371  msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const type::basic_variant<STR, BIN, EXT>& v) const {
372  boost::apply_visitor(detail::pack_imp<Stream>(o), v);
373  return o;
374  }
375 };
376 
377 namespace detail {
378 
379 struct object_imp : boost::static_visitor<void> {
380  void operator()(msgpack::type::nil_t const& v) const {
381  object<msgpack::type::nil_t>()(o_, v);
382  }
383  void operator()(bool const& v) const {
384  object<bool>()(o_, v);
385  }
386  void operator()(uint64_t const& v) const {
387  object<uint64_t>()(o_, v);
388  }
389  void operator()(int64_t const& v) const {
390  object<int64_t>()(o_, v);
391  }
392  void operator()(double const& v) const {
393  object<double>()(o_, v);
394  }
395  template <typename T>
396  void operator()(T const&) const {
397  throw msgpack::type_error();
398  }
399  object_imp(msgpack::object& o):o_(o) {}
400  msgpack::object& o_;
401 };
402 
403 } // namespace detail
404 
405 template <typename STR, typename BIN, typename EXT>
406 struct object<type::basic_variant<STR, BIN, EXT> > {
407  void operator()(msgpack::object& o, const type::basic_variant<STR, BIN, EXT>& v) const {
408  boost::apply_visitor(detail::object_imp(o), v);
409  }
410 };
411 
412 namespace detail {
413 
414 struct object_with_zone_imp : boost::static_visitor<void> {
415  template <typename T>
416  void operator()(T const& v) const {
417  object_with_zone<T>()(o_, v);
418  }
419  object_with_zone_imp(msgpack::object::with_zone& o):o_(o) {}
421 };
422 
423 } // namespace detail
424 
425 template <typename STR, typename BIN, typename EXT>
426 struct object_with_zone<type::basic_variant<STR, BIN, EXT> > {
427  void operator()(msgpack::object::with_zone& o, const type::basic_variant<STR, BIN, EXT>& v) const {
428  boost::apply_visitor(detail::object_with_zone_imp(o), v);
429  }
430 };
431 
432 } // namespace adaptor
433 
435 } // MSGPACK_API_VERSION_NAMESPACE(v1)
437 
438 } // namespace msgpack
439 
440 #endif // MSGPACK_USE_BOOST
441 #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:657
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:584
Definition: object_fwd.hpp:233
Definition: object_fwd_decl.hpp:41
void pack(msgpack::packer< Stream > &o, const T &v)
Definition: object.hpp:664
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:24
Definition: object_fwd_decl.hpp:31