1 //
2 // MessagePack for C++ static resolution routine
3 //
4 // Copyright (C) 2008-2014 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_OBJECT_HPP
11 #define MSGPACK_V1_OBJECT_HPP
12
13 #include "msgpack/object_decl.hpp"
14 #include "msgpack/adaptor/check_container_size.hpp"
15
16 #include <cstring>
17 #include <stdexcept>
18 #include <typeinfo>
19 #include <limits>
20 #include <ostream>
21 #include <typeinfo>
22 #include <iomanip>
23
24 namespace msgpack {
25
26 /// @cond
MSGPACK_API_VERSION_NAMESPACE(v1)27 MSGPACK_API_VERSION_NAMESPACE(v1) {
28 /// @endcond
29
30 struct object_kv {
31 msgpack::object key;
32 msgpack::object val;
33 };
34
35 struct object::with_zone : msgpack::object {
36 with_zone(msgpack::zone& z) : zone(z) { }
37 msgpack::zone& zone;
38 private:
39 with_zone();
40 };
41
42
43 /// The class holds object and zone
44 class object_handle {
45 public:
46 /// Constructor that creates nil object and null zone.
47 object_handle() {}
48
49 /// Constructor that creates an object_handle holding object `obj` and zone `z`.
50 /**
51 * @param obj object
52 * @param z zone
53 */
54 object_handle(
55 msgpack::object const& obj,
56 #if defined(MSGPACK_USE_CPP03)
57 msgpack::unique_ptr<msgpack::zone> z
58 #else // defined(MSGPACK_USE_CPP03)
59 msgpack::unique_ptr<msgpack::zone>&& z
60 #endif // defined(MSGPACK_USE_CPP03)
61 ) :
62 m_obj(obj), m_zone(msgpack::move(z)) { }
63
64 void set(msgpack::object const& obj)
65 { m_obj = obj; }
66
67 /// Get object reference
68 /**
69 * @return object
70 */
71 const msgpack::object& get() const
72 { return m_obj; }
73
74 /**
75 * @return object (to mimic smart pointers).
76 */
77 const msgpack::object& operator*() const
78 { return get(); }
79
80 /**
81 * @return the address of the object (to mimic smart pointers).
82 */
83 const msgpack::object* operator->() const
84 { return &get(); }
85
86 /// Get unique_ptr reference of zone.
87 /**
88 * @return unique_ptr reference of zone
89 */
90 msgpack::unique_ptr<msgpack::zone>& zone()
91 { return m_zone; }
92
93 /// Get unique_ptr const reference of zone.
94 /**
95 * @return unique_ptr const reference of zone
96 */
97 const msgpack::unique_ptr<msgpack::zone>& zone() const
98 { return m_zone; }
99
100 #if defined(MSGPACK_USE_CPP03)
101 struct object_handle_ref {
102 object_handle_ref(object_handle* oh):m_oh(oh) {}
103 object_handle* m_oh;
104 };
105
106 object_handle(object_handle& other):
107 m_obj(other.m_obj),
108 m_zone(msgpack::move(other.m_zone)) {
109 }
110
111 object_handle(object_handle_ref ref):
112 m_obj(ref.m_oh->m_obj),
113 m_zone(msgpack::move(ref.m_oh->m_zone)) {
114 }
115
116 object_handle& operator=(object_handle& other) {
117 m_obj = other.m_obj;
118 m_zone = msgpack::move(other.m_zone);
119 return *this;
120 }
121
122 object_handle& operator=(object_handle_ref ref) {
123 m_obj = ref.m_oh->m_obj;
124 m_zone = msgpack::move(ref.m_oh->m_zone);
125 return *this;
126 }
127
128 operator object_handle_ref() {
129 return object_handle_ref(this);
130 }
131 #endif // defined(MSGPACK_USE_CPP03)
132
133 private:
134 msgpack::object m_obj;
135 msgpack::unique_ptr<msgpack::zone> m_zone;
136 };
137
138 namespace detail {
139
140 template <std::size_t N>
141 inline std::size_t add_ext_type_size(std::size_t size) {
142 return size + 1;
143 }
144
145 template <>
146 inline std::size_t add_ext_type_size<4>(std::size_t size) {
147 return size == 0xffffffff ? size : size + 1;
148 }
149
150 } // namespace detail
151 class object_parser {
152 private:
153 enum next_ret {
154 cont,
155 finish,
156 abort
157 };
158 struct elem {
159 elem(msgpack::object const* p, std::size_t r)
160 : rest(r), is_map(false), is_key(false) {
161 as.obj_ptr = p;
162 }
163
164 elem(msgpack::object_kv const* p, std::size_t r)
165 : rest(r), is_map(true), is_key(true) {
166 as.kv_ptr = p;
167 }
168
169 msgpack::object const& get() const {
170 if (is_map) {
171 if (is_key) {
172 return as.kv_ptr->key;
173 }
174 else {
175 return as.kv_ptr->val;
176 }
177 }
178 else {
179 return *as.obj_ptr;
180 }
181 }
182
183 template <typename Visitor>
184 next_ret next(Visitor& v) {
185 if (rest == 0) {
186 if (is_map) {
187 if (!v.end_map()) return abort;
188 }
189 else {
190 if (!v.end_array()) return abort;
191 }
192 return finish;
193 }
194 else {
195 if (is_map) {
196 if (is_key) {
197 if (!v.end_map_key()) return abort;
198 if (!v.start_map_value()) return abort;
199 is_key = false;
200 }
201 else {
202 if (!v.end_map_value()) return abort;
203 --rest;
204 if (rest == 0) {
205 if (!v.end_map()) return abort;
206 return finish;
207 }
208 if (!v.start_map_key()) return abort;
209 ++as.kv_ptr;
210 is_key = true;
211 }
212 }
213 else {
214 if (!v.end_array_item()) return abort;
215 --rest;
216 if (rest == 0) {
217 if (!v.end_array()) return abort;
218 return finish;
219 }
220 if (!v.start_array_item()) return abort;
221 ++as.obj_ptr;
222 }
223 return cont;
224 }
225 }
226
227 union {
228 msgpack::object const* obj_ptr;
229 msgpack::object_kv const* kv_ptr;
230 } as;
231 std::size_t rest;
232 bool is_map;
233 bool is_key;
234 };
235 public:
236 explicit object_parser(msgpack::object const& obj):m_current(&obj) {}
237 template <typename Visitor>
238 void parse(Visitor& v) {
239 while (true) {
240 bool start_collection = false;
241 switch(m_current->type) {
242 case msgpack::type::NIL:
243 if (!v.visit_nil()) return;
244 break;
245 case msgpack::type::BOOLEAN:
246 if (!v.visit_boolean(m_current->via.boolean)) return;
247 break;
248 case msgpack::type::POSITIVE_INTEGER:
249 if (!v.visit_positive_integer(m_current->via.u64)) return;
250 break;
251 case msgpack::type::NEGATIVE_INTEGER:
252 if (!v.visit_negative_integer(m_current->via.i64)) return;
253 break;
254 case msgpack::type::FLOAT32:
255 if (!v.visit_float32(static_cast<float>(m_current->via.f64))) return;
256 break;
257 case msgpack::type::FLOAT64:
258 if (!v.visit_float64(m_current->via.f64)) return;
259 break;
260 case msgpack::type::STR:
261 if (!v.visit_str(m_current->via.str.ptr, m_current->via.str.size)) return;
262 break;
263 case msgpack::type::BIN:
264 if (!v.visit_bin(m_current->via.bin.ptr, m_current->via.bin.size)) return;
265 break;
266 case msgpack::type::EXT:
267 msgpack::detail::check_container_size<sizeof(std::size_t)>(m_current->via.ext.size);
268 if (!v.visit_ext(m_current->via.ext.ptr, m_current->via.ext.size + 1)) return;
269 break;
270 case msgpack::type::ARRAY:
271 if (!v.start_array(m_current->via.array.size)) return;
272 m_ctx.push_back(elem(m_current->via.array.ptr, m_current->via.array.size));
273 start_collection = m_current->via.array.size != 0;
274 if (start_collection) {
275 if (!v.start_array_item()) return;
276 }
277 break;
278 case msgpack::type::MAP:
279 if (!v.start_map(m_current->via.map.size)) return;
280 m_ctx.push_back(elem(m_current->via.map.ptr, m_current->via.map.size));
281 start_collection = m_current->via.map.size != 0;
282 if (start_collection) {
283 if (!v.start_map_key()) return;
284 }
285 break;
286 default:
287 throw msgpack::type_error();
288 break;
289 }
290 if (m_ctx.empty()) return;
291 if (!start_collection) {
292 while (true) {
293 next_ret r = m_ctx.back().next(v);
294 if (r == finish) {
295 m_ctx.pop_back();
296 if (m_ctx.empty()) return;
297 }
298 else if (r == cont) {
299 break;
300 }
301 else {
302 // abort
303 return;
304 }
305 }
306 }
307 m_current = &m_ctx.back().get();
308 }
309 }
310 private:
311 msgpack::object const* m_current;
312 std::vector<elem> m_ctx;
313 };
314
315 template <typename Stream>
316 struct object_pack_visitor {
317 explicit object_pack_visitor(msgpack::packer<Stream>& pk)
318 :m_packer(pk) {}
319 bool visit_nil() {
320 m_packer.pack_nil();
321 return true;
322 }
323 bool visit_boolean(bool v) {
324 if (v) m_packer.pack_true();
325 else m_packer.pack_false();
326 return true;
327 }
328 bool visit_positive_integer(uint64_t v) {
329 m_packer.pack_uint64(v);
330 return true;
331 }
332 bool visit_negative_integer(int64_t v) {
333 m_packer.pack_int64(v);
334 return true;
335 }
336 bool visit_float32(float v) {
337 m_packer.pack_float(v);
338 return true;
339 }
340 bool visit_float64(double v) {
341 m_packer.pack_double(v);
342 return true;
343 }
344 bool visit_str(const char* v, uint32_t size) {
345 m_packer.pack_str(size);
346 m_packer.pack_str_body(v, size);
347 return true;
348 }
349 bool visit_bin(const char* v, uint32_t size) {
350 m_packer.pack_bin(size);
351 m_packer.pack_bin_body(v, size);
352 return true;
353 }
354 bool visit_ext(const char* v, uint32_t size) {
355 m_packer.pack_ext(size, *v);
356 m_packer.pack_ext_body(v, size);
357 return true;
358 }
359 bool start_array(uint32_t num_elements) {
360 m_packer.pack_array(num_elements);
361 return true;
362 }
363 bool start_array_item() {
364 return true;
365 }
366 bool end_array_item() {
367 return true;
368 }
369 bool end_array() {
370 return true;
371 }
372 bool start_map(uint32_t num_kv_pairs) {
373 m_packer.pack_map(num_kv_pairs);
374 return true;
375 }
376 bool start_map_key() {
377 return true;
378 }
379 bool end_map_key() {
380 return true;
381 }
382 bool start_map_value() {
383 return true;
384 }
385 bool end_map_value() {
386 return true;
387 }
388 bool end_map() {
389 return true;
390 }
391 private:
392 msgpack::packer<Stream>& m_packer;
393 };
394
395
396 struct object_stringize_visitor {
397 explicit object_stringize_visitor(std::ostream& os)
398 :m_os(os) {}
399 bool visit_nil() {
400 m_os << "null";
401 return true;
402 }
403 bool visit_boolean(bool v) {
404 if (v) m_os << "true";
405 else m_os << "false";
406 return true;
407 }
408 bool visit_positive_integer(uint64_t v) {
409 m_os << v;
410 return true;
411 }
412 bool visit_negative_integer(int64_t v) {
413 m_os << v;
414 return true;
415 }
416 bool visit_float32(float v) {
417 m_os << v;
418 return true;
419 }
420 bool visit_float64(double v) {
421 m_os << v;
422 return true;
423 }
424 bool visit_str(const char* v, uint32_t size) {
425 m_os << '"';
426 for (uint32_t i = 0; i < size; ++i) {
427 char c = v[i];
428 switch (c) {
429 case '\\':
430 m_os << "\\\\";
431 break;
432 case '"':
433 m_os << "\\\"";
434 break;
435 case '/':
436 m_os << "\\/";
437 break;
438 case '\b':
439 m_os << "\\b";
440 break;
441 case '\f':
442 m_os << "\\f";
443 break;
444 case '\n':
445 m_os << "\\n";
446 break;
447 case '\r':
448 m_os << "\\r";
449 break;
450 case '\t':
451 m_os << "\\t";
452 break;
453 default: {
454 unsigned int code = static_cast<unsigned int>(c);
455 if (code < 0x20 || code == 0x7f) {
456 std::ios::fmtflags flags(m_os.flags());
457 m_os << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (code & 0xff);
458 m_os.flags(flags);
459 }
460 else {
461 m_os << c;
462 }
463 } break;
464 }
465 }
466 m_os << '"';
467 return true;
468 }
469 bool visit_bin(const char* v, uint32_t size) {
470 (m_os << '"').write(v, size) << '"';
471 return true;
472 }
473 bool visit_ext(const char* /*v*/, uint32_t /*size*/) {
474 m_os << "EXT";
475 return true;
476 }
477 bool start_array(uint32_t num_elements) {
478 m_current_size.push_back(num_elements);
479 m_os << "[";
480 return true;
481 }
482 bool start_array_item() {
483 return true;
484 }
485 bool end_array_item() {
486 --m_current_size.back();
487 if (m_current_size.back() != 0) {
488 m_os << ",";
489 }
490 return true;
491 }
492 bool end_array() {
493 m_current_size.pop_back();
494 m_os << "]";
495 return true;
496 }
497 bool start_map(uint32_t num_kv_pairs) {
498 m_current_size.push_back(num_kv_pairs);
499 m_os << "{";
500 return true;
501 }
502 bool start_map_key() {
503 return true;
504 }
505 bool end_map_key() {
506 m_os << ":";
507 return true;
508 }
509 bool start_map_value() {
510 return true;
511 }
512 bool end_map_value() {
513 --m_current_size.back();
514 if (m_current_size.back() != 0) {
515 m_os << ",";
516 }
517 return true;
518 }
519 bool end_map() {
520 m_current_size.pop_back();
521 m_os << "}";
522 return true;
523 }
524 private:
525 std::ostream& m_os;
526 std::vector<uint32_t> m_current_size;
527 };
528
529 struct aligned_zone_size_visitor {
530 explicit aligned_zone_size_visitor(std::size_t s)
531 :m_size(s) {}
532 bool visit_nil() {
533 return true;
534 }
535 bool visit_boolean(bool) {
536 return true;
537 }
538 bool visit_positive_integer(uint64_t) {
539 return true;
540 }
541 bool visit_negative_integer(int64_t) {
542 return true;
543 }
544 bool visit_float32(float) {
545 return true;
546 }
547 bool visit_float64(double) {
548 return true;
549 }
550 bool visit_str(const char*, uint32_t size) {
551 m_size += msgpack::aligned_size(size, MSGPACK_ZONE_ALIGNOF(char));
552 return true;
553 }
554 bool visit_bin(const char*, uint32_t size) {
555 m_size += msgpack::aligned_size(size, MSGPACK_ZONE_ALIGNOF(char));
556 return true;
557 }
558 bool visit_ext(const char*, uint32_t size) {
559 m_size += msgpack::aligned_size(size, MSGPACK_ZONE_ALIGNOF(char));
560 return true;
561 }
562 bool start_array(uint32_t num_elements) {
563 m_size += msgpack::aligned_size(
564 sizeof(msgpack::object) * num_elements,
565 MSGPACK_ZONE_ALIGNOF(msgpack::object));
566 return true;
567 }
568 bool start_array_item() {
569 return true;
570 }
571 bool end_array_item() {
572 return true;
573 }
574 bool end_array() {
575 return true;
576 }
577 bool start_map(uint32_t num_kv_pairs) {
578 m_size += msgpack::aligned_size(
579 sizeof(msgpack::object_kv) * num_kv_pairs,
580 MSGPACK_ZONE_ALIGNOF(msgpack::object_kv));
581 return true;
582 }
583 bool start_map_key() {
584 return true;
585 }
586 bool end_map_key() {
587 return true;
588 }
589 bool start_map_value() {
590 return true;
591 }
592 bool end_map_value() {
593 return true;
594 }
595 bool end_map() {
596 return true;
597 }
598 private:
599 std::size_t m_size;
600 };
601
602 inline std::size_t aligned_zone_size(msgpack::object const& obj) {
603 std::size_t s = 0;
604 aligned_zone_size_visitor vis(s);
605 msgpack::object_parser(obj).parse(vis);
606 return s;
607 }
608
609 /// clone object
610 /**
611 * Clone (deep copy) object.
612 * The copied object is located on newly allocated zone.
613 * @param obj copy source object
614 *
615 * @return object_handle that holds deep copied object and zone.
616 */
617 inline object_handle clone(msgpack::object const& obj) {
618 std::size_t size = msgpack::aligned_zone_size(obj);
619 msgpack::unique_ptr<msgpack::zone> z(size == 0 ? MSGPACK_NULLPTR : new msgpack::zone(size));
620 msgpack::object newobj = z.get() ? msgpack::object(obj, *z) : obj;
621 return object_handle(newobj, msgpack::move(z));
622 }
623
624 template <typename T>
625 inline object::implicit_type::operator T() { return obj.as<T>(); }
626
627 namespace detail {
628 template <typename Stream, typename T>
629 struct packer_serializer {
630 static msgpack::packer<Stream>& pack(msgpack::packer<Stream>& o, const T& v) {
631 v.msgpack_pack(o);
632 return o;
633 }
634 };
635 } // namespace detail
636
637 // Adaptor functors' member functions definitions.
638 template <typename T, typename Enabler>
639 inline
640 msgpack::object const&
641 adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
642 v.msgpack_unpack(o.convert());
643 return o;
644 }
645
646 template <typename T, typename Enabler>
647 template <typename Stream>
648 inline
649 msgpack::packer<Stream>&
650 adaptor::pack<T, Enabler>::operator()(msgpack::packer<Stream>& o, T const& v) const {
651 return msgpack::detail::packer_serializer<Stream, T>::pack(o, v);
652 }
653
654 template <typename T, typename Enabler>
655 inline
656 void
657 adaptor::object_with_zone<T, Enabler>::operator()(msgpack::object::with_zone& o, T const& v) const {
658 v.msgpack_object(static_cast<msgpack::object*>(&o), o.zone);
659 }
660
661 // Adaptor functor specialization to object
662 namespace adaptor {
663
664 template <>
665 struct convert<msgpack::object> {
666 msgpack::object const& operator()(msgpack::object const& o, msgpack::object& v) const {
667 v = o;
668 return o;
669 }
670 };
671
672 template <>
673 struct pack<msgpack::object> {
674 template <typename Stream>
675 msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, msgpack::object const& v) const {
676 object_pack_visitor<Stream> vis(o);
677 msgpack::object_parser(v).parse(vis);
678 return o;
679 }
680 };
681
682 template <>
683 struct object_with_zone<msgpack::object> {
684 void operator()(msgpack::object::with_zone& o, msgpack::object const& v) const {
685 object_with_zone_visitor vis(o);
686 msgpack::object_parser(v).parse(vis);
687 }
688 private:
689 struct object_with_zone_visitor {
690 explicit object_with_zone_visitor(msgpack::object::with_zone& owz)
691 :m_zone(owz.zone), m_ptr(&owz) {
692 m_objs.push_back(&owz);
693 }
694 bool visit_nil() {
695 m_ptr->type = msgpack::type::NIL;
696 return true;
697 }
698 bool visit_boolean(bool v) {
699 m_ptr->type = msgpack::type::BOOLEAN;
700 m_ptr->via.boolean = v;
701 return true;
702 }
703 bool visit_positive_integer(uint64_t v) {
704 m_ptr->type = msgpack::type::POSITIVE_INTEGER;
705 m_ptr->via.u64 = v;
706 return true;
707 }
708 bool visit_negative_integer(int64_t v) {
709 m_ptr->type = msgpack::type::NEGATIVE_INTEGER;
710 m_ptr->via.i64 = v;
711 return true;
712 }
713 bool visit_float32(float v) {
714 m_ptr->type = msgpack::type::FLOAT32;
715 m_ptr->via.f64 = v;
716 return true;
717 }
718 bool visit_float64(double v) {
719 m_ptr->type = msgpack::type::FLOAT64;
720 m_ptr->via.f64 = v;
721 return true;
722 }
723 bool visit_str(const char* v, uint32_t size) {
724 m_ptr->type = msgpack::type::STR;
725 m_ptr->via.str.size = size;
726 char* ptr = static_cast<char*>(m_zone.allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
727 m_ptr->via.str.ptr = ptr;
728 std::memcpy(ptr, v, size);
729 return true;
730 }
731 bool visit_bin(const char* v, uint32_t size) {
732 m_ptr->type = msgpack::type::BIN;
733 m_ptr->via.bin.size = size;
734 char* ptr = static_cast<char*>(m_zone.allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
735 m_ptr->via.bin.ptr = ptr;
736 std::memcpy(ptr, v, size);
737 return true;
738 }
739 bool visit_ext(const char* v, uint32_t size) {
740 m_ptr->type = msgpack::type::EXT;
741
742 // v contains type but length(size) doesn't count the type byte.
743 // See https://github.com/msgpack/msgpack/blob/master/spec.md#ext-format-family
744 m_ptr->via.ext.size = size - 1;
745
746 char* ptr = static_cast<char*>(m_zone.allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
747 m_ptr->via.ext.ptr = ptr;
748 std::memcpy(ptr, v, size);
749 return true;
750 }
751 bool start_array(uint32_t num_elements) {
752 m_ptr->type = msgpack::type::ARRAY;
753 m_ptr->via.array.ptr = static_cast<msgpack::object*>(
754 m_zone.allocate_align(
755 sizeof(msgpack::object) * num_elements, MSGPACK_ZONE_ALIGNOF(msgpack::object)));
756 m_ptr->via.array.size = num_elements;
757 m_objs.push_back(elem(m_ptr->via.array.ptr));
758 return true;
759 }
760 bool start_array_item() {
761 m_ptr = m_objs.back().get_item();
762 return true;
763 }
764 bool end_array_item() {
765 ++m_objs.back().as.obj;
766 return true;
767 }
768 bool end_array() {
769 m_objs.pop_back();
770 return true;
771 }
772 bool start_map(uint32_t num_kv_pairs) {
773 m_ptr->type = msgpack::type::MAP;
774 m_ptr->via.map.ptr = (msgpack::object_kv*)m_zone.allocate_align(
775 sizeof(msgpack::object_kv) * num_kv_pairs, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv));
776 m_ptr->via.map.size = num_kv_pairs;
777 m_objs.push_back(elem(m_ptr->via.map.ptr));
778 return true;
779 }
780 bool start_map_key() {
781 m_ptr = m_objs.back().get_key();
782 return true;
783 }
784 bool end_map_key() {
785 return true;
786 }
787 bool start_map_value() {
788 m_ptr = m_objs.back().get_val();
789 return true;
790 }
791 bool end_map_value() {
792 ++m_objs.back().as.kv;
793 return true;
794 }
795 bool end_map() {
796 m_objs.pop_back();
797 return true;
798 }
799 private:
800 struct elem {
801 elem(msgpack::object* obj)
802 :is_obj(true) {
803 as.obj = obj;
804 }
805 elem(msgpack::object_kv* kv)
806 :is_obj(false) {
807 as.kv = kv;
808 }
809 msgpack::object* get_item() {
810 return as.obj;
811 }
812 msgpack::object* get_key() {
813 return &as.kv->key;
814 }
815 msgpack::object* get_val() {
816 return &as.kv->val;
817 }
818 union {
819 msgpack::object* obj;
820 msgpack::object_kv* kv;
821 } as;
822 bool is_obj;
823 };
824 std::vector<elem> m_objs;
825 msgpack::zone& m_zone;
826 msgpack::object* m_ptr;
827 };
828 };
829
830 // Adaptor functor specialization to object::with_zone
831
832 template <>
833 struct object_with_zone<msgpack::object::with_zone> {
834 void operator()(
835 msgpack::object::with_zone& o,
836 msgpack::object::with_zone const& v) const {
837 o << static_cast<msgpack::object const&>(v);
838 }
839 };
840
841
842 } // namespace adaptor
843
844
845 // obsolete
846 template <typename Type>
847 class define : public Type {
848 public:
849 typedef Type msgpack_type;
850 typedef define<Type> define_type;
851 define() {}
852 define(const msgpack_type& v) : msgpack_type(v) {}
853
854 template <typename Packer>
855 void msgpack_pack(Packer& o) const
856 {
857 msgpack::operator<<(o, static_cast<const msgpack_type&>(*this));
858 }
859
860 void msgpack_unpack(object const& o)
861 {
862 msgpack::operator>>(o, static_cast<msgpack_type&>(*this));
863 }
864 };
865
866 // deconvert operator
867
868 template <typename Stream>
869 template <typename T>
870 inline msgpack::packer<Stream>& packer<Stream>::pack(const T& v)
871 {
872 msgpack::operator<<(*this, v);
873 return *this;
874 }
875
876 struct object_equal_visitor {
877 object_equal_visitor(msgpack::object const& obj, bool& result)
878 :m_ptr(&obj), m_result(result) {}
879 bool visit_nil() {
880 if (m_ptr->type != msgpack::type::NIL) {
881 m_result = false;
882 return false;
883 }
884 return true;
885 }
886 bool visit_boolean(bool v) {
887 if (m_ptr->type != msgpack::type::BOOLEAN || m_ptr->via.boolean != v) {
888 m_result = false;
889 return false;
890 }
891 return true;
892 }
893 bool visit_positive_integer(uint64_t v) {
894 if (m_ptr->type != msgpack::type::POSITIVE_INTEGER || m_ptr->via.u64 != v) {
895 m_result = false;
896 return false;
897 }
898 return true;
899 }
900 bool visit_negative_integer(int64_t v) {
901 if (m_ptr->type != msgpack::type::NEGATIVE_INTEGER || m_ptr->via.i64 != v) {
902 m_result = false;
903 return false;
904 }
905 return true;
906 }
907 bool visit_float32(float v) {
908 if (m_ptr->type != msgpack::type::FLOAT32 || m_ptr->via.f64 != v) {
909 m_result = false;
910 return false;
911 }
912 return true;
913 }
914 bool visit_float64(double v) {
915 if (m_ptr->type != msgpack::type::FLOAT64 || m_ptr->via.f64 != v) {
916 m_result = false;
917 return false;
918 }
919 return true;
920 }
921 bool visit_str(const char* v, uint32_t size) {
922 if (m_ptr->type != msgpack::type::STR ||
923 m_ptr->via.str.size != size ||
924 std::memcmp(m_ptr->via.str.ptr, v, size) != 0) {
925 m_result = false;
926 return false;
927 }
928 return true;
929 }
930 bool visit_bin(const char* v, uint32_t size) {
931 if (m_ptr->type != msgpack::type::BIN ||
932 m_ptr->via.bin.size != size ||
933 std::memcmp(m_ptr->via.bin.ptr, v, size) != 0) {
934 m_result = false;
935 return false;
936 }
937 return true;
938 }
939 bool visit_ext(const char* v, uint32_t size) {
940 if (m_ptr->type != msgpack::type::EXT ||
941 m_ptr->via.ext.size != size ||
942 std::memcmp(m_ptr->via.ext.ptr, v, size) != 0) {
943 m_result = false;
944 return false;
945 }
946 return true;
947 }
948 bool start_array(uint32_t num_elements) {
949 if (m_ptr->type != msgpack::type::ARRAY ||
950 m_ptr->via.array.size != num_elements) {
951 m_result = false;
952 return false;
953 }
954 m_objs.push_back(elem(m_ptr->via.array.ptr));
955 return true;
956 }
957 bool start_array_item() {
958 m_ptr = m_objs.back().get_item();
959 return true;
960 }
961 bool end_array_item() {
962 ++m_objs.back().as.obj;
963 return true;
964 }
965 bool end_array() {
966 m_objs.pop_back();
967 return true;
968 }
969 bool start_map(uint32_t num_kv_pairs) {
970 if (m_ptr->type != msgpack::type::MAP ||
971 m_ptr->via.array.size != num_kv_pairs) {
972 m_result = false;
973 return false;
974 }
975 m_objs.push_back(elem(m_ptr->via.map.ptr));
976 return true;
977 }
978 bool start_map_key() {
979 m_ptr = m_objs.back().get_key();
980 return true;
981 }
982 bool end_map_key() {
983 return true;
984 }
985 bool start_map_value() {
986 m_ptr = m_objs.back().get_val();
987 return true;
988 }
989 bool end_map_value() {
990 ++m_objs.back().as.kv;
991 return true;
992 }
993 bool end_map() {
994 m_objs.pop_back();
995 return true;
996 }
997 private:
998 struct elem {
999 elem(msgpack::object const* obj)
1000 :is_obj(true) {
1001 as.obj = obj;
1002 }
1003 elem(msgpack::object_kv const* kv)
1004 :is_obj(false) {
1005 as.kv = kv;
1006 }
1007 msgpack::object const* get_item() {
1008 return as.obj;
1009 }
1010 msgpack::object const* get_key() {
1011 return &as.kv->key;
1012 }
1013 msgpack::object const* get_val() {
1014 return &as.kv->val;
1015 }
1016 union {
1017 msgpack::object const* obj;
1018 msgpack::object_kv const* kv;
1019 } as;
1020 bool is_obj;
1021 };
1022 std::vector<elem> m_objs;
1023 msgpack::object const* m_ptr;
1024 bool& m_result;
1025 };
1026
1027 inline bool operator==(const msgpack::object& x, const msgpack::object& y)
1028 {
1029 if(x.type != y.type) { return false; }
1030 bool b = true;
1031 object_equal_visitor vis(y, b);
1032 msgpack::object_parser(x).parse(vis);
1033 return b;
1034 }
1035
1036 template <typename T>
1037 inline bool operator==(const msgpack::object& x, const T& y)
1038 try {
1039 return x == msgpack::object(y);
1040 } catch (msgpack::type_error&) {
1041 return false;
1042 }
1043
1044 inline bool operator!=(const msgpack::object& x, const msgpack::object& y)
1045 { return !(x == y); }
1046
1047 template <typename T>
1048 inline bool operator==(const T& y, const msgpack::object& x)
1049 { return x == y; }
1050
1051 template <typename T>
1052 inline bool operator!=(const msgpack::object& x, const T& y)
1053 { return !(x == y); }
1054
1055 template <typename T>
1056 inline bool operator!=(const T& y, const msgpack::object& x)
1057 { return x != y; }
1058
1059
1060 inline object::implicit_type object::convert() const
1061 {
1062 return object::implicit_type(*this);
1063 }
1064
1065 template <typename T>
1066 inline
1067 typename msgpack::enable_if<
1068 !msgpack::is_array<T>::value && !msgpack::is_pointer<T>::value,
1069 T&
1070 >::type
1071 object::convert(T& v) const
1072 {
1073 msgpack::operator>>(*this, v);
1074 return v;
1075 }
1076
1077 template <typename T, std::size_t N>
1078 inline T(&object::convert(T(&v)[N]) const)[N]
1079 {
1080 msgpack::operator>>(*this, v);
1081 return v;
1082 }
1083
1084 #if !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
1085 template <typename T>
1086 inline
1087 typename msgpack::enable_if<
1088 msgpack::is_pointer<T>::value,
1089 T
1090 >::type
1091 object::convert(T v) const
1092 {
1093 convert(*v);
1094 return v;
1095 }
1096 #endif // !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
1097
1098 template <typename T>
1099 inline bool object::convert_if_not_nil(T& v) const
1100 {
1101 if (is_nil()) {
1102 return false;
1103 }
1104 convert(v);
1105 return true;
1106 }
1107
1108 #if defined(MSGPACK_USE_CPP03)
1109
1110 template <typename T>
1111 inline T object::as() const
1112 {
1113 T v;
1114 convert(v);
1115 return v;
1116 }
1117
1118 #else // defined(MSGPACK_USE_CPP03)
1119
1120 template <typename T>
1121 inline typename std::enable_if<msgpack::has_as<T>::value, T>::type object::as() const {
1122 return msgpack::adaptor::as<T>()(*this);
1123 }
1124
1125 template <typename T>
1126 inline typename std::enable_if<!msgpack::has_as<T>::value, T>::type object::as() const {
1127 T v;
1128 convert(v);
1129 return v;
1130 }
1131
1132 #endif // defined(MSGPACK_USE_CPP03)
1133
1134 inline object::object()
1135 {
1136 type = msgpack::type::NIL;
1137 }
1138
1139 template <typename T>
1140 inline object::object(const T& v)
1141 {
1142 *this << v;
1143 }
1144
1145 template <typename T>
1146 inline object& object::operator=(const T& v)
1147 {
1148 *this = object(v);
1149 return *this;
1150 }
1151
1152 template <typename T>
1153 inline object::object(const T& v, msgpack::zone& z)
1154 {
1155 with_zone oz(z);
1156 msgpack::operator<<(oz, v);
1157 type = oz.type;
1158 via = oz.via;
1159 }
1160
1161 template <typename T>
1162 inline object::object(const T& v, msgpack::zone* z)
1163 {
1164 with_zone oz(*z);
1165 msgpack::operator<<(oz, v);
1166 type = oz.type;
1167 via = oz.via;
1168 }
1169
1170
1171 inline object::object(const msgpack_object& o)
1172 {
1173 // FIXME beter way?
1174 std::memcpy(this, &o, sizeof(o));
1175 }
1176
1177 inline void operator<< (msgpack::object& o, const msgpack_object& v)
1178 {
1179 // FIXME beter way?
1180 std::memcpy(static_cast<void*>(&o), &v, sizeof(v));
1181 }
1182
1183 inline object::operator msgpack_object() const
1184 {
1185 // FIXME beter way?
1186 msgpack_object obj;
1187 std::memcpy(&obj, this, sizeof(obj));
1188 return obj;
1189 }
1190
1191
1192 // obsolete
1193 template <typename T>
1194 inline void convert(T& v, msgpack::object const& o)
1195 {
1196 o.convert(v);
1197 }
1198
1199 // obsolete
1200 template <typename Stream, typename T>
1201 inline void pack(msgpack::packer<Stream>& o, const T& v)
1202 {
1203 o.pack(v);
1204 }
1205
1206 // obsolete
1207 template <typename Stream, typename T>
1208 inline void pack_copy(msgpack::packer<Stream>& o, T v)
1209 {
1210 pack(o, v);
1211 }
1212
1213 template <typename Stream>
1214 inline msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const msgpack::object& v)
1215 {
1216 object_pack_visitor<Stream> vis(o);
1217 msgpack::object_parser(v).parse(vis);
1218 return o;
1219 }
1220
1221 template <typename Stream>
1222 inline msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const msgpack::object::with_zone& v)
1223 {
1224 return o << static_cast<msgpack::object>(v);
1225 }
1226
1227 inline std::ostream& operator<< (std::ostream& s, const msgpack::object& v)
1228 {
1229 object_stringize_visitor vis(s);
1230 msgpack::object_parser(v).parse(vis);
1231 return s;
1232 }
1233
1234 /// @cond
1235 } // MSGPACK_API_VERSION_NAMESPACE(v1)
1236 /// @endcond
1237
1238 } // namespace msgpack
1239
1240 #endif // MSGPACK_V1_OBJECT_HPP
1241