messagepack implementation for embedded systems (mbed / arduino)

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers object.hpp Source File

object.hpp

00001 //
00002 // MessagePack for C++ static resolution routine
00003 //
00004 // Copyright (C) 2008-2014 FURUHASHI Sadayuki and KONDO Takatoshi
00005 //
00006 //    Distributed under the Boost Software License, Version 1.0.
00007 //    (See accompanying file LICENSE_1_0.txt or copy at
00008 //    http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 #ifndef MSGPACK_OBJECT_HPP
00011 #define MSGPACK_OBJECT_HPP
00012 
00013 #include "msgpack/versioning.hpp"
00014 #include "msgpack/pack.hpp"
00015 #include "msgpack/zone.hpp"
00016 #include "msgpack/adaptor/adaptor_base.hpp"
00017 
00018 #include <cstring>
00019 #include <stdexcept>
00020 #include <typeinfo>
00021 #include <limits>
00022 #include <ostream>
00023 #include <typeinfo>
00024 #include <iomanip>
00025 
00026 namespace msgpack {
00027 
00028 /// @cond
00029 MSGPACK_API_VERSION_NAMESPACE(v1) {
00030 /// @endcond
00031 
00032 /// The class holds object and zone
00033 class object_handle  {
00034 public:
00035     /// Constructor that creates nil object and null zone.
00036     object_handle() {}
00037 
00038     /// Constructor that creates an object_handle holding object `obj` and zone `z`.
00039     /**
00040      * @param obj object
00041      * @param z zone
00042      */
00043     object_handle(msgpack::object const& obj, msgpack::unique_ptr<msgpack::zone> z) :
00044         m_obj(obj), m_zone(msgpack::move(z)) { }
00045 
00046     // obsolete
00047     void set(msgpack::object const& obj)
00048         { m_obj = obj; }
00049 
00050     /// Get object reference
00051     /**
00052      * @return object
00053      */
00054     const msgpack::object& get() const
00055         { return m_obj; }
00056 
00057     /// Get unique_ptr reference of zone.
00058     /**
00059      * @return unique_ptr reference of zone
00060      */
00061     msgpack::unique_ptr<msgpack::zone>& zone()
00062         { return m_zone; }
00063 
00064     /// Get unique_ptr const reference of zone.
00065     /**
00066      * @return unique_ptr const reference of zone
00067      */
00068     const msgpack::unique_ptr<msgpack::zone>& zone() const
00069         { return m_zone; }
00070 
00071 #if defined(MSGPACK_USE_CPP03)
00072     struct object_handle_ref {
00073         object_handle_ref(object_handle * oh):m_oh(oh) {}
00074         object_handle* m_oh;
00075     };
00076 
00077     object_handle(object_handle& other):
00078         m_obj(other.m_obj),
00079         m_zone(msgpack::move(other.m_zone)) {
00080     }
00081 
00082     object_handle(object_handle_ref ref):
00083         m_obj(ref.m_oh->m_obj),
00084         m_zone(msgpack::move(ref.m_oh->m_zone)) {
00085     }
00086 
00087     object_handle& operator=(object_handle& other) {
00088         m_obj = other.m_obj;
00089         m_zone = msgpack::move(other.m_zone);
00090         return *this;
00091     }
00092 
00093     object_handle& operator=(object_handle_ref ref) {
00094         m_obj = ref.m_oh->m_obj;
00095         m_zone = msgpack::move(ref.m_oh->m_zone);
00096         return *this;
00097     }
00098 
00099     operator object_handle_ref() {
00100         return object_handle_ref(this);
00101     }
00102 #endif // defined(MSGPACK_USE_CPP03)
00103 
00104 private:
00105     msgpack::object m_obj;
00106     msgpack::unique_ptr<msgpack::zone> m_zone;
00107 };
00108 
00109 namespace detail {
00110 
00111 template <std::size_t N>
00112 inline std::size_t add_ext_type_size(std::size_t size) {
00113     return size + 1;
00114 }
00115 
00116 template <>
00117 inline std::size_t add_ext_type_size<4>(std::size_t size) {
00118     return size == 0xffffffff ? size : size + 1;
00119 }
00120 
00121 } // namespace detail
00122 
00123 inline std::size_t aligned_zone_size(msgpack::object const& obj) {
00124     std::size_t s = 0;
00125     switch (obj.type) {
00126     case msgpack::type::ARRAY:
00127         s += sizeof(msgpack::object) * obj.via.array.size;
00128         for (uint32_t i = 0; i < obj.via.array.size; ++i) {
00129             s += msgpack::aligned_zone_size(obj.via.array.ptr[i]);
00130         }
00131         break;
00132     case msgpack::type::MAP:
00133         s += sizeof(msgpack::object_kv) * obj.via.map.size;
00134         for (uint32_t i = 0; i < obj.via.map.size; ++i) {
00135             s += msgpack::aligned_zone_size(obj.via.map.ptr[i].key);
00136             s += msgpack::aligned_zone_size(obj.via.map.ptr[i].val);
00137         }
00138         break;
00139     case msgpack::type::EXT:
00140         s += msgpack::aligned_size(
00141             detail::add_ext_type_size<sizeof(std::size_t)>(obj.via.ext.size));
00142         break;
00143     case msgpack::type::STR:
00144         s += msgpack::aligned_size(obj.via.str.size);
00145         break;
00146     case msgpack::type::BIN:
00147         s += msgpack::aligned_size(obj.via.bin.size);
00148         break;
00149     default:
00150         break;
00151     }
00152     return s;
00153 }
00154 
00155 /// clone object
00156 /**
00157  * Clone (deep copy) object.
00158  * The copied object is located on newly allocated zone.
00159  * @param obj copy source object
00160  *
00161  * @return object_handle that holds deep copied object and zone.
00162  */
00163 inline object_handle clone(msgpack::object const& obj) {
00164     std::size_t size = msgpack::aligned_zone_size(obj);
00165     msgpack::unique_ptr<msgpack::zone> z(size == 0 ? nullptr : new msgpack::zone(size));
00166     msgpack::object newobj = z.get() ? msgpack::object(obj, *z) : obj;
00167     return object_handle(newobj, msgpack::move(z));
00168 }
00169 
00170 struct object::implicit_type {
00171     implicit_type(object const& o) : obj(o) { }
00172     ~implicit_type() { }
00173 
00174     template <typename T>
00175     operator T() { return obj.as<T>(); }
00176 
00177 private:
00178     msgpack::object const& obj;
00179 };
00180 
00181 namespace detail {
00182 template <typename Stream, typename T>
00183 struct packer_serializer {
00184     static msgpack::packer<Stream> & pack(msgpack::packer<Stream> & o, const T& v) {
00185         v.msgpack_pack(o);
00186         return o;
00187     }
00188 };
00189 } // namespace detail
00190 
00191 // Adaptor functors' member functions definitions.
00192 template <typename T, typename Enabler>
00193 inline
00194 msgpack::object const&
00195 msgpack::adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
00196     v.msgpack_unpack(o.convert());
00197     return o;
00198 }
00199 
00200 template <typename T, typename Enabler>
00201 template <typename Stream>
00202 inline
00203 msgpack::packer<Stream> &
00204 msgpack::adaptor::pack<T, Enabler>::operator()(msgpack::packer<Stream> & o, T const& v) const {
00205     return msgpack::detail::packer_serializer<Stream, T>::pack(o, v);
00206 }
00207 
00208 template <typename T, typename Enabler>
00209 inline
00210 void
00211 msgpack::adaptor::object_with_zone<T, Enabler>::operator()(msgpack::object::with_zone& o, T const& v) const {
00212     v.msgpack_object(static_cast<msgpack::object*>(&o), o.zone);
00213 }
00214 
00215 // Adaptor functor specialization to object
00216 namespace adaptor {
00217 
00218 template <>
00219 struct convert<msgpack::object> {
00220     msgpack::object const& operator()(msgpack::object const& o, msgpack::object& v) const {
00221         v = o;
00222         return o;
00223     }
00224 };
00225 
00226 template <>
00227 struct pack<msgpack::object> {
00228     template <typename Stream>
00229     msgpack::packer<Stream> & operator()(msgpack::packer<Stream> & o, msgpack::object const& v) const {
00230         switch(v.type) {
00231         case msgpack::type::NIL:
00232             o.pack_nil();
00233             return o;
00234 
00235         case msgpack::type::BOOLEAN:
00236             if(v.via.boolean) {
00237                 o.pack_true();
00238             } else {
00239                 o.pack_false();
00240             }
00241             return o;
00242 
00243         case msgpack::type::POSITIVE_INTEGER:
00244             o.pack_uint64(v.via.u64);
00245             return o;
00246 
00247         case msgpack::type::NEGATIVE_INTEGER:
00248             o.pack_int64(v.via.i64);
00249             return o;
00250 
00251         case msgpack::type::FLOAT:
00252             o.pack_double(v.via.f64);
00253             return o;
00254 
00255         case msgpack::type::STR:
00256             o.pack_str(v.via.str.size);
00257             o.pack_str_body(v.via.str.ptr, v.via.str.size);
00258             return o;
00259 
00260         case msgpack::type::BIN:
00261             o.pack_bin(v.via.bin.size);
00262             o.pack_bin_body(v.via.bin.ptr, v.via.bin.size);
00263             return o;
00264 
00265         case msgpack::type::EXT:
00266             o.pack_ext(v.via.ext.size, v.via.ext.type());
00267             o.pack_ext_body(v.via.ext.data(), v.via.ext.size);
00268             return o;
00269 
00270         case msgpack::type::ARRAY:
00271             o.pack_array(v.via.array.size);
00272             for(msgpack::object* p(v.via.array.ptr),
00273                     * const pend(v.via.array.ptr + v.via.array.size);
00274                 p < pend; ++p) {
00275                 msgpack::operator<<(o, *p);
00276             }
00277             return o;
00278 
00279         case msgpack::type::MAP:
00280             o.pack_map(v.via.map.size);
00281             for(msgpack::object_kv* p(v.via.map.ptr),
00282                     * const pend(v.via.map.ptr + v.via.map.size);
00283                 p < pend; ++p) {
00284                 msgpack::operator<<(o, p->key);
00285                 msgpack::operator<<(o, p->val);
00286             }
00287             return o;
00288 
00289         default:
00290             throw msgpack::type_error();
00291         }
00292     }
00293 };
00294 
00295 template <>
00296 struct object_with_zone<msgpack::object> {
00297     void operator()(msgpack::object::with_zone& o, msgpack::object const& v) const {
00298         o.type = v.type;
00299 
00300         switch(v.type) {
00301         case msgpack::type::NIL:
00302         case msgpack::type::BOOLEAN:
00303         case msgpack::type::POSITIVE_INTEGER:
00304         case msgpack::type::NEGATIVE_INTEGER:
00305         case msgpack::type::FLOAT:
00306             std::memcpy(&o.via, &v.via, sizeof(v.via));
00307             return;
00308 
00309         case msgpack::type::STR: {
00310             char* ptr = static_cast<char*>(o.zone.allocate_align(v.via.str.size));
00311             o.via.str.ptr = ptr;
00312             o.via.str.size = v.via.str.size;
00313             std::memcpy(ptr, v.via.str.ptr, v.via.str.size);
00314             return;
00315         }
00316 
00317         case msgpack::type::BIN: {
00318             char* ptr = static_cast<char*>(o.zone.allocate_align(v.via.bin.size));
00319             o.via.bin.ptr = ptr;
00320             o.via.bin.size = v.via.bin.size;
00321             std::memcpy(ptr, v.via.bin.ptr, v.via.bin.size);
00322             return;
00323         }
00324 
00325         case msgpack::type::EXT: {
00326             char* ptr = static_cast<char*>(o.zone.allocate_align(v.via.ext.size + 1));
00327             o.via.ext.ptr = ptr;
00328             o.via.ext.size = v.via.ext.size;
00329             std::memcpy(ptr, v.via.ext.ptr, v.via.ext.size + 1);
00330             return;
00331         }
00332 
00333         case msgpack::type::ARRAY:
00334             o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object) * v.via.array.size));
00335             o.via.array.size = v.via.array.size;
00336             for (msgpack::object
00337                      * po(o.via.array.ptr),
00338                      * pv(v.via.array.ptr),
00339                      * const pvend(v.via.array.ptr + v.via.array.size);
00340                  pv < pvend;
00341                  ++po, ++pv) {
00342                 new (po) msgpack::object(*pv, o.zone);
00343             }
00344             return;
00345 
00346         case msgpack::type::MAP:
00347             o.via.map.ptr = (msgpack::object_kv*)o.zone.allocate_align(sizeof(msgpack::object_kv) * v.via.map.size);
00348             o.via.map.size = v.via.map.size;
00349             for(msgpack::object_kv
00350                     * po(o.via.map.ptr),
00351                     * pv(v.via.map.ptr),
00352                     * const pvend(v.via.map.ptr + v.via.map.size);
00353                 pv < pvend;
00354                 ++po, ++pv) {
00355                 msgpack::object_kv* kv = new (po) msgpack::object_kv;
00356                 new (&kv->key) msgpack::object(pv->key, o.zone);
00357                 new (&kv->val) msgpack::object(pv->val, o.zone);
00358             }
00359             return;
00360 
00361         default:
00362             ;
00363 //            throw msgpack::type_error();
00364         }
00365 
00366     }
00367 };
00368 
00369 // Adaptor functor specialization to object::with_zone
00370 
00371 template <>
00372 struct object_with_zone<msgpack::object::with_zone> {
00373     void operator()(
00374         msgpack::object::with_zone& o,
00375         msgpack::object::with_zone const& v) const {
00376         o << static_cast<msgpack::object const&>(v);
00377     }
00378 };
00379 
00380 
00381 } // namespace adaptor
00382 
00383 
00384 // obsolete
00385 template <typename Type>
00386 class define : public Type {
00387 public:
00388     typedef Type msgpack_type;
00389     typedef define<Type> define_type;
00390 
00391     define() {}
00392     define(const msgpack_type& v) : msgpack_type(v) {}
00393 
00394     template <typename Packer>
00395     void msgpack_pack(Packer& o) const
00396     {
00397         msgpack::operator<<(o, static_cast<const msgpack_type&>(*this));
00398     }
00399 
00400     void msgpack_unpack(object const& o)
00401     {
00402         msgpack::operator>>(o, static_cast<msgpack_type&>(*this));
00403     }
00404 };
00405 
00406 // deconvert operator
00407 
00408 template <typename Stream>
00409 template <typename T>
00410 inline msgpack::packer<Stream> & packer<Stream>::pack(const T& v)
00411 {
00412     msgpack::operator<<(*this, v);
00413     return *this;
00414 }
00415 
00416 inline bool operator==(const msgpack::object& x, const msgpack::object& y)
00417 {
00418     if(x.type != y.type) { return false; }
00419 
00420     switch(x.type) {
00421     case msgpack::type::NIL:
00422         return true;
00423 
00424     case msgpack::type::BOOLEAN:
00425         return x.via.boolean == y.via.boolean;
00426 
00427     case msgpack::type::POSITIVE_INTEGER:
00428         return x.via.u64 == y.via.u64;
00429 
00430     case msgpack::type::NEGATIVE_INTEGER:
00431         return x.via.i64 == y.via.i64;
00432 
00433     case msgpack::type::FLOAT:
00434         return x.via.f64 == y.via.f64;
00435 
00436     case msgpack::type::STR:
00437         return x.via.str.size == y.via.str.size &&
00438             std::memcmp(x.via.str.ptr, y.via.str.ptr, x.via.str.size) == 0;
00439 
00440     case msgpack::type::BIN:
00441         return x.via.bin.size == y.via.bin.size &&
00442             std::memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0;
00443 
00444     case msgpack::type::EXT:
00445         return x.via.ext.size == y.via.ext.size &&
00446             std::memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0;
00447 
00448     case msgpack::type::ARRAY:
00449         if(x.via.array.size != y.via.array.size) {
00450             return false;
00451         } else if(x.via.array.size == 0) {
00452             return true;
00453         } else {
00454             msgpack::object* px = x.via.array.ptr;
00455             msgpack::object* const pxend = x.via.array.ptr + x.via.array.size;
00456             msgpack::object* py = y.via.array.ptr;
00457             do {
00458                 if(!(*px == *py)) {
00459                     return false;
00460                 }
00461                 ++px;
00462                 ++py;
00463             } while(px < pxend);
00464             return true;
00465         }
00466 
00467     case msgpack::type::MAP:
00468         if(x.via.map.size != y.via.map.size) {
00469             return false;
00470         } else if(x.via.map.size == 0) {
00471             return true;
00472         } else {
00473             msgpack::object_kv* px = x.via.map.ptr;
00474             msgpack::object_kv* const pxend = x.via.map.ptr + x.via.map.size;
00475             msgpack::object_kv* py = y.via.map.ptr;
00476             do {
00477                 if(!(px->key == py->key) || !(px->val == py->val)) {
00478                     return false;
00479                 }
00480                 ++px;
00481                 ++py;
00482             } while(px < pxend);
00483             return true;
00484         }
00485 
00486     default:
00487         return false;
00488     }
00489 }
00490 
00491 template <typename T>
00492 inline bool operator==(const msgpack::object& x, const T& y)
00493 try {
00494     return x == msgpack::object(y);
00495 } catch (msgpack::type_error&) {
00496     return false;
00497 }
00498 
00499 inline bool operator!=(const msgpack::object& x, const msgpack::object& y)
00500 { return !(x == y); }
00501 
00502 template <typename T>
00503 inline bool operator==(const T& y, const msgpack::object& x)
00504 { return x == y; }
00505 
00506 template <typename T>
00507 inline bool operator!=(const msgpack::object& x, const T& y)
00508 { return !(x == y); }
00509 
00510 template <typename T>
00511 inline bool operator!=(const T& y, const msgpack::object& x)
00512 { return x != y; }
00513 
00514 
00515 inline msgpack::object::implicit_type object::convert() const
00516 {
00517     return msgpack::object::implicit_type(*this);
00518 }
00519 
00520 template <typename T>
00521 inline T& object::convert(T& v) const
00522 {
00523     msgpack::operator>>(*this, v);
00524     return v;
00525 }
00526 
00527 #if !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
00528 template <typename T>
00529 inline T* object::convert(T* v) const
00530 {
00531     convert(*v);
00532     return v;
00533 }
00534 #endif // !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
00535 
00536 template <typename T>
00537 inline bool object::convert_if_not_nil(T& v) const
00538 {
00539     if (is_nil()) {
00540         return false;
00541     }
00542     convert(v);
00543     return true;
00544 }
00545 
00546 #if defined(MSGPACK_USE_CPP03)
00547 
00548 template <typename T>
00549 inline T object::as() const
00550 {
00551     T v;
00552     convert(v);
00553     return v;
00554 }
00555 
00556 #else  // defined(MSGPACK_USE_CPP03)
00557 
00558 template <typename T>
00559 inline typename std::enable_if<msgpack::has_as<T>::value, T>::type object::as() const {
00560     return msgpack::adaptor::as<T>()(*this);
00561 }
00562 
00563 template <typename T>
00564 inline typename std::enable_if<!msgpack::has_as<T>::value, T>::type object::as() const {
00565     T v;
00566     convert(v);
00567     return v;
00568 }
00569 
00570 #endif // defined(MSGPACK_USE_CPP03)
00571 
00572 inline object::object()
00573 {
00574     type = msgpack::type::NIL;
00575 }
00576 
00577 template <typename T>
00578 inline object::object(const T& v)
00579 {
00580     msgpack::operator<<(*this, v);
00581 }
00582 
00583 template <typename T>
00584 inline object& object::operator=(const T& v)
00585 {
00586     *this = object(v);
00587     return *this;
00588 }
00589 
00590 template <typename T>
00591 object::object(const T& v, msgpack::zone& z)
00592 {
00593     with_zone oz(z);
00594     msgpack::operator<<(oz, v);
00595     type = oz.type;
00596     via = oz.via;
00597 }
00598 
00599 template <typename T>
00600 object::object(const T& v, msgpack::zone* z)
00601 {
00602     with_zone oz(*z);
00603     msgpack::operator<<(oz, v);
00604     type = oz.type;
00605     via = oz.via;
00606 }
00607 
00608 
00609 inline object::object(const msgpack_object& o)
00610 {
00611     // FIXME beter way?
00612     std::memcpy(this, &o, sizeof(o));
00613 }
00614 
00615 inline void operator<< (msgpack::object& o, const msgpack_object& v)
00616 {
00617     // FIXME beter way?
00618     std::memcpy(&o, &v, sizeof(v));
00619 }
00620 
00621 inline object::operator msgpack_object() const
00622 {
00623     // FIXME beter way?
00624     msgpack_object obj;
00625     std::memcpy(&obj, this, sizeof(obj));
00626     return obj;
00627 }
00628 
00629 
00630 // obsolete
00631 template <typename T>
00632 inline void convert(T& v, msgpack::object const& o)
00633 {
00634     o.convert(v);
00635 }
00636 
00637 // obsolete
00638 template <typename Stream, typename T>
00639 inline void pack(msgpack::packer<Stream> & o, const T& v)
00640 {
00641     o.pack(v);
00642 }
00643 
00644 // obsolete
00645 template <typename Stream, typename T>
00646 inline void pack_copy(msgpack::packer<Stream> & o, T v)
00647 {
00648     pack(o, v);
00649 }
00650 
00651 
00652 template <typename Stream>
00653 inline msgpack::packer<Stream> & operator<< (msgpack::packer<Stream>& o, const msgpack::object& v)
00654 {
00655     switch(v.type) {
00656     case msgpack::type::NIL:
00657         o.pack_nil();
00658         return o;
00659 
00660     case msgpack::type::BOOLEAN:
00661         if(v.via.boolean) {
00662             o.pack_true();
00663         } else {
00664             o.pack_false();
00665         }
00666         return o;
00667 
00668     case msgpack::type::POSITIVE_INTEGER:
00669         o.pack_uint64(v.via.u64);
00670         return o;
00671 
00672     case msgpack::type::NEGATIVE_INTEGER:
00673         o.pack_int64(v.via.i64);
00674         return o;
00675 
00676     case msgpack::type::FLOAT:
00677         o.pack_double(v.via.f64);
00678         return o;
00679 
00680     case msgpack::type::STR:
00681         o.pack_str(v.via.str.size);
00682         o.pack_str_body(v.via.str.ptr, v.via.str.size);
00683         return o;
00684 
00685     case msgpack::type::BIN:
00686         o.pack_bin(v.via.bin.size);
00687         o.pack_bin_body(v.via.bin.ptr, v.via.bin.size);
00688         return o;
00689 
00690     case msgpack::type::EXT:
00691         o.pack_ext(v.via.ext.size, v.via.ext.type());
00692         o.pack_ext_body(v.via.ext.data(), v.via.ext.size);
00693         return o;
00694 
00695     case msgpack::type::ARRAY:
00696         o.pack_array(v.via.array.size);
00697         for(msgpack::object* p(v.via.array.ptr),
00698                 * const pend(v.via.array.ptr + v.via.array.size);
00699                 p < pend; ++p) {
00700             msgpack::operator<<(o, *p);
00701         }
00702         return o;
00703 
00704     case msgpack::type::MAP:
00705         o.pack_map(v.via.map.size);
00706         for(msgpack::object_kv* p(v.via.map.ptr),
00707                 * const pend(v.via.map.ptr + v.via.map.size);
00708                 p < pend; ++p) {
00709             msgpack::operator<<(o, p->key);
00710             msgpack::operator<<(o, p->val);
00711         }
00712         return o;
00713 
00714     default:
00715         throw msgpack::type_error();
00716     }
00717 }
00718 
00719 template <typename Stream>
00720 msgpack::packer<Stream> & operator<< (msgpack::packer<Stream>& o, const msgpack::object::with_zone& v)
00721 {
00722     return o << static_cast<msgpack::object>(v);
00723 }
00724 
00725 inline std::ostream& operator<< (std::ostream& s, const msgpack::object& o)
00726 {
00727     switch(o.type) {
00728     case msgpack::type::NIL:
00729         s << "nil";
00730         break;
00731 
00732     case msgpack::type::BOOLEAN:
00733         s << (o.via.boolean ? "true" : "false");
00734         break;
00735 
00736     case msgpack::type::POSITIVE_INTEGER:
00737         s << o.via.u64;
00738         break;
00739 
00740     case msgpack::type::NEGATIVE_INTEGER:
00741         s << o.via.i64;
00742         break;
00743 
00744     case msgpack::type::FLOAT:
00745         s << o.via.f64;
00746         break;
00747 
00748     case msgpack::type::STR:
00749         s << '"';
00750         for (uint32_t i = 0; i < o.via.str.size; ++i) {
00751             char c = o.via.str.ptr[i];
00752             switch (c) {
00753             case '\\':
00754                 s << "\\\\";
00755                 break;
00756             case '"':
00757                 s << "\\\"";
00758                 break;
00759             case '/':
00760                 s << "\\/";
00761                 break;
00762             case '\b':
00763                 s << "\\b";
00764                 break;
00765             case '\f':
00766                 s << "\\f";
00767                 break;
00768             case '\n':
00769                 s << "\\n";
00770                 break;
00771             case '\r':
00772                 s << "\\r";
00773                 break;
00774             case '\t':
00775                 s << "\\t";
00776                 break;
00777             default: {
00778                 unsigned int code = static_cast<unsigned int>(c);
00779                 if (code < 0x20 || code == 0x7f) {
00780                     s << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (code & 0xff);
00781                 }
00782                 else {
00783                     s << c;
00784                 }
00785             } break;
00786             }
00787         }
00788         s << '"';
00789         break;
00790 
00791     case msgpack::type::BIN:
00792         (s << '"').write(o.via.bin.ptr, o.via.bin.size) << '"';
00793         break;
00794 
00795     case msgpack::type::EXT:
00796         s << "EXT";
00797         break;
00798 
00799     case msgpack::type::ARRAY:
00800         s << "[";
00801         if(o.via.array.size != 0) {
00802             msgpack::object* p(o.via.array.ptr);
00803             s << *p;
00804             ++p;
00805             for(msgpack::object* const pend(o.via.array.ptr + o.via.array.size);
00806                     p < pend; ++p) {
00807                 s << ", " << *p;
00808             }
00809         }
00810         s << "]";
00811         break;
00812 
00813     case msgpack::type::MAP:
00814         s << "{";
00815         if(o.via.map.size != 0) {
00816             msgpack::object_kv* p(o.via.map.ptr);
00817             s << p->key << ':' << p->val;
00818             ++p;
00819             for(msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
00820                     p < pend; ++p) {
00821                 s << ", " << p->key << ':' << p->val;
00822             }
00823         }
00824         s << "}";
00825         break;
00826 
00827     default:
00828         // FIXME
00829         s << "#<UNKNOWN " << static_cast<uint16_t>(o.type) << ">";
00830     }
00831     return s;
00832 }
00833 
00834 /// @cond
00835 }  // MSGPACK_API_VERSION_NAMESPACE(v1)
00836 /// @endcond
00837 
00838 }  // namespace msgpack
00839 
00840 #include "msgpack/type.hpp"
00841 
00842 #endif /* msgpack/object.hpp */