MessagePack for C++
unpack.hpp
Go to the documentation of this file.
1 //
2 // MessagePack for C++ deserializing routine
3 //
4 // Copyright (C) 2008-2016 FURUHASHI Sadayuki and KONDO Takatoshi
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 #ifndef MSGPACK_V1_UNPACK_HPP
11 #define MSGPACK_V1_UNPACK_HPP
12 
13 #include "msgpack/versioning.hpp"
14 #include "msgpack/unpack_decl.hpp"
15 #include "msgpack/object.hpp"
16 #include "msgpack/zone.hpp"
17 #include "msgpack/unpack_define.h"
18 #include "msgpack/cpp_config.hpp"
19 #include "msgpack/sysdep.h"
20 
21 #include <memory>
22 #include <stdexcept>
23 
24 #if !defined(MSGPACK_USE_CPP03)
25 #include <atomic>
26 #endif
27 
28 
29 #if defined(_MSC_VER)
30 // avoiding confliction std::max, std::min, and macro in windows.h
31 #ifndef NOMINMAX
32 #define NOMINMAX
33 #endif
34 #endif // defined(_MSC_VER)
35 
36 namespace msgpack {
37 
41 
42 struct unpack_error : public std::runtime_error {
43  explicit unpack_error(const std::string& msg)
44  :std::runtime_error(msg) {}
45 #if !defined(MSGPACK_USE_CPP03)
46  explicit unpack_error(const char* msg):
47  std::runtime_error(msg) {}
48 #endif // !defined(MSGPACK_USE_CPP03)
49 };
50 
51 struct parse_error : public unpack_error {
52  explicit parse_error(const std::string& msg)
53  :unpack_error(msg) {}
54 #if !defined(MSGPACK_USE_CPP03)
55  explicit parse_error(const char* msg)
56  :unpack_error(msg) {}
57 #endif // !defined(MSGPACK_USE_CPP03)
58 };
59 
61  explicit insufficient_bytes(const std::string& msg)
62  :unpack_error(msg) {}
63 #if !defined(MSGPACK_USE_CPP03)
64  explicit insufficient_bytes(const char* msg)
65  :unpack_error(msg) {}
66 #endif // !defined(MSGPACK_USE_CPP03)
67 };
68 
69 struct size_overflow : public unpack_error {
70  explicit size_overflow(const std::string& msg)
71  :unpack_error(msg) {}
72 #if !defined(MSGPACK_USE_CPP03)
73  explicit size_overflow(const char* msg)
74  :unpack_error(msg) {}
75 #endif
76 };
77 
79  array_size_overflow(const std::string& msg)
80  :size_overflow(msg) {}
81 #if !defined(MSGPACK_USE_CPP03)
82  array_size_overflow(const char* msg)
83  :size_overflow(msg) {}
84 #endif
85 };
86 
88  map_size_overflow(const std::string& msg)
89  :size_overflow(msg) {}
90 #if !defined(MSGPACK_USE_CPP03)
91  map_size_overflow(const char* msg)
92  :size_overflow(msg) {}
93 #endif
94 };
95 
97  str_size_overflow(const std::string& msg)
98  :size_overflow(msg) {}
99 #if !defined(MSGPACK_USE_CPP03)
100  str_size_overflow(const char* msg)
101  :size_overflow(msg) {}
102 #endif
103 };
104 
106  bin_size_overflow(const std::string& msg)
107  :size_overflow(msg) {}
108 #if !defined(MSGPACK_USE_CPP03)
109  bin_size_overflow(const char* msg)
110  :size_overflow(msg) {}
111 #endif
112 };
113 
115  ext_size_overflow(const std::string& msg)
116  :size_overflow(msg) {}
117 #if !defined(MSGPACK_USE_CPP03)
118  ext_size_overflow(const char* msg)
119  :size_overflow(msg) {}
120 #endif
121 };
122 
124  depth_size_overflow(const std::string& msg)
125  :size_overflow(msg) {}
126 #if !defined(MSGPACK_USE_CPP03)
127  depth_size_overflow(const char* msg)
128  :size_overflow(msg) {}
129 #endif
130 };
131 
132 namespace detail {
133 
134 class unpack_user {
135 public:
137  void* user_data = nullptr,
138  unpack_limit const& limit = unpack_limit())
139  :m_func(f), m_user_data(user_data), m_limit(limit) {}
140  msgpack::zone const& zone() const { return *m_zone; }
141  msgpack::zone& zone() { return *m_zone; }
142  void set_zone(msgpack::zone& zone) { m_zone = &zone; }
143  bool referenced() const { return m_referenced; }
144  void set_referenced(bool referenced) { m_referenced = referenced; }
145  unpack_reference_func reference_func() const { return m_func; }
146  void* user_data() const { return m_user_data; }
147  unpack_limit const& limit() const { return m_limit; }
148  unpack_limit& limit() { return m_limit; }
149 
150 private:
151  msgpack::zone* m_zone;
152  bool m_referenced;
153  unpack_reference_func m_func;
154  void* m_user_data;
155  unpack_limit m_limit;
156 };
157 
158 inline void unpack_uint8(uint8_t d, msgpack::object& o)
160 
161 inline void unpack_uint16(uint16_t d, msgpack::object& o)
163 
164 inline void unpack_uint32(uint32_t d, msgpack::object& o)
166 
167 inline void unpack_uint64(uint64_t d, msgpack::object& o)
169 
170 inline void unpack_int8(int8_t d, msgpack::object& o)
171 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
172  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
173 
174 inline void unpack_int16(int16_t d, msgpack::object& o)
175 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
176  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
177 
178 inline void unpack_int32(int32_t d, msgpack::object& o)
179 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
180  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
181 
182 inline void unpack_int64(int64_t d, msgpack::object& o)
183 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
184  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
185 
186 inline void unpack_float(float d, msgpack::object& o)
187 { o.type = msgpack::type::FLOAT; o.via.f64 = d; }
188 
189 inline void unpack_double(double d, msgpack::object& o)
190 { o.type = msgpack::type::FLOAT; o.via.f64 = d; }
191 
193 { o.type = msgpack::type::NIL; }
194 
196 { o.type = msgpack::type::BOOLEAN; o.via.boolean = true; }
197 
199 { o.type = msgpack::type::BOOLEAN; o.via.boolean = false; }
200 
201 struct unpack_array {
202  void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
203  if (n > u.limit().array()) throw msgpack::array_size_overflow("array size overflow");
205  o.via.array.size = 0;
206  o.via.array.ptr = static_cast<msgpack::object*>(u.zone().allocate_align(n*sizeof(msgpack::object)));
207  }
208 };
209 
211 {
212 #if defined(__GNUC__) && !defined(__clang__)
213  std::memcpy(&c.via.array.ptr[c.via.array.size++], &o, sizeof(msgpack::object));
214 #else /* __GNUC__ && !__clang__ */
215  c.via.array.ptr[c.via.array.size++] = o;
216 #endif /* __GNUC__ && !__clang__ */
217 }
218 
219 struct unpack_map {
220  void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
221  if (n > u.limit().map()) throw msgpack::map_size_overflow("map size overflow");
223  o.via.map.size = 0;
224  o.via.map.ptr = static_cast<msgpack::object_kv*>(u.zone().allocate_align(n*sizeof(msgpack::object_kv)));
225  }
226 };
227 
229 {
230 #if defined(__GNUC__) && !defined(__clang__)
231  std::memcpy(&c.via.map.ptr[c.via.map.size].key, &k, sizeof(msgpack::object));
232  std::memcpy(&c.via.map.ptr[c.via.map.size].val, &v, sizeof(msgpack::object));
233 #else /* __GNUC__ && !__clang__ */
234  c.via.map.ptr[c.via.map.size].key = k;
235  c.via.map.ptr[c.via.map.size].val = v;
236 #endif /* __GNUC__ && !__clang__ */
237  ++c.via.map.size;
238 }
239 
240 inline void unpack_str(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
241 {
243  if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
244  o.via.str.ptr = p;
245  u.set_referenced(true);
246  }
247  else {
248  if (l > u.limit().str()) throw msgpack::str_size_overflow("str size overflow");
249  char* tmp = static_cast<char*>(u.zone().allocate_align(l));
250  std::memcpy(tmp, p, l);
251  o.via.str.ptr = tmp;
252  }
253  o.via.str.size = l;
254 }
255 
256 inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
257 {
259  if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
260  o.via.bin.ptr = p;
261  u.set_referenced(true);
262  }
263  else {
264  if (l > u.limit().bin()) throw msgpack::bin_size_overflow("bin size overflow");
265  char* tmp = static_cast<char*>(u.zone().allocate_align(l));
266  std::memcpy(tmp, p, l);
267  o.via.bin.ptr = tmp;
268  }
269  o.via.bin.size = l;
270 }
271 
272 inline void unpack_ext(unpack_user& u, const char* p, std::size_t l, msgpack::object& o)
273 {
275  if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
276  o.via.ext.ptr = p;
277  u.set_referenced(true);
278  }
279  else {
280  if (l > u.limit().ext()) throw msgpack::ext_size_overflow("ext size overflow");
281  char* tmp = static_cast<char*>(u.zone().allocate_align(l));
282  std::memcpy(tmp, p, l);
283  o.via.ext.ptr = tmp;
284  }
285  o.via.ext.size = static_cast<uint32_t>(l - 1);
286 }
287 
288 
290 public:
291  msgpack::object const& obj() const { return m_obj; }
292  msgpack::object& obj() { return m_obj; }
293  void set_obj(msgpack::object const& obj) { m_obj = obj; }
294  std::size_t count() const { return m_count; }
295  void set_count(std::size_t count) { m_count = count; }
296  std::size_t decr_count() { return --m_count; }
297  uint32_t container_type() const { return m_container_type; }
298  void set_container_type(uint32_t container_type) { m_container_type = container_type; }
299  msgpack::object const& map_key() const { return m_map_key; }
300  void set_map_key(msgpack::object const& map_key) { m_map_key = map_key; }
301 private:
302  msgpack::object m_obj;
303  std::size_t m_count;
304  uint32_t m_container_type;
305  msgpack::object m_map_key;
306 };
307 
308 inline void init_count(void* buffer)
309 {
310 #if defined(MSGPACK_USE_CPP03)
311  *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer) = 1;
312 #else // defined(MSGPACK_USE_CPP03)
313  new (buffer) std::atomic<unsigned int>(1);
314 #endif // defined(MSGPACK_USE_CPP03)
315 }
316 
317 inline void decr_count(void* buffer)
318 {
319 #if defined(MSGPACK_USE_CPP03)
320  if(_msgpack_sync_decr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer)) == 0) {
321  free(buffer);
322  }
323 #else // defined(MSGPACK_USE_CPP03)
324  if (--*reinterpret_cast<std::atomic<unsigned int>*>(buffer) == 0) {
325  free(buffer);
326  }
327 #endif // defined(MSGPACK_USE_CPP03)
328 }
329 
330 inline void incr_count(void* buffer)
331 {
332 #if defined(MSGPACK_USE_CPP03)
333  _msgpack_sync_incr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer));
334 #else // defined(MSGPACK_USE_CPP03)
335  ++*reinterpret_cast<std::atomic<unsigned int>*>(buffer);
336 #endif // defined(MSGPACK_USE_CPP03)
337 }
338 
339 #if defined(MSGPACK_USE_CPP03)
340 inline _msgpack_atomic_counter_t get_count(void* buffer)
341 {
342  return *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer);
343 }
344 #else // defined(MSGPACK_USE_CPP03)
345 inline std::atomic<unsigned int> const& get_count(void* buffer)
346 {
347  return *reinterpret_cast<std::atomic<unsigned int>*>(buffer);
348 }
349 #endif // defined(MSGPACK_USE_CPP03)
350 
351 template <typename T>
352 struct value {
353  typedef T type;
354 };
355 template <>
356 struct value<fix_tag> {
357  typedef uint32_t type;
358 };
359 
360 template <typename T>
361 inline typename msgpack::enable_if<sizeof(T) == sizeof(fix_tag)>::type load(uint32_t& dst, const char* n) {
362  dst = static_cast<uint32_t>(*reinterpret_cast<const uint8_t*>(n)) & 0x0f;
363 }
364 
365 template <typename T>
366 inline typename msgpack::enable_if<sizeof(T) == 1>::type load(T& dst, const char* n) {
367  dst = static_cast<T>(*reinterpret_cast<const uint8_t*>(n));
368 }
369 
370 template <typename T>
371 inline typename msgpack::enable_if<sizeof(T) == 2>::type load(T& dst, const char* n) {
372  _msgpack_load16(T, n, &dst);
373 }
374 
375 template <typename T>
376 inline typename msgpack::enable_if<sizeof(T) == 4>::type load(T& dst, const char* n) {
377  _msgpack_load32(T, n, &dst);
378 }
379 
380 template <typename T>
381 inline typename msgpack::enable_if<sizeof(T) == 8>::type load(T& dst, const char* n) {
382  _msgpack_load64(T, n, &dst);
383 }
384 
385 class context {
386 public:
387  context(unpack_reference_func f, void* user_data, unpack_limit const& limit)
388  :m_trail(0), m_user(f, user_data, limit), m_cs(MSGPACK_CS_HEADER)
389  {
390  m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
391  m_stack.push_back(unpack_stack());
392  }
393 
394  void init()
395  {
396  m_cs = MSGPACK_CS_HEADER;
397  m_trail = 0;
398  m_stack.resize(1);
399  m_stack[0].set_obj(msgpack::object());
400  }
401 
402  msgpack::object const& data() const
403  {
404  return m_stack[0].obj();
405  }
406 
408  {
409  return m_user;
410  }
411 
412  unpack_user const& user() const
413  {
414  return m_user;
415  }
416 
417  int execute(const char* data, std::size_t len, std::size_t& off);
418 
419 private:
420  template <typename T>
421  static uint32_t next_cs(T p)
422  {
423  return static_cast<uint32_t>(*p) & 0x1f;
424  }
425 
426  template <typename T, typename Func>
427  int push_aggregate(
428  Func const& f,
429  uint32_t container_type,
430  msgpack::object& obj,
431  const char* load_pos,
432  std::size_t& off) {
433  typename value<T>::type tmp;
434  load<T>(tmp, load_pos);
435  f(m_user, tmp, m_stack.back().obj());
436  if(tmp == 0) {
437  obj = m_stack.back().obj();
438  int ret = push_proc(obj, off);
439  if (ret != 0) return ret;
440  }
441  else {
442  m_stack.back().set_container_type(container_type);
443  m_stack.back().set_count(tmp);
444  if (m_stack.size() <= m_user.limit().depth()) {
445  m_stack.push_back(unpack_stack());
446  }
447  else {
448  throw msgpack::depth_size_overflow("depth size overflow");
449  }
450  m_cs = MSGPACK_CS_HEADER;
451  ++m_current;
452  }
453  return 0;
454  }
455 
456  int push_item(msgpack::object& obj) {
457  bool finish = false;
458  while (!finish) {
459  if(m_stack.size() == 1) {
460  return 1;
461  }
462  unpack_stack& sp = *(m_stack.end() - 2);
463  switch(sp.container_type()) {
464  case MSGPACK_CT_ARRAY_ITEM:
465  unpack_array_item(sp.obj(), obj);
466  if(sp.decr_count() == 0) {
467  obj = sp.obj();
468  m_stack.pop_back();
469  }
470  else {
471  finish = true;
472  }
473  break;
474  case MSGPACK_CT_MAP_KEY:
475  sp.set_map_key(obj);
476  sp.set_container_type(MSGPACK_CT_MAP_VALUE);
477  finish = true;
478  break;
479  case MSGPACK_CT_MAP_VALUE:
480  unpack_map_item(sp.obj(), sp.map_key(), obj);
481  if(sp.decr_count() == 0) {
482  obj = sp.obj();
483  m_stack.pop_back();
484  }
485  else {
486  sp.set_container_type(MSGPACK_CT_MAP_KEY);
487  finish = true;
488  }
489  break;
490  default:
491  return -1;
492  }
493  }
494  return 0;
495  }
496 
497  int push_proc(msgpack::object& obj, std::size_t& off) {
498  int ret = push_item(obj);
499  if (ret > 0) {
500  m_stack[0].set_obj(obj);
501  ++m_current;
502  /*printf("-- finish --\n"); */
503  off = m_current - m_start;
504  }
505  else if (ret < 0) {
506  off = m_current - m_start;
507  }
508  else {
509  m_cs = MSGPACK_CS_HEADER;
510  ++m_current;
511  }
512  return ret;
513  }
514 
515  template <std::size_t N>
516  static void check_ext_size(std::size_t /*size*/) {
517  }
518 
519 private:
520  char const* m_start;
521  char const* m_current;
522 
523  std::size_t m_trail;
524  unpack_user m_user;
525  uint32_t m_cs;
526  std::vector<unpack_stack> m_stack;
527 };
528 
529 template <>
530 inline void context::check_ext_size<4>(std::size_t size) {
531  if (size == 0xffffffff) throw msgpack::ext_size_overflow("ext size overflow");
532 }
533 
534 inline int context::execute(const char* data, std::size_t len, std::size_t& off)
535 {
536  assert(len >= off);
537 
538  m_start = data;
539  m_current = data + off;
540  const char* const pe = data + len;
541  const char* n = nullptr;
542 
543  msgpack::object obj;
544 
545  if(m_current == pe) {
546  off = m_current - m_start;
547  return 0;
548  }
549  bool fixed_trail_again = false;
550  do {
551  if (m_cs == MSGPACK_CS_HEADER) {
552  fixed_trail_again = false;
553  int selector = *reinterpret_cast<const unsigned char*>(m_current);
554  if (0x00 <= selector && selector <= 0x7f) { // Positive Fixnum
555  unpack_uint8(*reinterpret_cast<const uint8_t*>(m_current), obj);
556  int ret = push_proc(obj, off);
557  if (ret != 0) return ret;
558  } else if(0xe0 <= selector && selector <= 0xff) { // Negative Fixnum
559  unpack_int8(*reinterpret_cast<const int8_t*>(m_current), obj);
560  int ret = push_proc(obj, off);
561  if (ret != 0) return ret;
562  } else if (0xc4 <= selector && selector <= 0xdf) {
563  const uint32_t trail[] = {
564  1, // bin 8 0xc4
565  2, // bin 16 0xc5
566  4, // bin 32 0xc6
567  1, // ext 8 0xc7
568  2, // ext 16 0xc8
569  4, // ext 32 0xc9
570  4, // float 32 0xca
571  8, // float 64 0xcb
572  1, // uint 8 0xcc
573  2, // uint 16 0xcd
574  4, // uint 32 0xce
575  8, // uint 64 0xcf
576  1, // int 8 0xd0
577  2, // int 16 0xd1
578  4, // int 32 0xd2
579  8, // int 64 0xd3
580  2, // fixext 1 0xd4
581  3, // fixext 2 0xd5
582  5, // fixext 4 0xd6
583  9, // fixext 8 0xd7
584  17,// fixext 16 0xd8
585  1, // str 8 0xd9
586  2, // str 16 0xda
587  4, // str 32 0xdb
588  2, // array 16 0xdc
589  4, // array 32 0xdd
590  2, // map 16 0xde
591  4, // map 32 0xdf
592  };
593  m_trail = trail[selector - 0xc4];
594  m_cs = next_cs(m_current);
595  fixed_trail_again = true;
596  } else if(0xa0 <= selector && selector <= 0xbf) { // FixStr
597  m_trail = static_cast<uint32_t>(*m_current) & 0x1f;
598  if(m_trail == 0) {
599  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
600  int ret = push_proc(obj, off);
601  if (ret != 0) return ret;
602  }
603  else {
604  m_cs = MSGPACK_ACS_STR_VALUE;
605  fixed_trail_again = true;
606  }
607 
608  } else if(0x90 <= selector && selector <= 0x9f) { // FixArray
609  int ret = push_aggregate<fix_tag>(
610  unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, m_current, off);
611  if (ret != 0) return ret;
612  } else if(0x80 <= selector && selector <= 0x8f) { // FixMap
613  int ret = push_aggregate<fix_tag>(
614  unpack_map(), MSGPACK_CT_MAP_KEY, obj, m_current, off);
615  if (ret != 0) return ret;
616  } else if(selector == 0xc2) { // false
617  unpack_false(obj);
618  int ret = push_proc(obj, off);
619  if (ret != 0) return ret;
620  } else if(selector == 0xc3) { // true
621  unpack_true(obj);
622  int ret = push_proc(obj, off);
623  if (ret != 0) return ret;
624  } else if(selector == 0xc0) { // nil
625  unpack_nil(obj);
626  int ret = push_proc(obj, off);
627  if (ret != 0) return ret;
628  } else {
629  off = m_current - m_start;
630  return -1;
631  }
632  // end MSGPACK_CS_HEADER
633  }
634  if (m_cs != MSGPACK_CS_HEADER || fixed_trail_again) {
635  if (fixed_trail_again) {
636  ++m_current;
637  fixed_trail_again = false;
638  }
639  if(static_cast<std::size_t>(pe - m_current) < m_trail) {
640  off = m_current - m_start;
641  return 0;
642  }
643  n = m_current;
644  m_current += m_trail - 1;
645  switch(m_cs) {
646  //case MSGPACK_CS_
647  //case MSGPACK_CS_
648  case MSGPACK_CS_FLOAT: {
649  union { uint32_t i; float f; } mem;
650  load<uint32_t>(mem.i, n);
651  unpack_float(mem.f, obj);
652  int ret = push_proc(obj, off);
653  if (ret != 0) return ret;
654  } break;
655  case MSGPACK_CS_DOUBLE: {
656  union { uint64_t i; double f; } mem;
657  load<uint64_t>(mem.i, n);
658 #if defined(TARGET_OS_IPHONE)
659  // ok
660 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
661  // https://github.com/msgpack/msgpack-perl/pull/1
662  mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
663 #endif
664  unpack_double(mem.f, obj);
665  int ret = push_proc(obj, off);
666  if (ret != 0) return ret;
667  } break;
668  case MSGPACK_CS_UINT_8: {
669  uint8_t tmp;
670  load<uint8_t>(tmp, n);
671  unpack_uint8(tmp, obj);
672  int ret = push_proc(obj, off);
673  if (ret != 0) return ret;
674  } break;
675  case MSGPACK_CS_UINT_16: {
676  uint16_t tmp;
677  load<uint16_t>(tmp, n);
678  unpack_uint16(tmp, obj);
679  int ret = push_proc(obj, off);
680  if (ret != 0) return ret;
681  } break;
682  case MSGPACK_CS_UINT_32: {
683  uint32_t tmp;
684  load<uint32_t>(tmp, n);
685  unpack_uint32(tmp, obj);
686  int ret = push_proc(obj, off);
687  if (ret != 0) return ret;
688  } break;
689  case MSGPACK_CS_UINT_64: {
690  uint64_t tmp;
691  load<uint64_t>(tmp, n);
692  unpack_uint64(tmp, obj);
693  int ret = push_proc(obj, off);
694  if (ret != 0) return ret;
695  } break;
696  case MSGPACK_CS_INT_8: {
697  int8_t tmp;
698  load<int8_t>(tmp, n);
699  unpack_int8(tmp, obj);
700  int ret = push_proc(obj, off);
701  if (ret != 0) return ret;
702  } break;
703  case MSGPACK_CS_INT_16: {
704  int16_t tmp;
705  load<int16_t>(tmp, n);
706  unpack_int16(tmp, obj);
707  int ret = push_proc(obj, off);
708  if (ret != 0) return ret;
709  } break;
710  case MSGPACK_CS_INT_32: {
711  int32_t tmp;
712  load<int32_t>(tmp, n);
713  unpack_int32(tmp, obj);
714  int ret = push_proc(obj, off);
715  if (ret != 0) return ret;
716  } break;
717  case MSGPACK_CS_INT_64: {
718  int64_t tmp;
719  load<int64_t>(tmp, n);
720  unpack_int64(tmp, obj);
721  int ret = push_proc(obj, off);
722  if (ret != 0) return ret;
723  } break;
724  case MSGPACK_CS_FIXEXT_1: {
725  unpack_ext(m_user, n, 1+1, obj);
726  int ret = push_proc(obj, off);
727  if (ret != 0) return ret;
728  } break;
729  case MSGPACK_CS_FIXEXT_2: {
730  unpack_ext(m_user, n, 2+1, obj);
731  int ret = push_proc(obj, off);
732  if (ret != 0) return ret;
733  } break;
734  case MSGPACK_CS_FIXEXT_4: {
735  unpack_ext(m_user, n, 4+1, obj);
736  int ret = push_proc(obj, off);
737  if (ret != 0) return ret;
738  } break;
739  case MSGPACK_CS_FIXEXT_8: {
740  unpack_ext(m_user, n, 8+1, obj);
741  int ret = push_proc(obj, off);
742  if (ret != 0) return ret;
743  } break;
744  case MSGPACK_CS_FIXEXT_16: {
745  unpack_ext(m_user, n, 16+1, obj);
746  int ret = push_proc(obj, off);
747  if (ret != 0) return ret;
748  } break;
749  case MSGPACK_CS_STR_8: {
750  uint8_t tmp;
751  load<uint8_t>(tmp, n);
752  m_trail = tmp;
753  if(m_trail == 0) {
754  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
755  int ret = push_proc(obj, off);
756  if (ret != 0) return ret;
757  }
758  else {
759  m_cs = MSGPACK_ACS_STR_VALUE;
760  fixed_trail_again = true;
761  }
762  } break;
763  case MSGPACK_CS_BIN_8: {
764  uint8_t tmp;
765  load<uint8_t>(tmp, n);
766  m_trail = tmp;
767  if(m_trail == 0) {
768  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
769  int ret = push_proc(obj, off);
770  if (ret != 0) return ret;
771  }
772  else {
773  m_cs = MSGPACK_ACS_BIN_VALUE;
774  fixed_trail_again = true;
775  }
776  } break;
777  case MSGPACK_CS_EXT_8: {
778  uint8_t tmp;
779  load<uint8_t>(tmp, n);
780  m_trail = tmp + 1;
781  if(m_trail == 0) {
782  unpack_ext(m_user, n, m_trail, obj);
783  int ret = push_proc(obj, off);
784  if (ret != 0) return ret;
785  }
786  else {
787  m_cs = MSGPACK_ACS_EXT_VALUE;
788  fixed_trail_again = true;
789  }
790  } break;
791  case MSGPACK_CS_STR_16: {
792  uint16_t tmp;
793  load<uint16_t>(tmp, n);
794  m_trail = tmp;
795  if(m_trail == 0) {
796  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
797  int ret = push_proc(obj, off);
798  if (ret != 0) return ret;
799  }
800  else {
801  m_cs = MSGPACK_ACS_STR_VALUE;
802  fixed_trail_again = true;
803  }
804  } break;
805  case MSGPACK_CS_BIN_16: {
806  uint16_t tmp;
807  load<uint16_t>(tmp, n);
808  m_trail = tmp;
809  if(m_trail == 0) {
810  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
811  int ret = push_proc(obj, off);
812  if (ret != 0) return ret;
813  }
814  else {
815  m_cs = MSGPACK_ACS_BIN_VALUE;
816  fixed_trail_again = true;
817  }
818  } break;
819  case MSGPACK_CS_EXT_16: {
820  uint16_t tmp;
821  load<uint16_t>(tmp, n);
822  m_trail = tmp + 1;
823  if(m_trail == 0) {
824  unpack_ext(m_user, n, m_trail, obj);
825  int ret = push_proc(obj, off);
826  if (ret != 0) return ret;
827  }
828  else {
829  m_cs = MSGPACK_ACS_EXT_VALUE;
830  fixed_trail_again = true;
831  }
832  } break;
833  case MSGPACK_CS_STR_32: {
834  uint32_t tmp;
835  load<uint32_t>(tmp, n);
836  m_trail = tmp;
837  if(m_trail == 0) {
838  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
839  int ret = push_proc(obj, off);
840  if (ret != 0) return ret;
841  }
842  else {
843  m_cs = MSGPACK_ACS_STR_VALUE;
844  fixed_trail_again = true;
845  }
846  } break;
847  case MSGPACK_CS_BIN_32: {
848  uint32_t tmp;
849  load<uint32_t>(tmp, n);
850  m_trail = tmp;
851  if(m_trail == 0) {
852  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
853  int ret = push_proc(obj, off);
854  if (ret != 0) return ret;
855  }
856  else {
857  m_cs = MSGPACK_ACS_BIN_VALUE;
858  fixed_trail_again = true;
859  }
860  } break;
861  case MSGPACK_CS_EXT_32: {
862  uint32_t tmp;
863  load<uint32_t>(tmp, n);
864  check_ext_size<sizeof(std::size_t)>(tmp);
865  m_trail = tmp;
866  ++m_trail;
867  if(m_trail == 0) {
868  unpack_ext(m_user, n, m_trail, obj);
869  int ret = push_proc(obj, off);
870  if (ret != 0) return ret;
871  }
872  else {
873  m_cs = MSGPACK_ACS_EXT_VALUE;
874  fixed_trail_again = true;
875  }
876  } break;
877  case MSGPACK_ACS_STR_VALUE: {
878  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
879  int ret = push_proc(obj, off);
880  if (ret != 0) return ret;
881  } break;
882  case MSGPACK_ACS_BIN_VALUE: {
883  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
884  int ret = push_proc(obj, off);
885  if (ret != 0) return ret;
886  } break;
887  case MSGPACK_ACS_EXT_VALUE: {
888  unpack_ext(m_user, n, m_trail, obj);
889  int ret = push_proc(obj, off);
890  if (ret != 0) return ret;
891  } break;
892  case MSGPACK_CS_ARRAY_16: {
893  int ret = push_aggregate<uint16_t>(
894  unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
895  if (ret != 0) return ret;
896  } break;
897  case MSGPACK_CS_ARRAY_32: {
898  /* FIXME security guard */
899  int ret = push_aggregate<uint32_t>(
900  unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
901  if (ret != 0) return ret;
902  } break;
903  case MSGPACK_CS_MAP_16: {
904  int ret = push_aggregate<uint16_t>(
905  unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
906  if (ret != 0) return ret;
907  } break;
908  case MSGPACK_CS_MAP_32: {
909  /* FIXME security guard */
910  int ret = push_aggregate<uint32_t>(
911  unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
912  if (ret != 0) return ret;
913  } break;
914  default:
915  off = m_current - m_start;
916  return -1;
917  }
918  }
919  } while(m_current != pe);
920 
921  off = m_current - m_start;
922  return 0;
923 }
924 
925 } // detail
926 
927 
929 class unpacker {
930 public:
932 
940  unpacker(unpack_reference_func f = &unpacker::default_reference_func,
941  void* user_data = nullptr,
942  std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE,
943  unpack_limit const& limit = unpack_limit());
944 
945 #if !defined(MSGPACK_USE_CPP03)
946  unpacker(unpacker&& other);
947  unpacker& operator=(unpacker&& other);
948 #endif // !defined(MSGPACK_USE_CPP03)
949 
950  ~unpacker();
951 
952 public:
954 
961  void reserve_buffer(std::size_t size = MSGPACK_UNPACKER_RESERVE_SIZE);
962 
964 
969  char* buffer();
970 
972 
978  std::size_t buffer_capacity() const;
979 
981 
990  void buffer_consumed(std::size_t size);
991 
993 
1006  bool next(msgpack::object_handle* result);
1007 
1009 
1022  bool next(msgpack::object_handle& result, bool& referenced);
1023 
1025 
1036  bool next(msgpack::object_handle& result);
1037 
1039 
1042  std::size_t message_size() const;
1043 
1045  bool execute();
1046 
1048  msgpack::object const& data();
1049 
1051  msgpack::zone* release_zone();
1052 
1054  void reset_zone();
1055 
1057  void reset();
1058 
1059 public:
1061 
1067  std::size_t parsed_size() const;
1068 
1070 
1076  char* nonparsed_buffer();
1077 
1079 
1085  std::size_t nonparsed_size() const;
1086 
1088 
1095  void skip_nonparsed_buffer(std::size_t size);
1096 
1098 
1102  void remove_nonparsed_buffer();
1103 
1104 private:
1105  void expand_buffer(std::size_t size);
1106  int execute_imp();
1107  bool flush_zone();
1108  static bool default_reference_func(msgpack::type::object_type type, std::size_t len, void*);
1109 
1110 private:
1111  char* m_buffer;
1112  std::size_t m_used;
1113  std::size_t m_free;
1114  std::size_t m_off;
1115  std::size_t m_parsed;
1117  std::size_t m_initial_buffer_size;
1118  detail::context m_ctx;
1119 
1120 #if defined(MSGPACK_USE_CPP03)
1121 private:
1122  unpacker(const unpacker&);
1123  unpacker& operator=(const unpacker&);
1124 #else // defined(MSGPACK_USE_CPP03)
1125  unpacker(const unpacker&) = delete;
1126  unpacker& operator=(const unpacker&) = delete;
1127 #endif // defined(MSGPACK_USE_CPP03)
1128 };
1129 
1131  void* user_data,
1132  std::size_t initial_buffer_size,
1133  unpack_limit const& limit)
1134  :m_z(new msgpack::zone), m_ctx(f, user_data, limit)
1135 {
1136  if(initial_buffer_size < COUNTER_SIZE) {
1137  initial_buffer_size = COUNTER_SIZE;
1138  }
1139 
1140  char* buffer = static_cast<char*>(::malloc(initial_buffer_size));
1141  if(!buffer) {
1142  throw std::bad_alloc();
1143  }
1144 
1145  m_buffer = buffer;
1146  m_used = COUNTER_SIZE;
1147  m_free = initial_buffer_size - m_used;
1148  m_off = COUNTER_SIZE;
1149  m_parsed = 0;
1150  m_initial_buffer_size = initial_buffer_size;
1151 
1152  detail::init_count(m_buffer);
1153 
1154  m_ctx.init();
1155  m_ctx.user().set_zone(*m_z);
1156  m_ctx.user().set_referenced(false);
1157 }
1158 
1159 #if !defined(MSGPACK_USE_CPP03)
1160 // Move constructor and move assignment operator
1161 
1163  :m_buffer(other.m_buffer),
1164  m_used(other.m_used),
1165  m_free(other.m_free),
1166  m_off(other.m_off),
1167  m_parsed(other.m_parsed),
1168  m_z(std::move(other.m_z)),
1169  m_initial_buffer_size(other.m_initial_buffer_size),
1170  m_ctx(other.m_ctx) {
1171  other.m_buffer = nullptr;
1172 }
1173 
1175  this->~unpacker();
1176  new (this) unpacker(std::move(other));
1177  return *this;
1178 }
1179 
1180 #endif // !defined(MSGPACK_USE_CPP03)
1181 
1182 
1184 {
1185  // These checks are required for move operations.
1186  if (m_buffer) detail::decr_count(m_buffer);
1187 }
1188 
1189 
1190 inline void unpacker::reserve_buffer(std::size_t size)
1191 {
1192  if(m_free >= size) return;
1193  expand_buffer(size);
1194 }
1195 
1196 inline void unpacker::expand_buffer(std::size_t size)
1197 {
1198  if(m_used == m_off && detail::get_count(m_buffer) == 1
1199  && !m_ctx.user().referenced()) {
1200  // rewind buffer
1201  m_free += m_used - COUNTER_SIZE;
1202  m_used = COUNTER_SIZE;
1203  m_off = COUNTER_SIZE;
1204 
1205  if(m_free >= size) return;
1206  }
1207 
1208  if(m_off == COUNTER_SIZE) {
1209  std::size_t next_size = (m_used + m_free) * 2; // include COUNTER_SIZE
1210  while(next_size < size + m_used) {
1211  std::size_t tmp_next_size = next_size * 2;
1212  if (tmp_next_size <= next_size) {
1213  next_size = size + m_used;
1214  break;
1215  }
1216  next_size = tmp_next_size;
1217  }
1218 
1219  char* tmp = static_cast<char*>(::realloc(m_buffer, next_size));
1220  if(!tmp) {
1221  throw std::bad_alloc();
1222  }
1223 
1224  m_buffer = tmp;
1225  m_free = next_size - m_used;
1226 
1227  } else {
1228  std::size_t next_size = m_initial_buffer_size; // include COUNTER_SIZE
1229  std::size_t not_parsed = m_used - m_off;
1230  while(next_size < size + not_parsed + COUNTER_SIZE) {
1231  std::size_t tmp_next_size = next_size * 2;
1232  if (tmp_next_size <= next_size) {
1233  next_size = size + not_parsed + COUNTER_SIZE;
1234  break;
1235  }
1236  next_size = tmp_next_size;
1237  }
1238 
1239  char* tmp = static_cast<char*>(::malloc(next_size));
1240  if(!tmp) {
1241  throw std::bad_alloc();
1242  }
1243 
1244  detail::init_count(tmp);
1245 
1246  std::memcpy(tmp+COUNTER_SIZE, m_buffer + m_off, not_parsed);
1247 
1248  if(m_ctx.user().referenced()) {
1249  try {
1250  m_z->push_finalizer(&detail::decr_count, m_buffer);
1251  }
1252  catch (...) {
1253  ::free(tmp);
1254  throw;
1255  }
1256  m_ctx.user().set_referenced(false);
1257  } else {
1258  detail::decr_count(m_buffer);
1259  }
1260 
1261  m_buffer = tmp;
1262  m_used = not_parsed + COUNTER_SIZE;
1263  m_free = next_size - m_used;
1264  m_off = COUNTER_SIZE;
1265  }
1266 }
1267 
1268 inline char* unpacker::buffer()
1269 {
1270  return m_buffer + m_used;
1271 }
1272 
1273 inline std::size_t unpacker::buffer_capacity() const
1274 {
1275  return m_free;
1276 }
1277 
1278 inline void unpacker::buffer_consumed(std::size_t size)
1279 {
1280  m_used += size;
1281  m_free -= size;
1282 }
1283 
1284 inline bool unpacker::next(msgpack::object_handle& result, bool& referenced)
1285 {
1286  referenced = false;
1287  int ret = execute_imp();
1288  if(ret < 0) {
1289  throw msgpack::parse_error("parse error");
1290  }
1291 
1292  if(ret == 0) {
1293  result.zone().reset();
1294  result.set(msgpack::object());
1295  return false;
1296 
1297  } else {
1298  referenced = m_ctx.user().referenced();
1299  result.zone().reset( release_zone() );
1300  result.set(data());
1301  reset();
1302  return true;
1303  }
1304 }
1305 
1307 {
1308  bool referenced;
1309  return next(result, referenced);
1310 }
1311 
1313 {
1314  return next(*result);
1315 }
1316 
1317 
1318 inline bool unpacker::execute()
1319 {
1320  int ret = execute_imp();
1321  if(ret < 0) {
1322  throw msgpack::parse_error("parse error");
1323  } else if(ret == 0) {
1324  return false;
1325  } else {
1326  return true;
1327  }
1328 }
1329 
1330 inline int unpacker::execute_imp()
1331 {
1332  std::size_t off = m_off;
1333  int ret = m_ctx.execute(m_buffer, m_used, m_off);
1334  if(m_off > off) {
1335  m_parsed += m_off - off;
1336  }
1337  return ret;
1338 }
1339 
1341 {
1342  return m_ctx.data();
1343 }
1344 
1346 {
1347  if(!flush_zone()) {
1348  return nullptr;
1349  }
1350 
1351  msgpack::zone* r = new msgpack::zone;
1352  msgpack::zone* old = m_z.release();
1353  m_z.reset(r);
1354  m_ctx.user().set_zone(*m_z);
1355 
1356  return old;
1357 }
1358 
1360 {
1361  m_z->clear();
1362 }
1363 
1364 inline bool unpacker::flush_zone()
1365 {
1366  if(m_ctx.user().referenced()) {
1367  try {
1368  m_z->push_finalizer(&detail::decr_count, m_buffer);
1369  } catch (...) {
1370  return false;
1371  }
1372  m_ctx.user().set_referenced(false);
1373 
1374  detail::incr_count(m_buffer);
1375  }
1376 
1377  return true;
1378 }
1379 
1380 inline void unpacker::reset()
1381 {
1382  m_ctx.init();
1383  // don't reset referenced flag
1384  m_parsed = 0;
1385 }
1386 
1387 inline std::size_t unpacker::message_size() const
1388 {
1389  return m_parsed - m_off + m_used;
1390 }
1391 
1392 inline std::size_t unpacker::parsed_size() const
1393 {
1394  return m_parsed;
1395 }
1396 
1398 {
1399  return m_buffer + m_off;
1400 }
1401 
1402 inline std::size_t unpacker::nonparsed_size() const
1403 {
1404  return m_used - m_off;
1405 }
1406 
1407 inline void unpacker::skip_nonparsed_buffer(std::size_t size)
1408 {
1409  m_off += size;
1410 }
1411 
1413 {
1414  m_used = m_off;
1415 }
1416 
1417 namespace detail {
1418 
1419 inline unpack_return
1420 unpack_imp(const char* data, std::size_t len, std::size_t& off,
1421  msgpack::zone& result_zone, msgpack::object& result, bool& referenced,
1422  unpack_reference_func f = nullptr, void* user_data = nullptr,
1423  unpack_limit const& limit = unpack_limit())
1424 {
1425  std::size_t noff = off;
1426 
1427  if(len <= noff) {
1428  // FIXME
1429  return UNPACK_CONTINUE;
1430  }
1431 
1432  detail::context ctx(f, user_data, limit);
1433  ctx.init();
1434 
1435  ctx.user().set_zone(result_zone);
1436  ctx.user().set_referenced(false);
1437  referenced = false;
1438 
1439  int e = ctx.execute(data, len, noff);
1440  if(e < 0) {
1441  return UNPACK_PARSE_ERROR;
1442  }
1443 
1444  referenced = ctx.user().referenced();
1445  off = noff;
1446 
1447  if(e == 0) {
1448  return UNPACK_CONTINUE;
1449  }
1450 
1451  result = ctx.data();
1452 
1453  if(noff < len) {
1454  return UNPACK_EXTRA_BYTES;
1455  }
1456 
1457  return UNPACK_SUCCESS;
1458 }
1459 
1460 } // detail
1461 
1462 // reference version
1463 
1465  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1466  unpack_reference_func f, void* user_data,
1467  unpack_limit const& limit
1468 )
1469 {
1470  msgpack::object obj;
1472  referenced = false;
1473  std::size_t noff = off;
1475  data, len, noff, *z, obj, referenced, f, user_data, limit);
1476 
1477  switch(ret) {
1478  case UNPACK_SUCCESS:
1479  off = noff;
1480  return msgpack::object_handle(obj, msgpack::move(z));
1481  case UNPACK_EXTRA_BYTES:
1482  off = noff;
1483  return msgpack::object_handle(obj, msgpack::move(z));
1484  case UNPACK_CONTINUE:
1485  throw msgpack::insufficient_bytes("insufficient bytes");
1486  case UNPACK_PARSE_ERROR:
1487  default:
1488  throw msgpack::parse_error("parse error");
1489  }
1490  return msgpack::object_handle();
1491 }
1492 
1494  const char* data, std::size_t len, std::size_t& off,
1495  unpack_reference_func f, void* user_data,
1496  unpack_limit const& limit)
1497 {
1498  bool referenced;
1499  return unpack(data, len, off, referenced, f, user_data, limit);
1500 }
1501 
1503  const char* data, std::size_t len, bool& referenced,
1504  unpack_reference_func f, void* user_data,
1505  unpack_limit const& limit)
1506 {
1507  std::size_t off = 0;
1508  return unpack(data, len, off, referenced, f, user_data, limit);
1509 }
1510 
1512  const char* data, std::size_t len,
1513  unpack_reference_func f, void* user_data,
1514  unpack_limit const& limit)
1515 {
1516  bool referenced;
1517  std::size_t off = 0;
1518  return unpack(data, len, off, referenced, f, user_data, limit);
1519 }
1520 
1521 inline void unpack(
1522  msgpack::object_handle& result,
1523  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1524  unpack_reference_func f, void* user_data,
1525  unpack_limit const& limit)
1526 {
1527  msgpack::object obj;
1529  referenced = false;
1530  std::size_t noff = off;
1532  data, len, noff, *z, obj, referenced, f, user_data, limit);
1533 
1534  switch(ret) {
1535  case UNPACK_SUCCESS:
1536  off = noff;
1537  result.set(obj);
1538  result.zone() = msgpack::move(z);
1539  return;
1540  case UNPACK_EXTRA_BYTES:
1541  off = noff;
1542  result.set(obj);
1543  result.zone() = msgpack::move(z);
1544  return;
1545  case UNPACK_CONTINUE:
1546  throw msgpack::insufficient_bytes("insufficient bytes");
1547  case UNPACK_PARSE_ERROR:
1548  default:
1549  throw msgpack::parse_error("parse error");
1550  }
1551 }
1552 
1553 inline void unpack(
1554  msgpack::object_handle& result,
1555  const char* data, std::size_t len, std::size_t& off,
1556  unpack_reference_func f, void* user_data,
1557  unpack_limit const& limit)
1558 {
1559  bool referenced;
1560  unpack(result, data, len, off, referenced, f, user_data, limit);
1561 }
1562 
1563 inline void unpack(
1564  msgpack::object_handle& result,
1565  const char* data, std::size_t len, bool& referenced,
1566  unpack_reference_func f, void* user_data,
1567  unpack_limit const& limit)
1568 {
1569  std::size_t off = 0;
1570  unpack(result, data, len, off, referenced, f, user_data, limit);
1571 }
1572 
1573 inline void unpack(
1574  msgpack::object_handle& result,
1575  const char* data, std::size_t len,
1576  unpack_reference_func f, void* user_data,
1577  unpack_limit const& limit)
1578 {
1579  bool referenced;
1580  std::size_t off = 0;
1581  unpack(result, data, len, off, referenced, f, user_data, limit);
1582 }
1583 
1584 
1586  msgpack::zone& z,
1587  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1588  unpack_reference_func f, void* user_data,
1589  unpack_limit const& limit)
1590 {
1591  msgpack::object obj;
1592  std::size_t noff = off;
1593  referenced = false;
1595  data, len, noff, z, obj, referenced, f, user_data, limit);
1596 
1597  switch(ret) {
1598  case UNPACK_SUCCESS:
1599  off = noff;
1600  return obj;
1601  case UNPACK_EXTRA_BYTES:
1602  off = noff;
1603  return obj;
1604  case UNPACK_CONTINUE:
1605  throw msgpack::insufficient_bytes("insufficient bytes");
1606  case UNPACK_PARSE_ERROR:
1607  default:
1608  throw msgpack::parse_error("parse error");
1609  }
1610  return obj;
1611 }
1612 
1614  msgpack::zone& z,
1615  const char* data, std::size_t len, std::size_t& off,
1616  unpack_reference_func f, void* user_data,
1617  unpack_limit const& limit)
1618 {
1619  bool referenced;
1620  return unpack(z, data, len, off, referenced, f, user_data, limit);
1621 }
1622 
1624  msgpack::zone& z,
1625  const char* data, std::size_t len, bool& referenced,
1626  unpack_reference_func f, void* user_data,
1627  unpack_limit const& limit)
1628 {
1629  std::size_t off = 0;
1630  return unpack(z, data, len, off, referenced, f, user_data, limit);
1631 }
1632 
1634  msgpack::zone& z,
1635  const char* data, std::size_t len,
1636  unpack_reference_func f, void* user_data,
1637  unpack_limit const& limit)
1638 {
1639  bool referenced;
1640  std::size_t off = 0;
1641  return unpack(z, data, len, off, referenced, f, user_data, limit);
1642 }
1643 
1644 // obsolete
1645 // pointer version
1646 inline void unpack(
1647  msgpack::object_handle* result,
1648  const char* data, std::size_t len, std::size_t* off, bool* referenced,
1649  unpack_reference_func f, void* user_data,
1650  unpack_limit const& limit)
1651 {
1652  if (off)
1653  if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data, limit);
1654  else unpack(*result, data, len, *off, f, user_data, limit);
1655  else
1656  if (referenced) unpack(*result, data, len, *referenced, f, user_data, limit);
1657  else unpack(*result, data, len, f, user_data, limit);
1658 }
1659 
1660 inline bool unpacker::default_reference_func(msgpack::type::object_type /*type*/, std::size_t /*len*/, void*)
1661 {
1662  return true;
1663 }
1664 
1666 } // MSGPACK_API_VERSION_NAMESPACE(v1)
1668 
1669 } // namespace msgpack
1670 
1671 
1672 #endif // MSGPACK_V1_UNPACK_HPP
uint32_t type
Definition: unpack.hpp:357
map_size_overflow(const char *msg)
Definition: unpack.hpp:91
ext_size_overflow(const std::string &msg)
Definition: unpack.hpp:115
unpack_return
Definition: unpack_decl.hpp:437
Definition: object_fwd_decl.hpp:37
Definition: unpack.hpp:134
std::size_t buffer_capacity() const
Get buffer capacity.
Definition: unpack.hpp:1273
std::size_t array() const
Definition: unpack_decl.hpp:101
Definition: unpack.hpp:201
char * nonparsed_buffer()
Get the address that is not parsed in the buffer.
Definition: unpack.hpp:1397
Definition: unpack.hpp:219
std::atomic< unsigned int > const & get_count(void *buffer)
Definition: unpack.hpp:345
void unpack_int8(int8_t d, msgpack::object &o)
Definition: unpack.hpp:170
insufficient_bytes(const char *msg)
Definition: unpack.hpp:64
msgpack::object_kv * ptr
Definition: object_fwd.hpp:29
void incr_count(void *buffer)
Definition: unpack.hpp:330
Definition: unpack_decl.hpp:86
Definition: unpack.hpp:96
context(unpack_reference_func f, void *user_data, unpack_limit const &limit)
Definition: unpack.hpp:387
uint32_t size
Definition: object_fwd.hpp:23
unpack_error(const std::string &msg)
Definition: unpack.hpp:43
void set_referenced(bool referenced)
Definition: unpack.hpp:144
void * allocate_align(size_t size, size_t align=MSGPACK_ZONE_ALIGN)
Definition: cpp03_zone.hpp:236
~unpacker()
Definition: unpack.hpp:1183
unpack_error(const char *msg)
Definition: unpack.hpp:46
msgpack::object_handle unpack(const char *data, std::size_t len, std::size_t &off, bool &referenced, unpack_reference_func f, void *user_data, unpack_limit const &limit)
Unpack msgpack::object from a buffer.
Definition: unpack.hpp:1464
std::size_t ext() const
Definition: unpack_decl.hpp:105
Definition: unpack_decl.hpp:439
Definition: object_fwd_decl.hpp:30
const char * ptr
Definition: object_fwd.hpp:39
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE
Definition: unpack_decl.hpp:42
void unpack_ext(unpack_user &u, const char *p, std::size_t l, msgpack::object &o)
Definition: unpack.hpp:272
map_size_overflow(const std::string &msg)
Definition: unpack.hpp:88
void set_container_type(uint32_t container_type)
Definition: unpack.hpp:298
void unpack_uint32(uint32_t d, msgpack::object &o)
Definition: unpack.hpp:164
void set(msgpack::object const &obj)
Definition: object.hpp:64
unpack_user const & user() const
Definition: unpack.hpp:412
depth_size_overflow(const std::string &msg)
Definition: unpack.hpp:124
union_type via
Definition: object_fwd.hpp:92
void unpack_str(unpack_user &u, const char *p, uint32_t l, msgpack::object &o)
Definition: unpack.hpp:240
bool execute()
Definition: unpack.hpp:1318
Definition: unpack.hpp:42
bool(* unpack_reference_func)(msgpack::type::object_type type, std::size_t size, void *user_data)
The type of reference or copy judging function.
Definition: unpack_decl.hpp:73
Definition: object_fwd_decl.hpp:38
Definition: unpack.hpp:123
void * user_data() const
Definition: unpack.hpp:146
void unpack_int16(int16_t d, msgpack::object &o)
Definition: unpack.hpp:174
std::size_t parsed_size() const
Get parsed message size.
Definition: unpack.hpp:1392
void unpack_bin(unpack_user &u, const char *p, uint32_t l, msgpack::object &o)
Definition: unpack.hpp:256
std::size_t count() const
Definition: unpack.hpp:294
const char * ptr
Definition: object_fwd.hpp:46
msgpack::object * ptr
Definition: object_fwd.hpp:24
parse_error(const std::string &msg)
Definition: unpack.hpp:52
void unpack_uint8(uint8_t d, msgpack::object &o)
Definition: unpack.hpp:158
int execute(const char *data, std::size_t len, std::size_t &off)
Definition: unpack.hpp:534
msgpack::object val
Definition: object.hpp:31
uint32_t size
Definition: object_fwd.hpp:38
T type
Definition: unpack.hpp:353
Definition: adaptor_base.hpp:15
Definition: unpack.hpp:51
Definition: unpack.hpp:114
unpack_return unpack_imp(const char *data, std::size_t len, std::size_t &off, msgpack::zone &result_zone, msgpack::object &result, bool &referenced, unpack_reference_func f=nullptr, void *user_data=nullptr, unpack_limit const &limit=unpack_limit())
Definition: unpack.hpp:1420
const char * ptr
Definition: object_fwd.hpp:34
Definition: cpp03_zone.hpp:22
bin_size_overflow(const char *msg)
Definition: unpack.hpp:109
void unpack_false(msgpack::object &o)
Definition: unpack.hpp:198
Definition: object_fwd_decl.hpp:33
object_type
Definition: object_fwd_decl.hpp:28
bool boolean
Definition: object_fwd.hpp:77
Definition: unpack_decl.hpp:440
void set_obj(msgpack::object const &obj)
Definition: unpack.hpp:293
str_size_overflow(const std::string &msg)
Definition: unpack.hpp:97
Definition: unpack_decl.hpp:438
unpacker(unpack_reference_func f=&unpacker::default_reference_func, void *user_data=nullptr, std::size_t initial_buffer_size=MSGPACK_UNPACKER_INIT_BUFFER_SIZE, unpack_limit const &limit=unpack_limit())
Constructor.
Definition: unpack.hpp:1130
std::size_t message_size() const
Get message size.
Definition: unpack.hpp:1387
depth_size_overflow(const char *msg)
Definition: unpack.hpp:127
Definition: object.hpp:29
Definition: cpp_config_decl.hpp:43
void remove_nonparsed_buffer()
Remove nonparsed buffer and reset the current position as a new start point.
Definition: unpack.hpp:1412
Definition: unpack.hpp:69
Definition: object_fwd_decl.hpp:29
ext_size_overflow(const char *msg)
Definition: unpack.hpp:118
uint32_t container_type() const
Definition: unpack.hpp:297
msgpack::object const & obj() const
Definition: unpack.hpp:291
int64_t i64
Definition: object_fwd.hpp:79
void operator()(unpack_user &u, uint32_t n, msgpack::object &o) const
Definition: unpack.hpp:202
Definition: object_fwd_decl.hpp:32
array_size_overflow(const std::string &msg)
Definition: unpack.hpp:79
void reserve_buffer(std::size_t size=MSGPACK_UNPACKER_RESERVE_SIZE)
Reserve a buffer memory.
Definition: unpack.hpp:1190
Definition: unpack.hpp:385
void unpack_float(float d, msgpack::object &o)
Definition: unpack.hpp:186
msgpack::object const & map_key() const
Definition: unpack.hpp:299
Definition: unpack.hpp:105
void init_count(void *buffer)
Definition: unpack.hpp:308
void unpack_double(double d, msgpack::object &o)
Definition: unpack.hpp:189
msgpack::object & obj()
Definition: unpack.hpp:292
void unpack_uint64(uint64_t d, msgpack::object &o)
Definition: unpack.hpp:167
uint32_t size
Definition: object_fwd.hpp:45
Definition: unpack.hpp:60
unpack_reference_func reference_func() const
Definition: unpack.hpp:145
void operator()(unpack_user &u, uint32_t n, msgpack::object &o) const
Definition: unpack.hpp:220
Definition: unpack.hpp:78
void reset_zone()
Definition: unpack.hpp:1359
array_size_overflow(const char *msg)
Definition: unpack.hpp:82
msgpack::zone * release_zone()
Definition: unpack.hpp:1345
void unpack_int64(int64_t d, msgpack::object &o)
Definition: unpack.hpp:182
void unpack_uint16(uint16_t d, msgpack::object &o)
Definition: unpack.hpp:161
void unpack_true(msgpack::object &o)
Definition: unpack.hpp:195
void set_map_key(msgpack::object const &map_key)
Definition: unpack.hpp:300
void buffer_consumed(std::size_t size)
Notify a buffer consumed information to msgpack::unpacker.
Definition: unpack.hpp:1278
double f64
Definition: object_fwd.hpp:83
Definition: object_fwd_decl.hpp:41
insufficient_bytes(const std::string &msg)
Definition: unpack.hpp:61
msgpack::object_array array
Definition: object_fwd.hpp:84
msgpack::enable_if< sizeof(T)==8 >::type load(T &dst, const char *n)
Definition: unpack.hpp:381
char * buffer()
Get buffer pointer.
Definition: unpack.hpp:1268
const size_t COUNTER_SIZE
Definition: unpack_decl.hpp:39
std::size_t bin() const
Definition: unpack_decl.hpp:104
void init()
Definition: unpack.hpp:394
Definition: cpp_config_decl.hpp:52
msgpack::object_map map
Definition: object_fwd.hpp:85
msgpack::object const & data() const
Definition: unpack.hpp:402
msgpack::object_str str
Definition: object_fwd.hpp:86
Object class that corresponding to MessagePack format object.
Definition: object_fwd.hpp:75
Definition: unpack.hpp:87
unpack_limit const & limit() const
Definition: unpack.hpp:147
parse_error(const char *msg)
Definition: unpack.hpp:55
unpack_user & user()
Definition: unpack.hpp:407
msgpack::type::object_type type
Definition: object_fwd.hpp:91
Definition: unpack.hpp:289
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:58
Definition: object_fwd_decl.hpp:39
void reset()
Definition: unpack.hpp:1380
unpacker & operator=(unpacker &&other)
Definition: unpack.hpp:1174
msgpack::object key
Definition: object.hpp:30
msgpack::object const & data()
Definition: unpack.hpp:1340
Definition: unpack_decl.hpp:441
uint32_t size
Definition: object_fwd.hpp:28
Definition: object_fwd_decl.hpp:40
std::size_t nonparsed_size() const
Get the size of the buffer that is not parsed.
Definition: unpack.hpp:1402
msgpack::unique_ptr< msgpack::zone > & zone()
Get unique_ptr reference of zone.
Definition: object.hpp:78
void set_count(std::size_t count)
Definition: unpack.hpp:295
msgpack::zone const & zone() const
Definition: unpack.hpp:140
uint32_t size
Definition: object_fwd.hpp:33
size_overflow(const std::string &msg)
Definition: unpack.hpp:70
void unpack_nil(msgpack::object &o)
Definition: unpack.hpp:192
std::size_t map() const
Definition: unpack_decl.hpp:102
msgpack::zone & zone()
Definition: unpack.hpp:141
void unpack_map_item(msgpack::object &c, msgpack::object const &k, msgpack::object const &v)
Definition: unpack.hpp:228
void decr_count(void *buffer)
Definition: unpack.hpp:317
Unpacking class for a stream deserialization.
Definition: unpack.hpp:929
Definition: unpack_decl.hpp:179
size_overflow(const char *msg)
Definition: unpack.hpp:73
void unpack_int32(int32_t d, msgpack::object &o)
Definition: unpack.hpp:178
unpack_limit & limit()
Definition: unpack.hpp:148
void unpack_array_item(msgpack::object &c, msgpack::object const &o)
Definition: unpack.hpp:210
T & move(T &t)
void set_zone(msgpack::zone &zone)
Definition: unpack.hpp:142
msgpack::object_ext ext
Definition: object_fwd.hpp:88
Definition: unpack.hpp:352
std::size_t decr_count()
Definition: unpack.hpp:296
bool referenced() const
Definition: unpack.hpp:143
void skip_nonparsed_buffer(std::size_t size)
Skip the specified size of non-parsed buffer.
Definition: unpack.hpp:1407
bool next(msgpack::object_handle *result)
Unpack one msgpack::object. [obsolete].
Definition: unpack.hpp:1312
unpack_user(unpack_reference_func f=nullptr, void *user_data=nullptr, unpack_limit const &limit=unpack_limit())
Definition: unpack.hpp:136
bin_size_overflow(const std::string &msg)
Definition: unpack.hpp:106
std::size_t str() const
Definition: unpack_decl.hpp:103
The class holds object and zone.
Definition: object.hpp:43
Definition: object_fwd_decl.hpp:31
str_size_overflow(const char *msg)
Definition: unpack.hpp:100
uint64_t u64
Definition: object_fwd.hpp:78
msgpack::object_bin bin
Definition: object_fwd.hpp:87
#define MSGPACK_UNPACKER_RESERVE_SIZE
Definition: unpack_decl.hpp:46