messagepack implementation for embedded systems (mbed / arduino)

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers unpack.hpp Source File

unpack.hpp

00001 //
00002 // MessagePack for C++ deserializing routine
00003 //
00004 // Copyright (C) 2008-2015 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_UNPACK_HPP
00011 #define MSGPACK_UNPACK_HPP
00012 
00013 #include "msgpack/versioning.hpp"
00014 #include "object.hpp"
00015 #include "zone.hpp"
00016 #include "../unpack_define.h"
00017 #include "cpp_config.hpp"
00018 #include "../sysdep.h"
00019 
00020 #include <memory>
00021 #include <stdexcept>
00022 
00023 #if !defined(MSGPACK_USE_CPP03)
00024 #include <atomic>
00025 #endif
00026 
00027 
00028 #if defined(_MSC_VER)
00029 // avoiding confliction std::max, std::min, and macro in windows.h
00030 #ifndef NOMINMAX
00031 #define NOMINMAX
00032 #endif
00033 #endif // defined(_MSC_VER)
00034 
00035 #ifdef _msgpack_atomic_counter_header
00036 #include _msgpack_atomic_counter_header
00037 #endif
00038 
00039 
00040 const size_t COUNTER_SIZE = sizeof(_msgpack_atomic_counter_t);
00041 
00042 #ifndef MSGPACK_UNPACKER_INIT_BUFFER_SIZE
00043     #if defined(__MBED__)
00044         #define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (32*32)
00045     #elif defined(__AVR__)
00046         #define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (8*32)
00047     #else
00048         #define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (64*1024)
00049     #endif
00050 #endif
00051 
00052 #ifndef MSGPACK_UNPACKER_RESERVE_SIZE
00053     #if defined(__MBED__)
00054         #define MSGPACK_UNPACKER_RESERVE_SIZE (16*32)
00055     #elif defined(__AVR__)
00056         #define MSGPACK_UNPACKER_RESERVE_SIZE (4*32)
00057     #else
00058         #define MSGPACK_UNPACKER_RESERVE_SIZE (32*1024)
00059     #endif
00060 #endif
00061 
00062 
00063 // backward compatibility
00064 #ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
00065 #define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE MSGPACK_UNPACKER_INIT_BUFFER_SIZE
00066 #endif
00067 
00068 
00069 namespace msgpack {
00070 
00071 /// @cond
00072 MSGPACK_API_VERSION_NAMESPACE(v1) {
00073 /// @endcond
00074 
00075 /// The type of reference or copy judging function.
00076 /**
00077  * @param type msgpack data type.
00078  * @param size msgpack data size.
00079  * @param user_data The user_data that is set by msgpack::unpack functions.
00080  *
00081  * @return If the data should be referenced, then return true, otherwise (should be copied) false.
00082  *
00083  * This function is called when unpacking STR, BIN, or EXT.
00084  *
00085  */
00086 typedef bool (*unpack_reference_func)(msgpack::type::object_type type, std::size_t size, void* user_data);
00087 
00088 struct unpack_error : public std::runtime_error {
00089     explicit unpack_error(const std::string& msg)
00090         :std::runtime_error(msg) {}
00091 #if !defined(MSGPACK_USE_CPP03)
00092     explicit unpack_error(const char* msg):
00093         std::runtime_error(msg) {}
00094 #endif // !defined(MSGPACK_USE_CPP03)
00095 };
00096 
00097 struct parse_error : public unpack_error {
00098     explicit parse_error(const std::string& msg)
00099         :unpack_error(msg) {}
00100 #if !defined(MSGPACK_USE_CPP03)
00101     explicit parse_error(const char* msg)
00102         :unpack_error(msg) {}
00103 #endif // !defined(MSGPACK_USE_CPP03)
00104 };
00105 
00106 struct insufficient_bytes : public unpack_error {
00107     explicit insufficient_bytes(const std::string& msg)
00108         :unpack_error(msg) {}
00109 #if !defined(MSGPACK_USE_CPP03)
00110     explicit insufficient_bytes(const char* msg)
00111         :unpack_error(msg) {}
00112 #endif // !defined(MSGPACK_USE_CPP03)
00113 };
00114 
00115 struct size_overflow : public unpack_error {
00116     explicit size_overflow(const std::string& msg)
00117         :unpack_error(msg) {}
00118 #if !defined(MSGPACK_USE_CPP03)
00119     explicit size_overflow(const char* msg)
00120         :unpack_error(msg) {}
00121 #endif
00122 };
00123 
00124 struct array_size_overflow : public size_overflow {
00125     array_size_overflow(const std::string& msg)
00126         :size_overflow(msg) {}
00127 #if !defined(MSGPACK_USE_CPP03)
00128     array_size_overflow(const char* msg)
00129         :size_overflow(msg) {}
00130 #endif
00131 };
00132 
00133 struct map_size_overflow : public size_overflow {
00134     map_size_overflow(const std::string& msg)
00135         :size_overflow(msg) {}
00136 #if !defined(MSGPACK_USE_CPP03)
00137     map_size_overflow(const char* msg)
00138         :size_overflow(msg) {}
00139 #endif
00140 };
00141 
00142 struct str_size_overflow : public size_overflow {
00143     str_size_overflow(const std::string& msg)
00144         :size_overflow(msg) {}
00145 #if !defined(MSGPACK_USE_CPP03)
00146     str_size_overflow(const char* msg)
00147         :size_overflow(msg) {}
00148 #endif
00149 };
00150 
00151 struct bin_size_overflow : public size_overflow {
00152     bin_size_overflow(const std::string& msg)
00153         :size_overflow(msg) {}
00154 #if !defined(MSGPACK_USE_CPP03)
00155     bin_size_overflow(const char* msg)
00156         :size_overflow(msg) {}
00157 #endif
00158 };
00159 
00160 struct ext_size_overflow : public size_overflow {
00161     ext_size_overflow(const std::string& msg)
00162         :size_overflow(msg) {}
00163 #if !defined(MSGPACK_USE_CPP03)
00164     ext_size_overflow(const char* msg)
00165         :size_overflow(msg) {}
00166 #endif
00167 };
00168 
00169 struct depth_size_overflow : public size_overflow {
00170     depth_size_overflow(const std::string& msg)
00171         :size_overflow(msg) {}
00172 #if !defined(MSGPACK_USE_CPP03)
00173     depth_size_overflow(const char* msg)
00174         :size_overflow(msg) {}
00175 #endif
00176 };
00177 
00178 class unpack_limit {
00179 public:
00180     unpack_limit(
00181         std::size_t array = 0xffffffff,
00182         std::size_t map = 0xffffffff,
00183         std::size_t str = 0xffffffff,
00184         std::size_t bin = 0xffffffff,
00185         std::size_t ext = 0xffffffff,
00186         std::size_t depth = 0xffffffff)
00187         :array_(array),
00188          map_(map),
00189          str_(str),
00190          bin_(bin),
00191          ext_(ext),
00192          depth_(depth) {}
00193     std::size_t array() const { return array_; }
00194     std::size_t map() const { return map_; }
00195     std::size_t str() const { return str_; }
00196     std::size_t bin() const { return bin_; }
00197     std::size_t ext() const { return ext_; }
00198     std::size_t depth() const { return depth_; }
00199 
00200 private:
00201     std::size_t array_;
00202     std::size_t map_;
00203     std::size_t str_;
00204     std::size_t bin_;
00205     std::size_t ext_;
00206     std::size_t depth_;
00207 };
00208 
00209 namespace detail {
00210 
00211 class unpack_user {
00212 public:
00213     unpack_user(unpack_reference_func f = nullptr,
00214                 void* user_data = nullptr,
00215                 unpack_limit const& limit = unpack_limit())
00216         :m_func(f), m_user_data(user_data), m_limit(limit) {}
00217     msgpack::zone const& zone() const { return *m_zone; }
00218     msgpack::zone& zone() { return *m_zone; }
00219     void set_zone(msgpack::zone& zone) { m_zone = &zone; }
00220     bool referenced() const { return m_referenced; }
00221     void set_referenced(bool referenced) { m_referenced = referenced; }
00222     unpack_reference_func reference_func() const { return m_func; }
00223     void* user_data() const { return m_user_data; }
00224     unpack_limit const& limit() const { return m_limit; }
00225     unpack_limit& limit() { return m_limit; }
00226 
00227 private:
00228     msgpack::zone* m_zone;
00229     bool m_referenced;
00230     unpack_reference_func m_func;
00231     void* m_user_data;
00232     unpack_limit m_limit;
00233 };
00234 
00235 inline void unpack_uint8(uint8_t d, msgpack::object& o)
00236 { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00237 
00238 inline void unpack_uint16(uint16_t d, msgpack::object& o)
00239 { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00240 
00241 inline void unpack_uint32(uint32_t d, msgpack::object& o)
00242 { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00243 
00244 inline void unpack_uint64(uint64_t d, msgpack::object& o)
00245 { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00246 
00247 inline void unpack_int8(int8_t d, msgpack::object& o)
00248 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00249         else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
00250 
00251 inline void unpack_int16(int16_t d, msgpack::object& o)
00252 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00253         else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
00254 
00255 inline void unpack_int32(int32_t d, msgpack::object& o)
00256 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00257         else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
00258 
00259 inline void unpack_int64(int64_t d, msgpack::object& o)
00260 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
00261         else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
00262 
00263 inline void unpack_float(float d, msgpack::object& o)
00264 { o.type = msgpack::type::FLOAT; o.via.f64 = d; }
00265 
00266 inline void unpack_double(double d, msgpack::object& o)
00267 { o.type = msgpack::type::FLOAT; o.via.f64 = d; }
00268 
00269 inline void unpack_nil(msgpack::object& o)
00270 { o.type = msgpack::type::NIL; }
00271 
00272 inline void unpack_true(msgpack::object& o)
00273 { o.type = msgpack::type::BOOLEAN; o.via.boolean = true; }
00274 
00275 inline void unpack_false(msgpack::object& o)
00276 { o.type = msgpack::type::BOOLEAN; o.via.boolean = false; }
00277 
00278 struct unpack_array {
00279     void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
00280         if (n > u.limit().array()) 
00281             printf("array size overflow\n");
00282 //            throw msgpack::array_size_overflow("array size overflow");
00283         o.type = msgpack::type::ARRAY;
00284         o.via.array.size = 0;
00285         o.via.array.ptr = static_cast<msgpack::object*>(u.zone().allocate_align(n*sizeof(msgpack::object)));
00286     }
00287 };
00288 
00289 inline void unpack_array_item(msgpack::object& c, msgpack::object const& o)
00290 {
00291 #if defined(__GNUC__) && !defined(__clang__)
00292     std::memcpy(&c.via.array.ptr[c.via.array.size++], &o, sizeof(msgpack::object));
00293 #else  /* __GNUC__ && !__clang__ */
00294     c.via.array.ptr[c.via.array.size++] = o;
00295 #endif /* __GNUC__ && !__clang__ */
00296 }
00297 
00298 struct unpack_map {
00299     void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
00300         if (n > u.limit().map()) 
00301             printf("map size overflow\n");
00302 //            throw msgpack::map_size_overflow("map size overflow");
00303         o.type = msgpack::type::MAP;
00304         o.via.map.size = 0;
00305         o.via.map.ptr = static_cast<msgpack::object_kv*>(u.zone().allocate_align(n*sizeof(msgpack::object_kv)));
00306     }
00307 };
00308 
00309 inline void unpack_map_item(msgpack::object& c, msgpack::object const& k, msgpack::object const& v)
00310 {
00311 #if defined(__GNUC__) && !defined(__clang__)
00312     std::memcpy(&c.via.map.ptr[c.via.map.size].key, &k, sizeof(msgpack::object));
00313     std::memcpy(&c.via.map.ptr[c.via.map.size].val, &v, sizeof(msgpack::object));
00314 #else  /* __GNUC__ && !__clang__ */
00315     c.via.map.ptr[c.via.map.size].key = k;
00316     c.via.map.ptr[c.via.map.size].val = v;
00317 #endif /* __GNUC__ && !__clang__ */
00318     ++c.via.map.size;
00319 }
00320 
00321 inline void unpack_str(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
00322 {
00323     o.type = msgpack::type::STR;
00324     if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
00325         o.via.str.ptr = p;
00326         u.set_referenced(true);
00327     }
00328     else {
00329         if (l > u.limit().str()) 
00330             printf("str size overflow\n");
00331 //            throw msgpack::str_size_overflow("str size overflow");
00332         char* tmp = static_cast<char*>(u.zone().allocate_align(l));
00333         std::memcpy(tmp, p, l);
00334         o.via.str.ptr = tmp;
00335     }
00336     o.via.str.size = l;
00337 }
00338 
00339 inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
00340 {
00341     o.type = msgpack::type::BIN;
00342     if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
00343         o.via.bin.ptr = p;
00344         u.set_referenced(true);
00345     }
00346     else {
00347         if (l > u.limit().bin()) 
00348             printf("bin size overflow\n");
00349 //            throw msgpack::bin_size_overflow("bin size overflow");
00350         char* tmp = static_cast<char*>(u.zone().allocate_align(l));
00351         std::memcpy(tmp, p, l);
00352         o.via.bin.ptr = tmp;
00353     }
00354     o.via.bin.size = l;
00355 }
00356 
00357 inline void unpack_ext(unpack_user& u, const char* p, std::size_t l, msgpack::object& o)
00358 {
00359     o.type = msgpack::type::EXT;
00360     if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
00361         o.via.ext.ptr = p;
00362         u.set_referenced(true);
00363     }
00364     else {
00365         if (l > u.limit().ext()) 
00366             printf("ext size overflow\n");
00367 //            throw msgpack::ext_size_overflow("ext size overflow");
00368         char* tmp = static_cast<char*>(u.zone().allocate_align(l));
00369         std::memcpy(tmp, p, l);
00370         o.via.ext.ptr = tmp;
00371     }
00372     o.via.ext.size = static_cast<uint32_t>(l - 1);
00373 }
00374 
00375 
00376 class unpack_stack {
00377 public:
00378     msgpack::object const& obj() const { return m_obj; }
00379     msgpack::object& obj() { return m_obj; }
00380     void set_obj(msgpack::object const& obj) { m_obj = obj; }
00381     std::size_t count() const { return m_count; }
00382     void set_count(std::size_t count) { m_count = count; }
00383     std::size_t decr_count() { return --m_count; }
00384     uint32_t container_type() const { return m_container_type; }
00385     void set_container_type(uint32_t container_type) { m_container_type = container_type; }
00386     msgpack::object const& map_key() const { return m_map_key; }
00387     void set_map_key(msgpack::object const& map_key) { m_map_key = map_key; }
00388 private:
00389     msgpack::object m_obj;
00390     std::size_t m_count;
00391     uint32_t m_container_type;
00392     msgpack::object m_map_key;
00393 };
00394 
00395 inline void init_count(void* buffer)
00396 {
00397 #if defined(MSGPACK_USE_CPP03)
00398     *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer) = 1;
00399 #else  // defined(MSGPACK_USE_CPP03)
00400     new (buffer) std::atomic<unsigned int>(1);
00401 #endif // defined(MSGPACK_USE_CPP03)
00402 }
00403 
00404 inline void decr_count(void* buffer)
00405 {
00406 #if defined(MSGPACK_USE_CPP03)
00407     if(_msgpack_sync_decr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer)) == 0) {
00408         free(buffer);
00409     }
00410 #else  // defined(MSGPACK_USE_CPP03)
00411     if (--*reinterpret_cast<std::atomic<unsigned int>*>(buffer) == 0) {
00412         free(buffer);
00413     }
00414 #endif // defined(MSGPACK_USE_CPP03)
00415 }
00416 
00417 inline void incr_count(void* buffer)
00418 {
00419 #if defined(MSGPACK_USE_CPP03)
00420     _msgpack_sync_incr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer));
00421 #else  // defined(MSGPACK_USE_CPP03)
00422     ++*reinterpret_cast<std::atomic<unsigned int>*>(buffer);
00423 #endif // defined(MSGPACK_USE_CPP03)
00424 }
00425 
00426 #if defined(MSGPACK_USE_CPP03)
00427 inline _msgpack_atomic_counter_t get_count(void* buffer)
00428 {
00429     return *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer);
00430 }
00431 #else  // defined(MSGPACK_USE_CPP03)
00432 inline std::atomic<unsigned int> const& get_count(void* buffer)
00433 {
00434     return *reinterpret_cast<std::atomic<unsigned int>*>(buffer);
00435 }
00436 #endif // defined(MSGPACK_USE_CPP03)
00437 
00438 struct fix_tag {
00439     char f1[65]; // FIXME unique size is required. or use is_same meta function.
00440 };
00441 
00442 template <typename T>
00443 struct value {
00444     typedef T type;
00445 };
00446 template <>
00447 struct value<fix_tag> {
00448     typedef uint32_t type;
00449 };
00450 
00451 template <typename T>
00452 inline void load(uint32_t& dst, const char* n, typename msgpack::enable_if<sizeof(T) == sizeof(fix_tag)>::type* = nullptr) {
00453     dst = static_cast<uint32_t>(*reinterpret_cast<const uint8_t*>(n)) & 0x0f;
00454 }
00455 
00456 template <typename T>
00457 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 1>::type* = nullptr) {
00458     dst = static_cast<T>(*reinterpret_cast<const uint8_t*>(n));
00459 }
00460 
00461 template <typename T>
00462 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 2>::type* = nullptr) {
00463     _msgpack_load16(T, n, &dst);
00464 }
00465 
00466 template <typename T>
00467 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 4>::type* = nullptr) {
00468     _msgpack_load32(T, n, &dst);
00469 }
00470 
00471 template <typename T>
00472 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 8>::type* = nullptr) {
00473     _msgpack_load64(T, n, &dst);
00474 }
00475 
00476 class context {
00477 public:
00478     context(unpack_reference_func f, void* user_data, unpack_limit const& limit)
00479         :m_trail(0), m_user(f, user_data, limit), m_cs(MSGPACK_CS_HEADER)
00480     {
00481         m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
00482         m_stack.push_back(unpack_stack());
00483     }
00484 
00485     void init()
00486     {
00487         m_cs = MSGPACK_CS_HEADER;
00488         m_trail = 0;
00489         m_stack.resize(1);
00490         m_stack[0].set_obj(msgpack::object());
00491     }
00492 
00493     msgpack::object const& data() const
00494     {
00495         return m_stack[0].obj();
00496     }
00497 
00498     unpack_user& user()
00499     {
00500         return m_user;
00501     }
00502 
00503     unpack_user const& user() const
00504     {
00505         return m_user;
00506     }
00507 
00508     int execute(const char* data, std::size_t len, std::size_t& off);
00509 
00510 private:
00511     template <typename T>
00512     static uint32_t next_cs(T p)
00513     {
00514         return static_cast<uint32_t>(*p) & 0x1f;
00515     }
00516 
00517     template <typename T, typename Func>
00518     int push_aggregate(
00519         Func const& f,
00520         uint32_t container_type,
00521         msgpack::object& obj,
00522         const char* load_pos,
00523         std::size_t& off) {
00524         typename value<T>::type tmp;
00525         load<T>(tmp, load_pos);
00526         f(m_user, tmp, m_stack.back().obj());
00527         if(tmp == 0) {
00528             obj = m_stack.back().obj();
00529             int ret = push_proc(obj, off);
00530             if (ret != 0) return ret;
00531         }
00532         else {
00533             m_stack.back().set_container_type(container_type);
00534             m_stack.back().set_count(tmp);
00535             if (m_stack.size() <= m_user.limit().depth()) {
00536                 m_stack.push_back(unpack_stack());
00537             }
00538             else {
00539                 printf("depth size overflow\n");
00540 //                throw msgpack::depth_size_overflow("depth size overflow");
00541             }
00542             m_cs = MSGPACK_CS_HEADER;
00543             ++m_current;
00544         }
00545         return 0;
00546     }
00547 
00548     int push_item(msgpack::object& obj) {
00549         bool finish = false;
00550         while (!finish) {
00551             if(m_stack.size() == 1) {
00552                 return 1;
00553             }
00554             unpack_stack& sp = *(m_stack.end() - 2);
00555             switch(sp.container_type()) {
00556             case MSGPACK_CT_ARRAY_ITEM:
00557                 unpack_array_item(sp.obj(), obj);
00558                 if(sp.decr_count() == 0) {
00559                     obj = sp.obj();
00560                     m_stack.pop_back();
00561                 }
00562                 else {
00563                     finish = true;
00564                 }
00565                 break;
00566             case MSGPACK_CT_MAP_KEY:
00567                 sp.set_map_key(obj);
00568                 sp.set_container_type(MSGPACK_CT_MAP_VALUE);
00569                 finish = true;
00570                 break;
00571             case MSGPACK_CT_MAP_VALUE:
00572                 unpack_map_item(sp.obj(), sp.map_key(), obj);
00573                 if(sp.decr_count() == 0) {
00574                     obj = sp.obj();
00575                     m_stack.pop_back();
00576                 }
00577                 else {
00578                     sp.set_container_type(MSGPACK_CT_MAP_KEY);
00579                     finish = true;
00580                 }
00581                 break;
00582             default:
00583                 return -1;
00584             }
00585         }
00586         return 0;
00587     }
00588 
00589     int push_proc(msgpack::object& obj, std::size_t& off) {
00590         int ret = push_item(obj);
00591         if (ret > 0) {
00592             m_stack[0].set_obj(obj);
00593             ++m_current;
00594             /*printf("-- finish --\n"); */
00595             off = m_current - m_start;
00596         }
00597         else if (ret < 0) {
00598             off = m_current - m_start;
00599         }
00600         else {
00601             m_cs = MSGPACK_CS_HEADER;
00602             ++m_current;
00603         }
00604         return ret;
00605     }
00606 
00607     template <std::size_t N>
00608     static void check_ext_size(std::size_t /*size*/) {
00609     }
00610 
00611 private:
00612     char const* m_start;
00613     char const* m_current;
00614 
00615     std::size_t m_trail;
00616     unpack_user m_user;
00617     uint32_t m_cs;
00618     std::vector<unpack_stack> m_stack;
00619 };
00620 
00621 template <>
00622 inline void context::check_ext_size<4>(std::size_t size) {
00623     if (size == 0xffffffff) 
00624         printf("ext size overflow\n");
00625 //        throw msgpack::ext_size_overflow("ext size overflow");
00626 }
00627 
00628 inline int context::execute(const char* data, std::size_t len, std::size_t& off)
00629 {
00630     assert(len >= off);
00631 
00632     m_start = data;
00633     m_current = data + off;
00634     const char* const pe = data + len;
00635     const char* n = nullptr;
00636 
00637     msgpack::object obj;
00638 
00639     if(m_current == pe) {
00640         off = m_current - m_start;
00641         return 0;
00642     }
00643     bool fixed_trail_again = false;
00644     do {
00645         if (m_cs == MSGPACK_CS_HEADER) {
00646             fixed_trail_again = false;
00647             int selector = *reinterpret_cast<const unsigned char*>(m_current);
00648             if (0x00 <= selector && selector <= 0x7f) { // Positive Fixnum
00649                 unpack_uint8(*reinterpret_cast<const uint8_t*>(m_current), obj);
00650                 int ret = push_proc(obj, off);
00651                 if (ret != 0) return ret;
00652             } else if(0xe0 <= selector && selector <= 0xff) { // Negative Fixnum
00653                 unpack_int8(*reinterpret_cast<const int8_t*>(m_current), obj);
00654                 int ret = push_proc(obj, off);
00655                 if (ret != 0) return ret;
00656             } else if (0xc4 <= selector && selector <= 0xdf) {
00657                 const uint32_t trail[] = {
00658                     1, // bin     8  0xc4
00659                     2, // bin    16  0xc5
00660                     4, // bin    32  0xc6
00661                     1, // ext     8  0xc7
00662                     2, // ext    16  0xc8
00663                     4, // ext    32  0xc9
00664                     4, // float  32  0xca
00665                     8, // float  64  0xcb
00666                     1, // uint    8  0xcc
00667                     2, // uint   16  0xcd
00668                     4, // uint   32  0xce
00669                     8, // uint   64  0xcf
00670                     1, // int     8  0xd0
00671                     2, // int    16  0xd1
00672                     4, // int    32  0xd2
00673                     8, // int    64  0xd3
00674                     2, // fixext  1  0xd4
00675                     3, // fixext  2  0xd5
00676                     5, // fixext  4  0xd6
00677                     9, // fixext  8  0xd7
00678                     17,// fixext 16  0xd8
00679                     1, // str     8  0xd9
00680                     2, // str    16  0xda
00681                     4, // str    32  0xdb
00682                     2, // array  16  0xdc
00683                     4, // array  32  0xdd
00684                     2, // map    16  0xde
00685                     4, // map    32  0xdf
00686                 };
00687                 m_trail = trail[selector - 0xc4];
00688                 m_cs = next_cs(m_current);
00689                 fixed_trail_again = true;
00690             } else if(0xa0 <= selector && selector <= 0xbf) { // FixStr
00691                 m_trail = static_cast<uint32_t>(*m_current) & 0x1f;
00692                 if(m_trail == 0) {
00693                     unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
00694                     int ret = push_proc(obj, off);
00695                     if (ret != 0) return ret;
00696                 }
00697                 else {
00698                     m_cs = MSGPACK_ACS_STR_VALUE;
00699                     fixed_trail_again = true;
00700                 }
00701 
00702             } else if(0x90 <= selector && selector <= 0x9f) { // FixArray
00703                 int ret = push_aggregate<fix_tag>(
00704                     unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, m_current, off);
00705                 if (ret != 0) return ret;
00706             } else if(0x80 <= selector && selector <= 0x8f) { // FixMap
00707                 int ret = push_aggregate<fix_tag>(
00708                     unpack_map(), MSGPACK_CT_MAP_KEY, obj, m_current, off);
00709                 if (ret != 0) return ret;
00710             } else if(selector == 0xc2) { // false
00711                 unpack_false(obj);
00712                 int ret = push_proc(obj, off);
00713                 if (ret != 0) return ret;
00714             } else if(selector == 0xc3) { // true
00715                 unpack_true(obj);
00716                 int ret = push_proc(obj, off);
00717                 if (ret != 0) return ret;
00718             } else if(selector == 0xc0) { // nil
00719                 unpack_nil(obj);
00720                 int ret = push_proc(obj, off);
00721                 if (ret != 0) return ret;
00722             } else {
00723                 off = m_current - m_start;
00724                 return -1;
00725             }
00726             // end MSGPACK_CS_HEADER
00727         }
00728         if (m_cs != MSGPACK_CS_HEADER || fixed_trail_again) {
00729             if (fixed_trail_again) {
00730                 ++m_current;
00731                 fixed_trail_again = false;
00732             }
00733             if(static_cast<std::size_t>(pe - m_current) < m_trail) {
00734                 off = m_current - m_start;
00735                 return 0;
00736             }
00737             n = m_current;
00738             m_current += m_trail - 1;
00739             switch(m_cs) {
00740                 //case MSGPACK_CS_
00741                 //case MSGPACK_CS_
00742             case MSGPACK_CS_FLOAT: {
00743                 union { uint32_t i; float f; } mem;
00744                 load<uint32_t>(mem.i, n);
00745                 unpack_float(mem.f, obj);
00746                 int ret = push_proc(obj, off);
00747                 if (ret != 0) return ret;
00748             } break;
00749             case MSGPACK_CS_DOUBLE: {
00750                 union { uint64_t i; double f; } mem;
00751                 load<uint64_t>(mem.i, n);
00752 #if defined(TARGET_OS_IPHONE)
00753                 // ok
00754 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
00755                 // https://github.com/msgpack/msgpack-perl/pull/1
00756                 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
00757 #endif
00758                 unpack_double(mem.f, obj);
00759                 int ret = push_proc(obj, off);
00760                 if (ret != 0) return ret;
00761             } break;
00762             case MSGPACK_CS_UINT_8: {
00763                 uint8_t tmp;
00764                 load<uint8_t>(tmp, n);
00765                 unpack_uint8(tmp, obj);
00766                 int ret = push_proc(obj, off);
00767                 if (ret != 0) return ret;
00768             } break;
00769             case MSGPACK_CS_UINT_16: {
00770                 uint16_t tmp;
00771                 load<uint16_t>(tmp, n);
00772                 unpack_uint16(tmp, obj);
00773                 int ret = push_proc(obj, off);
00774                 if (ret != 0) return ret;
00775             } break;
00776             case MSGPACK_CS_UINT_32: {
00777                 uint32_t tmp;
00778                 load<uint32_t>(tmp, n);
00779                 unpack_uint32(tmp, obj);
00780                 int ret = push_proc(obj, off);
00781                 if (ret != 0) return ret;
00782             } break;
00783             case MSGPACK_CS_UINT_64: {
00784                 uint64_t tmp;
00785                 load<uint64_t>(tmp, n);
00786                 unpack_uint64(tmp, obj);
00787                 int ret = push_proc(obj, off);
00788                 if (ret != 0) return ret;
00789             } break;
00790             case MSGPACK_CS_INT_8: {
00791                 int8_t tmp;
00792                 load<int8_t>(tmp, n);
00793                 unpack_int8(tmp, obj);
00794                 int ret = push_proc(obj, off);
00795                 if (ret != 0) return ret;
00796             } break;
00797             case MSGPACK_CS_INT_16: {
00798                 int16_t tmp;
00799                 load<int16_t>(tmp, n);
00800                 unpack_int16(tmp, obj);
00801                 int ret = push_proc(obj, off);
00802                 if (ret != 0) return ret;
00803             } break;
00804             case MSGPACK_CS_INT_32: {
00805                 int32_t tmp;
00806                 load<int32_t>(tmp, n);
00807                 unpack_int32(tmp, obj);
00808                 int ret = push_proc(obj, off);
00809                 if (ret != 0) return ret;
00810             } break;
00811             case MSGPACK_CS_INT_64: {
00812                 int64_t tmp;
00813                 load<int64_t>(tmp, n);
00814                 unpack_int64(tmp, obj);
00815                 int ret = push_proc(obj, off);
00816                 if (ret != 0) return ret;
00817             } break;
00818             case MSGPACK_CS_FIXEXT_1: {
00819                 unpack_ext(m_user, n, 1+1, obj);
00820                 int ret = push_proc(obj, off);
00821                 if (ret != 0) return ret;
00822             } break;
00823             case MSGPACK_CS_FIXEXT_2: {
00824                 unpack_ext(m_user, n, 2+1, obj);
00825                 int ret = push_proc(obj, off);
00826                 if (ret != 0) return ret;
00827             } break;
00828             case MSGPACK_CS_FIXEXT_4: {
00829                 unpack_ext(m_user, n, 4+1, obj);
00830                 int ret = push_proc(obj, off);
00831                 if (ret != 0) return ret;
00832             } break;
00833             case MSGPACK_CS_FIXEXT_8: {
00834                 unpack_ext(m_user, n, 8+1, obj);
00835                 int ret = push_proc(obj, off);
00836                 if (ret != 0) return ret;
00837             } break;
00838             case MSGPACK_CS_FIXEXT_16: {
00839                 unpack_ext(m_user, n, 16+1, obj);
00840                 int ret = push_proc(obj, off);
00841                 if (ret != 0) return ret;
00842             } break;
00843             case MSGPACK_CS_STR_8: {
00844                 uint8_t tmp;
00845                 load<uint8_t>(tmp, n);
00846                 m_trail = tmp;
00847                 if(m_trail == 0) {
00848                     unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
00849                     int ret = push_proc(obj, off);
00850                     if (ret != 0) return ret;
00851                 }
00852                 else {
00853                     m_cs = MSGPACK_ACS_STR_VALUE;
00854                     fixed_trail_again = true;
00855                 }
00856             } break;
00857             case MSGPACK_CS_BIN_8: {
00858                 uint8_t tmp;
00859                 load<uint8_t>(tmp, n);
00860                 m_trail = tmp;
00861                 if(m_trail == 0) {
00862                     unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
00863                     int ret = push_proc(obj, off);
00864                     if (ret != 0) return ret;
00865                 }
00866                 else {
00867                     m_cs = MSGPACK_ACS_BIN_VALUE;
00868                     fixed_trail_again = true;
00869                 }
00870             } break;
00871             case MSGPACK_CS_EXT_8: {
00872                 uint8_t tmp;
00873                 load<uint8_t>(tmp, n);
00874                 m_trail = tmp + 1;
00875                 if(m_trail == 0) {
00876                     unpack_ext(m_user, n, m_trail, obj);
00877                     int ret = push_proc(obj, off);
00878                     if (ret != 0) return ret;
00879                 }
00880                 else {
00881                     m_cs = MSGPACK_ACS_EXT_VALUE;
00882                     fixed_trail_again = true;
00883                 }
00884             } break;
00885             case MSGPACK_CS_STR_16: {
00886                 uint16_t tmp;
00887                 load<uint16_t>(tmp, n);
00888                 m_trail = tmp;
00889                 if(m_trail == 0) {
00890                     unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
00891                     int ret = push_proc(obj, off);
00892                     if (ret != 0) return ret;
00893                 }
00894                 else {
00895                     m_cs = MSGPACK_ACS_STR_VALUE;
00896                     fixed_trail_again = true;
00897                 }
00898             } break;
00899             case MSGPACK_CS_BIN_16: {
00900                 uint16_t tmp;
00901                 load<uint16_t>(tmp, n);
00902                 m_trail = tmp;
00903                 if(m_trail == 0) {
00904                     unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
00905                     int ret = push_proc(obj, off);
00906                     if (ret != 0) return ret;
00907                 }
00908                 else {
00909                     m_cs = MSGPACK_ACS_BIN_VALUE;
00910                     fixed_trail_again = true;
00911                 }
00912             } break;
00913             case MSGPACK_CS_EXT_16: {
00914                 uint16_t tmp;
00915                 load<uint16_t>(tmp, n);
00916                 m_trail = tmp + 1;
00917                 if(m_trail == 0) {
00918                     unpack_ext(m_user, n, m_trail, obj);
00919                     int ret = push_proc(obj, off);
00920                     if (ret != 0) return ret;
00921                 }
00922                 else {
00923                     m_cs = MSGPACK_ACS_EXT_VALUE;
00924                     fixed_trail_again = true;
00925                 }
00926             } break;
00927             case MSGPACK_CS_STR_32: {
00928                 uint32_t tmp;
00929                 load<uint32_t>(tmp, n);
00930                 m_trail = tmp;
00931                 if(m_trail == 0) {
00932                     unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
00933                     int ret = push_proc(obj, off);
00934                     if (ret != 0) return ret;
00935                 }
00936                 else {
00937                     m_cs = MSGPACK_ACS_STR_VALUE;
00938                     fixed_trail_again = true;
00939                 }
00940             } break;
00941             case MSGPACK_CS_BIN_32: {
00942                 uint32_t tmp;
00943                 load<uint32_t>(tmp, n);
00944                 m_trail = tmp;
00945                 if(m_trail == 0) {
00946                     unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
00947                     int ret = push_proc(obj, off);
00948                     if (ret != 0) return ret;
00949                 }
00950                 else {
00951                     m_cs = MSGPACK_ACS_BIN_VALUE;
00952                     fixed_trail_again = true;
00953                 }
00954             } break;
00955             case MSGPACK_CS_EXT_32: {
00956                 uint32_t tmp;
00957                 load<uint32_t>(tmp, n);
00958                 check_ext_size<sizeof(std::size_t)>(tmp);
00959                 m_trail = tmp;
00960                 ++m_trail;
00961                 if(m_trail == 0) {
00962                     unpack_ext(m_user, n, m_trail, obj);
00963                     int ret = push_proc(obj, off);
00964                     if (ret != 0) return ret;
00965                 }
00966                 else {
00967                     m_cs = MSGPACK_ACS_EXT_VALUE;
00968                     fixed_trail_again = true;
00969                 }
00970             } break;
00971             case MSGPACK_ACS_STR_VALUE: {
00972                 unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
00973                 int ret = push_proc(obj, off);
00974                 if (ret != 0) return ret;
00975             } break;
00976             case MSGPACK_ACS_BIN_VALUE: {
00977                 unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
00978                 int ret = push_proc(obj, off);
00979                 if (ret != 0) return ret;
00980             } break;
00981             case MSGPACK_ACS_EXT_VALUE: {
00982                 unpack_ext(m_user, n, m_trail, obj);
00983                 int ret = push_proc(obj, off);
00984                 if (ret != 0) return ret;
00985             } break;
00986             case MSGPACK_CS_ARRAY_16: {
00987                 int ret = push_aggregate<uint16_t>(
00988                     unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
00989                 if (ret != 0) return ret;
00990             } break;
00991             case MSGPACK_CS_ARRAY_32: {
00992                 /* FIXME security guard */
00993                 int ret = push_aggregate<uint32_t>(
00994                     unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
00995                 if (ret != 0) return ret;
00996             } break;
00997             case MSGPACK_CS_MAP_16: {
00998                 int ret = push_aggregate<uint16_t>(
00999                     unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
01000                 if (ret != 0) return ret;
01001             } break;
01002             case MSGPACK_CS_MAP_32: {
01003                 /* FIXME security guard */
01004                 int ret = push_aggregate<uint32_t>(
01005                     unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
01006                 if (ret != 0) return ret;
01007             } break;
01008             default:
01009                 off = m_current - m_start;
01010                 return -1;
01011             }
01012         }
01013     } while(m_current != pe);
01014 
01015     off = m_current - m_start;
01016     return 0;
01017 }
01018 
01019 } // detail
01020 
01021 
01022 typedef object_handle unpacked;
01023 
01024 /// Unpacking class for a stream deserialization.
01025 class unpacker {
01026 public:
01027     /// Constructor
01028     /**
01029      * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01030      * @param f A judging function that msgpack::object refer to the buffer.
01031      * @param user_data This parameter is passed to f.
01032      * @param initial_buffer_size The memory size to allocate when unpacker is constructed.
01033      * @param limit The size limit information of msgpack::object.
01034      *
01035      */
01036     unpacker(unpack_reference_func f = &unpacker::default_reference_func,
01037              void* user_data = nullptr,
01038              std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE,
01039              unpack_limit const& limit = unpack_limit());
01040 
01041 #if !defined(MSGPACK_USE_CPP03)
01042     unpacker(unpacker&& other);
01043     unpacker& operator=(unpacker&& other);
01044 #endif // !defined(MSGPACK_USE_CPP03)
01045 
01046     ~unpacker();
01047 
01048 public:
01049     /// Reserve a buffer memory.
01050     /**
01051      * @param size The size of allocating memory.
01052      *
01053      * After returning this function, buffer_capacity() returns at least 'size'.
01054      * See:
01055      * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
01056      */
01057     void reserve_buffer(std::size_t size = MSGPACK_UNPACKER_RESERVE_SIZE);
01058 
01059     /// Get buffer pointer.
01060     /**
01061      * You need to care about the memory is enable between buffer() and buffer() + buffer_capacity()
01062      * See:
01063      * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
01064      */
01065     char* buffer();
01066 
01067     /// Get buffer capacity.
01068     /**
01069      * @return The memory size that you can write.
01070      *
01071      * See:
01072      * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
01073      */
01074     std::size_t buffer_capacity() const;
01075 
01076     /// Notify a buffer consumed information to msgpack::unpacker.
01077     /**
01078      * @param size The size of memory that you consumed.
01079      *
01080      * After copying the data to the memory that is pointed by buffer(), you need to call the
01081      * function to notify how many bytes are consumed. Then you can call next() functions.
01082      *
01083      * See:
01084      * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
01085      */
01086     void buffer_consumed(std::size_t size);
01087 
01088     /// Unpack one msgpack::object. [obsolete]
01089     /**
01090      *
01091      * @param result The object that contains unpacked data.
01092      *
01093      * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
01094      *         and additional data is required, then return false. If data format is invalid, throw
01095      *         msgpack::parse_error.
01096      *
01097      * See:
01098      * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
01099      * This function is obsolete. Use the reference inteface version of next() function instead of
01100      * the pointer interface version.
01101      */
01102     bool next(unpacked* result);
01103 
01104     /// Unpack one msgpack::object.
01105     /**
01106      *
01107      * @param result The object that contains unpacked data.
01108      * @param referenced If the unpacked object contains reference of the buffer,
01109      *                   then set as true, otherwise false.
01110      *
01111      * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
01112      *         and additional data is required, then return false. If data format is invalid, throw
01113      *         msgpack::parse_error.
01114      *
01115      * See:
01116      * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
01117      */
01118     bool next(unpacked& result, bool& referenced);
01119 
01120     /// Unpack one msgpack::object.
01121     /**
01122      *
01123      * @param result The object that contains unpacked data.
01124      *
01125      * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
01126      *         and additional data is required, then return false. If data format is invalid, throw
01127      *         msgpack::parse_error.
01128      *
01129      * See:
01130      * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
01131      */
01132     bool next(unpacked& result);
01133 
01134     /// Get message size.
01135     /**
01136      * @return Returns parsed_size() + nonparsed_size()
01137      */
01138     std::size_t message_size() const;
01139 
01140     /*! for backward compatibility */
01141     bool execute ();
01142 
01143     /*! for backward compatibility */
01144     msgpack::object const& data ();
01145 
01146     /*! for backward compatibility */
01147     msgpack::zone* release_zone ();
01148 
01149     /*! for backward compatibility */
01150     void reset_zone ();
01151 
01152     /*! for backward compatibility */
01153     void reset ();
01154 
01155 public:
01156     /// Get parsed message size.
01157     /**
01158      * @return Parsed message size.
01159      *
01160      * This function is usable when non-MessagePack message follows after
01161      * MessagePack message.
01162      */
01163     std::size_t parsed_size() const;
01164 
01165     /// Get the address that is not parsed in the buffer.
01166     /**
01167      * @return Address of the buffer that is not parsed
01168      *
01169      * This function is usable when non-MessagePack message follows after
01170      * MessagePack message.
01171      */
01172     char* nonparsed_buffer();
01173 
01174     /// Get the size of the buffer that is not parsed.
01175     /**
01176      * @return Size of the buffer that is not parsed
01177      *
01178      * This function is usable when non-MessagePack message follows after
01179      * MessagePack message.
01180      */
01181     std::size_t nonparsed_size() const;
01182 
01183     /// Skip the specified size of non-parsed buffer.
01184     /**
01185      * @param size to skip
01186      *
01187      * Note that the `size' argument must be smaller than nonparsed_size().
01188      * This function is usable when non-MessagePack message follows after
01189      * MessagePack message.
01190      */
01191     void skip_nonparsed_buffer(std::size_t size);
01192 
01193     /// Remove nonparsed buffer and reset the current position as a new start point.
01194     /**
01195      * This function is usable when non-MessagePack message follows after
01196      * MessagePack message.
01197      */
01198     void remove_nonparsed_buffer();
01199 
01200 private:
01201     void expand_buffer(std::size_t size);
01202     int execute_imp();
01203     bool flush_zone();
01204     static bool default_reference_func(msgpack::type::object_type type, std::size_t len, void*);
01205 
01206 private:
01207     char* m_buffer;
01208     std::size_t m_used;
01209     std::size_t m_free;
01210     std::size_t m_off;
01211     std::size_t m_parsed;
01212     msgpack::unique_ptr<msgpack::zone> m_z;
01213     std::size_t m_initial_buffer_size;
01214     detail::context m_ctx;
01215 
01216 #if defined(MSGPACK_USE_CPP03)
01217 private:
01218     unpacker(const unpacker&);
01219     unpacker& operator=(const unpacker&);
01220 #else  // defined(MSGPACK_USE_CPP03)
01221     unpacker(const unpacker&) = delete;
01222     unpacker& operator=(const unpacker&) = delete;
01223 #endif // defined(MSGPACK_USE_CPP03)
01224 };
01225 
01226 /// Unpack msgpack::object from a buffer.
01227 /**
01228  * @param data The pointer to the buffer.
01229  * @param len The length of the buffer.
01230  * @param off The offset position of the buffer. It is read and overwritten.
01231  * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01232  * @param f A judging function that msgpack::object refer to the buffer.
01233  * @param user_data This parameter is passed to f.
01234  * @param limit The size limit information of msgpack::object.
01235  *
01236  * @return unpacked object that contains unpacked data.
01237  *
01238  */
01239 unpacked unpack(
01240     const char* data, std::size_t len, std::size_t& off, bool& referenced,
01241     unpack_reference_func f = nullptr, void* user_data = nullptr,
01242     unpack_limit const& limit = unpack_limit());
01243 
01244 /// Unpack msgpack::object from a buffer.
01245 /**
01246  * @param data The pointer to the buffer.
01247  * @param len The length of the buffer.
01248  * @param off The offset position of the buffer. It is read and overwritten.
01249  * @param f A judging function that msgpack::object refer to the buffer.
01250  * @param user_data This parameter is passed to f.
01251  * @param limit The size limit information of msgpack::object.
01252  *
01253  * @return unpacked object that contains unpacked data.
01254  *
01255  */
01256 unpacked unpack(
01257     const char* data, std::size_t len, std::size_t& off,
01258     unpack_reference_func f = nullptr, void* user_data = nullptr,
01259     unpack_limit const& limit = unpack_limit());
01260 
01261 /// Unpack msgpack::object from a buffer.
01262 /**
01263  * @param data The pointer to the buffer.
01264  * @param len The length of the buffer.
01265  * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01266  * @param f A judging function that msgpack::object refer to the buffer.
01267  * @param user_data This parameter is passed to f.
01268  * @param limit The size limit information of msgpack::object.
01269  *
01270  * @return unpacked object that contains unpacked data.
01271  *
01272  */
01273 unpacked unpack(
01274     const char* data, std::size_t len, bool& referenced,
01275     unpack_reference_func f = nullptr, void* user_data = nullptr,
01276     unpack_limit const& limit = unpack_limit());
01277 
01278 /// Unpack msgpack::object from a buffer.
01279 /**
01280  * @param data The pointer to the buffer.
01281  * @param len The length of the buffer.
01282  * @param f A judging function that msgpack::object refer to the buffer.
01283  * @param user_data This parameter is passed to f.
01284  * @param limit The size limit information of msgpack::object.
01285  *
01286  * @return unpacked object that contains unpacked data.
01287  *
01288  */
01289 unpacked unpack(
01290     const char* data, std::size_t len,
01291     unpack_reference_func f = nullptr, void* user_data = nullptr,
01292     unpack_limit const& limit = unpack_limit());
01293 
01294 
01295 /// Unpack msgpack::object from a buffer.
01296 /**
01297  * @param result The object that contains unpacked data.
01298  * @param data The pointer to the buffer.
01299  * @param len The length of the buffer.
01300  * @param off The offset position of the buffer. It is read and overwritten.
01301  * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01302  * @param f A judging function that msgpack::object refer to the buffer.
01303  * @param user_data This parameter is passed to f.
01304  * @param limit The size limit information of msgpack::object.
01305  *
01306  *
01307  */
01308 void unpack(unpacked& result,
01309             const char* data, std::size_t len, std::size_t& off, bool& referenced,
01310             unpack_reference_func f = nullptr, void* user_data = nullptr,
01311             unpack_limit const& limit = unpack_limit());
01312 
01313 /// Unpack msgpack::object from a buffer.
01314 /**
01315  * @param result The object that contains unpacked data.
01316  * @param data The pointer to the buffer.
01317  * @param len The length of the buffer.
01318  * @param off The offset position of the buffer. It is read and overwritten.
01319  * @param f A judging function that msgpack::object refer to the buffer.
01320  * @param user_data This parameter is passed to f.
01321  * @param limit The size limit information of msgpack::object.
01322  *
01323  *
01324  */
01325 void unpack(unpacked& result,
01326             const char* data, std::size_t len, std::size_t& off,
01327             unpack_reference_func f = nullptr, void* user_data = nullptr,
01328             unpack_limit const& limit = unpack_limit());
01329 
01330 /// Unpack msgpack::object from a buffer.
01331 /**
01332  * @param result The object that contains unpacked data.
01333  * @param data The pointer to the buffer.
01334  * @param len The length of the buffer.
01335  * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01336  * @param f A judging function that msgpack::object refer to the buffer.
01337  * @param user_data This parameter is passed to f.
01338  * @param limit The size limit information of msgpack::object.
01339  *
01340  *
01341  */
01342 void unpack(unpacked& result,
01343             const char* data, std::size_t len, bool& referenced,
01344             unpack_reference_func f = nullptr, void* user_data = nullptr,
01345             unpack_limit const& limit = unpack_limit());
01346 
01347 /// Unpack msgpack::object from a buffer.
01348 /**
01349  * @param result The object that contains unpacked data.
01350  * @param data The pointer to the buffer.
01351  * @param len The length of the buffer.
01352  * @param f A judging function that msgpack::object refer to the buffer.
01353  * @param user_data This parameter is passed to f.
01354  * @param limit The size limit information of msgpack::object.
01355  *
01356  *
01357  */
01358 void unpack(unpacked& result,
01359             const char* data, std::size_t len,
01360             unpack_reference_func f = nullptr, void* user_data = nullptr,
01361             unpack_limit const& limit = unpack_limit());
01362 
01363 /// Unpack msgpack::object from a buffer.
01364 /**
01365  * @param z The msgpack::zone that is used as a memory of unpacked msgpack objects.
01366  * @param data The pointer to the buffer.
01367  * @param len The length of the buffer.
01368  * @param off The offset position of the buffer. It is read and overwritten.
01369  * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01370  * @param f A judging function that msgpack::object refer to the buffer.
01371  * @param user_data This parameter is passed to f.
01372  * @param limit The size limit information of msgpack::object.
01373  *
01374  * @return msgpack::object that contains unpacked data.
01375  *
01376  */
01377 msgpack::object unpack(
01378     msgpack::zone& z,
01379     const char* data, std::size_t len, std::size_t& off, bool& referenced,
01380     unpack_reference_func f = nullptr, void* user_data = nullptr,
01381     unpack_limit const& limit = unpack_limit());
01382 
01383 /// Unpack msgpack::object from a buffer.
01384 /**
01385  * @param z The msgpack::zone that is used as a memory of unpacked msgpack objects.
01386  * @param data The pointer to the buffer.
01387  * @param len The length of the buffer.
01388  * @param off The offset position of the buffer. It is read and overwritten.
01389  * @param f A judging function that msgpack::object refer to the buffer.
01390  * @param user_data This parameter is passed to f.
01391  * @param limit The size limit information of msgpack::object.
01392  *
01393  * @return msgpack::object that contains unpacked data.
01394  *
01395  */
01396 msgpack::object unpack(
01397     msgpack::zone& z,
01398     const char* data, std::size_t len, std::size_t& off,
01399     unpack_reference_func f = nullptr, void* user_data = nullptr,
01400     unpack_limit const& limit = unpack_limit());
01401 
01402 /// Unpack msgpack::object from a buffer.
01403 /**
01404  * @param z The msgpack::zone that is used as a memory of unpacked msgpack objects.
01405  * @param data The pointer to the buffer.
01406  * @param len The length of the buffer.
01407  * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01408  * @param f A judging function that msgpack::object refer to the buffer.
01409  * @param user_data This parameter is passed to f.
01410  * @param limit The size limit information of msgpack::object.
01411  *
01412  * @return msgpack::object that contains unpacked data.
01413  *
01414  */
01415 msgpack::object unpack(
01416     msgpack::zone& z,
01417     const char* data, std::size_t len, bool& referenced,
01418     unpack_reference_func f = nullptr, void* user_data = nullptr,
01419     unpack_limit const& limit = unpack_limit());
01420 
01421 /// Unpack msgpack::object from a buffer.
01422 /**
01423  * @param z The msgpack::zone that is used as a memory of unpacked msgpack objects.
01424  * @param data The pointer to the buffer.
01425  * @param len The length of the buffer.
01426  * @param f A judging function that msgpack::object refer to the buffer.
01427  * @param user_data This parameter is passed to f.
01428  * @param limit The size limit information of msgpack::object.
01429  *
01430  * @return msgpack::object that contains unpacked data.
01431  *
01432  */
01433 msgpack::object unpack(
01434     msgpack::zone& z,
01435     const char* data, std::size_t len,
01436     unpack_reference_func f = nullptr, void* user_data = nullptr,
01437     unpack_limit const& limit = unpack_limit());
01438 
01439 
01440 /// Unpack msgpack::object from a buffer. [obsolete]
01441 /**
01442  * @param result The object that contains unpacked data.
01443  * @param data The pointer to the buffer.
01444  * @param len The length of the buffer.
01445  * @param off The offset position of the buffer. It is read and overwritten.
01446  * @param referenced If the unpacked object contains reference of the buffer, then set as true, otherwise false.
01447  * @param f A judging function that msgpack::object refer to the buffer.
01448  * @param user_data This parameter is passed to f.
01449  * @param limit The size limit information of msgpack::object.
01450  *
01451  * This function is obsolete. Use the reference inteface version of unpack functions instead of the pointer interface version.
01452  */
01453 void unpack(unpacked* result,
01454             const char* data, std::size_t len, std::size_t* off = nullptr, bool* referenced = nullptr,
01455             unpack_reference_func f = nullptr, void* user_data = nullptr,
01456             unpack_limit const& limit = unpack_limit());
01457 
01458 
01459 // for internal use
01460 typedef enum {
01461     UNPACK_SUCCESS              =  2,
01462     UNPACK_EXTRA_BYTES          =  1,
01463     UNPACK_CONTINUE             =  0,
01464     UNPACK_PARSE_ERROR          = -1
01465 } unpack_return;
01466 
01467 inline unpacker::unpacker(unpack_reference_func f,
01468                           void* user_data,
01469                           std::size_t initial_buffer_size,
01470                           unpack_limit const& limit)
01471     :m_z(new msgpack::zone), m_ctx(f, user_data, limit)
01472 {
01473     if(initial_buffer_size < COUNTER_SIZE) {
01474         initial_buffer_size = COUNTER_SIZE;
01475     }
01476 
01477     char* buffer = static_cast<char*>(::malloc(initial_buffer_size));
01478     if(!buffer) {
01479         printf("std::bad_alloc()\n");
01480 //        throw std::bad_alloc();
01481     }
01482 
01483     m_buffer = buffer;
01484     m_used = COUNTER_SIZE;
01485     m_free = initial_buffer_size - m_used;
01486     m_off = COUNTER_SIZE;
01487     m_parsed = 0;
01488     m_initial_buffer_size = initial_buffer_size;
01489 
01490     detail::init_count(m_buffer);
01491 
01492     m_ctx.init();
01493     m_ctx.user().set_zone(*m_z);
01494     m_ctx.user().set_referenced(false);
01495 }
01496 
01497 #if !defined(MSGPACK_USE_CPP03)
01498 // Move constructor and move assignment operator
01499 
01500 inline unpacker::unpacker(unpacker&& other)
01501     :m_buffer(other.m_buffer),
01502      m_used(other.m_used),
01503      m_free(other.m_free),
01504      m_off(other.m_off),
01505      m_parsed(other.m_parsed),
01506      m_z(std::move(other.m_z)),
01507      m_initial_buffer_size(other.m_initial_buffer_size),
01508      m_ctx(other.m_ctx) {
01509     other.m_buffer = nullptr;
01510 }
01511 
01512 inline unpacker& unpacker::operator=(unpacker&& other) {
01513     this->~unpacker();
01514     new (this) unpacker(std::move(other));
01515     return *this;
01516 }
01517 
01518 #endif // !defined(MSGPACK_USE_CPP03)
01519 
01520 
01521 inline unpacker::~unpacker()
01522 {
01523     // These checks are required for move operations.
01524     if (m_buffer) detail::decr_count(m_buffer);
01525 }
01526 
01527 
01528 inline void unpacker::reserve_buffer(std::size_t size)
01529 {
01530     if(m_free >= size) return;
01531     expand_buffer(size);
01532 }
01533 
01534 inline void unpacker::expand_buffer(std::size_t size)
01535 {
01536     if(m_used == m_off && detail::get_count(m_buffer) == 1
01537         && !m_ctx.user().referenced()) {
01538         // rewind buffer
01539         m_free += m_used - COUNTER_SIZE;
01540         m_used = COUNTER_SIZE;
01541         m_off  = COUNTER_SIZE;
01542 
01543         if(m_free >= size) return;
01544     }
01545 
01546     if(m_off == COUNTER_SIZE) {
01547         std::size_t next_size = (m_used + m_free) * 2;    // include COUNTER_SIZE
01548         while(next_size < size + m_used) {
01549             std::size_t tmp_next_size = next_size * 2;
01550             if (tmp_next_size <= next_size) {
01551                 next_size = size + m_used;
01552                 break;
01553             }
01554             next_size = tmp_next_size;
01555         }
01556 
01557         char* tmp = static_cast<char*>(::realloc(m_buffer, next_size));
01558         if(!tmp) {
01559             printf("std::bad_alloc()\n");
01560 //            throw std::bad_alloc();
01561         }
01562 
01563         m_buffer = tmp;
01564         m_free = next_size - m_used;
01565 
01566     } else {
01567         std::size_t next_size = m_initial_buffer_size;  // include COUNTER_SIZE
01568         std::size_t not_parsed = m_used - m_off;
01569         while(next_size < size + not_parsed + COUNTER_SIZE) {
01570             std::size_t tmp_next_size = next_size * 2;
01571             if (tmp_next_size <= next_size) {
01572                 next_size = size + not_parsed + COUNTER_SIZE;
01573                 break;
01574             }
01575             next_size = tmp_next_size;
01576         }
01577 
01578         char* tmp = static_cast<char*>(::malloc(next_size));
01579         if(!tmp) {
01580             printf("std::bad_alloc()\n");
01581 //            throw std::bad_alloc();
01582         }
01583 
01584         detail::init_count(tmp);
01585 
01586         std::memcpy(tmp+COUNTER_SIZE, m_buffer + m_off, not_parsed);
01587 
01588         if(m_ctx.user().referenced()) {
01589 //            try {
01590                 printf("try\n");
01591                 m_z->push_finalizer(&detail::decr_count, m_buffer);
01592 //            }
01593 //            catch (...) {
01594 //                ::free(tmp);
01595 //                throw;
01596 //            }
01597             m_ctx.user().set_referenced(false);
01598         } else {
01599             detail::decr_count(m_buffer);
01600         }
01601 
01602         m_buffer = tmp;
01603         m_used  = not_parsed + COUNTER_SIZE;
01604         m_free  = next_size - m_used;
01605         m_off   = COUNTER_SIZE;
01606     }
01607 }
01608 
01609 inline char* unpacker::buffer()
01610 {
01611     return m_buffer + m_used;
01612 }
01613 
01614 inline std::size_t unpacker::buffer_capacity() const
01615 {
01616     return m_free;
01617 }
01618 
01619 inline void unpacker::buffer_consumed(std::size_t size)
01620 {
01621     m_used += size;
01622     m_free -= size;
01623 }
01624 
01625 inline bool unpacker::next(unpacked& result, bool& referenced)
01626 {
01627     referenced = false;
01628     int ret = execute_imp();
01629     if(ret < 0) {
01630         printf("parse_error\n");
01631 //        throw msgpack::parse_error("parse error");
01632     }
01633 
01634     if(ret == 0) {
01635         result.zone().reset();
01636         result.set(object());
01637         return false;
01638 
01639     } else {
01640         referenced = m_ctx.user().referenced();
01641         result.zone().reset( release_zone () );
01642         result.set(data ());
01643         reset ();
01644         return true;
01645     }
01646 }
01647 
01648 inline bool unpacker::next(unpacked& result)
01649 {
01650     bool referenced;
01651     return next(result, referenced);
01652 }
01653 
01654 inline bool unpacker::next(unpacked* result)
01655 {
01656     return next(*result);
01657 }
01658 
01659 
01660 inline bool unpacker::execute ()
01661 {
01662     int ret = execute_imp();
01663     if(ret < 0) {
01664         printf("parse_error\n");
01665         return false;
01666 //        throw msgpack::parse_error("parse error");
01667     } else if(ret == 0) {
01668         return false;
01669     } else {
01670         return true;
01671     }
01672 }
01673 
01674 inline int unpacker::execute_imp()
01675 {
01676     std::size_t off = m_off;
01677     int ret = m_ctx.execute(m_buffer, m_used, m_off);
01678     if(m_off > off) {
01679         m_parsed += m_off - off;
01680     }
01681     return ret;
01682 }
01683 
01684 inline msgpack::object const& unpacker::data ()
01685 {
01686     return m_ctx.data();
01687 }
01688 
01689 inline msgpack::zone* unpacker::release_zone ()
01690 {
01691     if(!flush_zone()) {
01692         return nullptr;
01693     }
01694 
01695     msgpack::zone* r =  new msgpack::zone;
01696     msgpack::zone* old = m_z.release();
01697     m_z.reset(r);
01698     m_ctx.user().set_zone(*m_z);
01699 
01700     return old;
01701 }
01702 
01703 inline void unpacker::reset_zone ()
01704 {
01705     m_z->clear();
01706 }
01707 
01708 inline bool unpacker::flush_zone()
01709 {
01710     if(m_ctx.user().referenced()) {
01711 //        try {
01712             m_z->push_finalizer(&detail::decr_count, m_buffer);
01713 //        } catch (...) {
01714 //            return false;
01715 //        }
01716         m_ctx.user().set_referenced(false);
01717 
01718         detail::incr_count(m_buffer);
01719     }
01720 
01721     return true;
01722 }
01723 
01724 inline void unpacker::reset ()
01725 {
01726     m_ctx.init();
01727     // don't reset referenced flag
01728     m_parsed = 0;
01729 }
01730 
01731 inline std::size_t unpacker::message_size() const
01732 {
01733     return m_parsed - m_off + m_used;
01734 }
01735 
01736 inline std::size_t unpacker::parsed_size() const
01737 {
01738     return m_parsed;
01739 }
01740 
01741 inline char* unpacker::nonparsed_buffer()
01742 {
01743     return m_buffer + m_off;
01744 }
01745 
01746 inline std::size_t unpacker::nonparsed_size() const
01747 {
01748     return m_used - m_off;
01749 }
01750 
01751 inline void unpacker::skip_nonparsed_buffer(std::size_t size)
01752 {
01753     m_off += size;
01754 }
01755 
01756 inline void unpacker::remove_nonparsed_buffer()
01757 {
01758     m_used = m_off;
01759 }
01760 
01761 namespace detail {
01762 
01763 inline unpack_return
01764 unpack_imp(const char* data, std::size_t len, std::size_t& off,
01765            msgpack::zone& result_zone, msgpack::object& result, bool& referenced,
01766            unpack_reference_func f = nullptr, void* user_data = nullptr,
01767            unpack_limit const& limit = unpack_limit())
01768 {
01769     std::size_t noff = off;
01770 
01771     if(len <= noff) {
01772         // FIXME
01773         return UNPACK_CONTINUE;
01774     }
01775 
01776     detail::context ctx(f, user_data, limit);
01777     ctx.init();
01778 
01779     ctx.user().set_zone(result_zone);
01780     ctx.user().set_referenced(false);
01781     referenced = false;
01782 
01783     int e = ctx.execute(data, len, noff);
01784     if(e < 0) {
01785         return UNPACK_PARSE_ERROR;
01786     }
01787 
01788     referenced = ctx.user().referenced();
01789     off = noff;
01790 
01791     if(e == 0) {
01792         return UNPACK_CONTINUE;
01793     }
01794 
01795     result = ctx.data();
01796 
01797     if(noff < len) {
01798         return UNPACK_EXTRA_BYTES;
01799     }
01800 
01801     return UNPACK_SUCCESS;
01802 }
01803 
01804 } // detail
01805 
01806 // reference version
01807 
01808 inline unpacked unpack(
01809     const char* data, std::size_t len, std::size_t& off, bool& referenced,
01810     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01811 {
01812     msgpack::object obj;
01813     msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
01814     referenced = false;
01815     std::size_t noff = off;
01816     unpack_return ret = detail::unpack_imp(
01817         data, len, noff, *z, obj, referenced, f, user_data, limit);
01818 
01819     switch(ret) {
01820     case UNPACK_SUCCESS:
01821         off = noff;
01822         return unpacked(obj, msgpack::move(z));
01823     case UNPACK_EXTRA_BYTES:
01824         off = noff;
01825         return unpacked(obj, msgpack::move(z));
01826     case UNPACK_CONTINUE:
01827         printf("insufficient bytes\n");
01828 //        throw msgpack::insufficient_bytes("insufficient bytes");
01829     case UNPACK_PARSE_ERROR:
01830     default:
01831         printf("parse error\n");
01832 //        throw msgpack::parse_error("parse error");
01833     }
01834     return unpacked();
01835 }
01836 
01837 inline unpacked unpack(
01838     const char* data, std::size_t len, std::size_t& off,
01839     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01840 {
01841     bool referenced;
01842     return unpack(data, len, off, referenced, f, user_data, limit);
01843 }
01844 
01845 inline unpacked unpack(
01846     const char* data, std::size_t len, bool& referenced,
01847     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01848 {
01849     std::size_t off = 0;
01850     return unpack(data, len, off, referenced, f, user_data, limit);
01851 }
01852 
01853 inline unpacked unpack(
01854     const char* data, std::size_t len,
01855     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01856 {
01857     bool referenced;
01858     std::size_t off = 0;
01859     return unpack(data, len, off, referenced, f, user_data, limit);
01860 }
01861 
01862 inline void unpack(unpacked& result,
01863                    const char* data, std::size_t len, std::size_t& off, bool& referenced,
01864                    unpack_reference_func f, void* user_data, unpack_limit const& limit)
01865 {
01866     msgpack::object obj;
01867     msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
01868     referenced = false;
01869     std::size_t noff = off;
01870     unpack_return ret = detail::unpack_imp(
01871         data, len, noff, *z, obj, referenced, f, user_data, limit);
01872 
01873     switch(ret) {
01874     case UNPACK_SUCCESS:
01875         off = noff;
01876         result.set(obj);
01877         result.zone() = msgpack::move(z);
01878         return;
01879     case UNPACK_EXTRA_BYTES:
01880         off = noff;
01881         result.set(obj);
01882         result.zone() = msgpack::move(z);
01883         return;
01884     case UNPACK_CONTINUE:
01885         printf("insufficient bytes\n");
01886 //        throw msgpack::insufficient_bytes("insufficient bytes");
01887     case UNPACK_PARSE_ERROR:
01888     default:
01889         printf("parse error\n");
01890 //        throw msgpack::parse_error("parse error");
01891     }
01892 }
01893 
01894 inline void unpack(unpacked& result,
01895                    const char* data, std::size_t len, std::size_t& off,
01896                    unpack_reference_func f, void* user_data, unpack_limit const& limit)
01897 {
01898     bool referenced;
01899     unpack(result, data, len, off, referenced, f, user_data, limit);
01900 }
01901 
01902 inline void unpack(unpacked& result,
01903                    const char* data, std::size_t len, bool& referenced,
01904                    unpack_reference_func f, void* user_data, unpack_limit const& limit)
01905 {
01906     std::size_t off = 0;
01907     unpack(result, data, len, off, referenced, f, user_data, limit);
01908 }
01909 
01910 inline void unpack(unpacked& result,
01911                    const char* data, std::size_t len,
01912                    unpack_reference_func f, void* user_data, unpack_limit const& limit)
01913 {
01914     bool referenced;
01915     std::size_t off = 0;
01916     unpack(result, data, len, off, referenced, f, user_data, limit);
01917 }
01918 
01919 
01920 inline msgpack::object unpack(
01921     msgpack::zone& z,
01922     const char* data, std::size_t len, std::size_t& off, bool& referenced,
01923     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01924 {
01925     msgpack::object obj;
01926     std::size_t noff = off;
01927     referenced = false;
01928     unpack_return ret = detail::unpack_imp(
01929         data, len, noff, z, obj, referenced, f, user_data, limit);
01930 
01931     switch(ret) {
01932     case UNPACK_SUCCESS:
01933         off = noff;
01934         return obj;
01935     case UNPACK_EXTRA_BYTES:
01936         off = noff;
01937         return obj;
01938     case UNPACK_CONTINUE:
01939         printf("insufficient bytes\n");
01940 //        throw msgpack::insufficient_bytes("insufficient bytes");
01941     case UNPACK_PARSE_ERROR:
01942     default:
01943         printf("parse error\n");
01944 //        throw msgpack::parse_error("parse error");
01945     }
01946     return obj;
01947 }
01948 
01949 inline msgpack::object unpack(
01950     msgpack::zone& z,
01951     const char* data, std::size_t len, std::size_t& off,
01952     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01953 {
01954     bool referenced;
01955     return unpack(z, data, len, off, referenced, f, user_data, limit);
01956 }
01957 
01958 inline msgpack::object unpack(
01959     msgpack::zone& z,
01960     const char* data, std::size_t len, bool& referenced,
01961     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01962 {
01963     std::size_t off = 0;
01964     return unpack(z, data, len, off, referenced, f, user_data, limit);
01965 }
01966 
01967 inline msgpack::object unpack(
01968     msgpack::zone& z,
01969     const char* data, std::size_t len,
01970     unpack_reference_func f, void* user_data, unpack_limit const& limit)
01971 {
01972     bool referenced;
01973     std::size_t off = 0;
01974     return unpack(z, data, len, off, referenced, f, user_data, limit);
01975 }
01976 
01977 // obsolete
01978 // pointer version
01979 inline void unpack(unpacked* result,
01980                    const char* data, std::size_t len, std::size_t* off, bool* referenced,
01981                    unpack_reference_func f, void* user_data, unpack_limit const& limit)
01982 {
01983     if (off) {
01984         if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data, limit);
01985         else unpack(*result, data, len, *off, f, user_data, limit);
01986     } else {
01987         if (referenced) unpack(*result, data, len, *referenced, f, user_data, limit);
01988         else unpack(*result, data, len, f, user_data, limit);
01989     }
01990 }
01991 
01992 inline bool unpacker::default_reference_func(msgpack::type::object_type /*type*/, std::size_t /*len*/, void*)
01993 {
01994     return true;
01995 }
01996 
01997 /// @cond
01998 }  // MSGPACK_API_VERSION_NAMESPACE(v1)
01999 /// @endcond
02000 
02001 }  // namespace msgpack
02002 
02003 
02004 #endif /* msgpack/unpack.hpp */