MessagePack for C++
unpack.hpp
Go to the documentation of this file.
1 //
2 // MessagePack for C++ deserializing routine
3 //
4 // Copyright (C) 2008-2015 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_UNPACK_HPP
11 #define MSGPACK_UNPACK_HPP
12 
13 #include "msgpack/versioning.hpp"
14 #include "object.hpp"
15 #include "zone.hpp"
16 #include "unpack_define.h"
17 #include "cpp_config.hpp"
18 #include "sysdep.h"
19 
20 #include <memory>
21 #include <stdexcept>
22 
23 #if !defined(MSGPACK_USE_CPP03)
24 #include <atomic>
25 #endif
26 
27 
28 #if defined(_MSC_VER)
29 // avoiding confliction std::max, std::min, and macro in windows.h
30 #ifndef NOMINMAX
31 #define NOMINMAX
32 #endif
33 #endif // defined(_MSC_VER)
34 
35 #ifdef _msgpack_atomic_counter_header
36 #include _msgpack_atomic_counter_header
37 #endif
38 
39 
40 const size_t COUNTER_SIZE = sizeof(_msgpack_atomic_counter_t);
41 
42 #ifndef MSGPACK_UNPACKER_INIT_BUFFER_SIZE
43 #define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (64*1024)
44 #endif
45 
46 #ifndef MSGPACK_UNPACKER_RESERVE_SIZE
47 #define MSGPACK_UNPACKER_RESERVE_SIZE (32*1024)
48 #endif
49 
50 
51 // backward compatibility
52 #ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
53 #define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE MSGPACK_UNPACKER_INIT_BUFFER_SIZE
54 #endif
55 
56 
57 namespace msgpack {
58 
62 
64 
74 typedef bool (*unpack_reference_func)(msgpack::type::object_type type, std::size_t size, void* user_data);
75 
76 struct unpack_error : public std::runtime_error {
77  explicit unpack_error(const std::string& msg)
78  :std::runtime_error(msg) {}
79 #if !defined(MSGPACK_USE_CPP03)
80  explicit unpack_error(const char* msg):
81  std::runtime_error(msg) {}
82 #endif // !defined(MSGPACK_USE_CPP03)
83 };
84 
85 struct parse_error : public unpack_error {
86  explicit parse_error(const std::string& msg)
87  :unpack_error(msg) {}
88 #if !defined(MSGPACK_USE_CPP03)
89  explicit parse_error(const char* msg)
90  :unpack_error(msg) {}
91 #endif // !defined(MSGPACK_USE_CPP03)
92 };
93 
95  explicit insufficient_bytes(const std::string& msg)
96  :unpack_error(msg) {}
97 #if !defined(MSGPACK_USE_CPP03)
98  explicit insufficient_bytes(const char* msg)
99  :unpack_error(msg) {}
100 #endif // !defined(MSGPACK_USE_CPP03)
101 };
102 
103 struct size_overflow : public unpack_error {
104  explicit size_overflow(const std::string& msg)
105  :unpack_error(msg) {}
106 #if !defined(MSGPACK_USE_CPP03)
107  explicit size_overflow(const char* msg)
108  :unpack_error(msg) {}
109 #endif
110 };
111 
113  array_size_overflow(const std::string& msg)
114  :size_overflow(msg) {}
115 #if !defined(MSGPACK_USE_CPP03)
116  array_size_overflow(const char* msg)
117  :size_overflow(msg) {}
118 #endif
119 };
120 
122  map_size_overflow(const std::string& msg)
123  :size_overflow(msg) {}
124 #if !defined(MSGPACK_USE_CPP03)
125  map_size_overflow(const char* msg)
126  :size_overflow(msg) {}
127 #endif
128 };
129 
131  str_size_overflow(const std::string& msg)
132  :size_overflow(msg) {}
133 #if !defined(MSGPACK_USE_CPP03)
134  str_size_overflow(const char* msg)
135  :size_overflow(msg) {}
136 #endif
137 };
138 
140  bin_size_overflow(const std::string& msg)
141  :size_overflow(msg) {}
142 #if !defined(MSGPACK_USE_CPP03)
143  bin_size_overflow(const char* msg)
144  :size_overflow(msg) {}
145 #endif
146 };
147 
149  ext_size_overflow(const std::string& msg)
150  :size_overflow(msg) {}
151 #if !defined(MSGPACK_USE_CPP03)
152  ext_size_overflow(const char* msg)
153  :size_overflow(msg) {}
154 #endif
155 };
156 
158  depth_size_overflow(const std::string& msg)
159  :size_overflow(msg) {}
160 #if !defined(MSGPACK_USE_CPP03)
161  depth_size_overflow(const char* msg)
162  :size_overflow(msg) {}
163 #endif
164 };
165 
167 public:
169  std::size_t array = 0xffffffff,
170  std::size_t map = 0xffffffff,
171  std::size_t str = 0xffffffff,
172  std::size_t bin = 0xffffffff,
173  std::size_t ext = 0xffffffff,
174  std::size_t depth = 0xffffffff)
175  :array_(array),
176  map_(map),
177  str_(str),
178  bin_(bin),
179  ext_(ext),
180  depth_(depth) {}
181  std::size_t array() const { return array_; }
182  std::size_t map() const { return map_; }
183  std::size_t str() const { return str_; }
184  std::size_t bin() const { return bin_; }
185  std::size_t ext() const { return ext_; }
186  std::size_t depth() const { return depth_; }
187 
188 private:
189  std::size_t array_;
190  std::size_t map_;
191  std::size_t str_;
192  std::size_t bin_;
193  std::size_t ext_;
194  std::size_t depth_;
195 };
196 
197 namespace detail {
198 
199 class unpack_user {
200 public:
202  void* user_data = nullptr,
203  unpack_limit const& limit = unpack_limit())
204  :m_func(f), m_user_data(user_data), m_limit(limit) {}
205  msgpack::zone const& zone() const { return *m_zone; }
206  msgpack::zone& zone() { return *m_zone; }
207  void set_zone(msgpack::zone& zone) { m_zone = &zone; }
208  bool referenced() const { return m_referenced; }
209  void set_referenced(bool referenced) { m_referenced = referenced; }
210  unpack_reference_func reference_func() const { return m_func; }
211  void* user_data() const { return m_user_data; }
212  unpack_limit const& limit() const { return m_limit; }
213  unpack_limit& limit() { return m_limit; }
214 
215 private:
216  msgpack::zone* m_zone;
217  bool m_referenced;
218  unpack_reference_func m_func;
219  void* m_user_data;
220  unpack_limit m_limit;
221 };
222 
223 inline void unpack_uint8(uint8_t d, msgpack::object& o)
225 
226 inline void unpack_uint16(uint16_t d, msgpack::object& o)
228 
229 inline void unpack_uint32(uint32_t d, msgpack::object& o)
231 
232 inline void unpack_uint64(uint64_t d, msgpack::object& o)
234 
235 inline void unpack_int8(int8_t d, msgpack::object& o)
236 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
237  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
238 
239 inline void unpack_int16(int16_t d, msgpack::object& o)
240 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
241  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
242 
243 inline void unpack_int32(int32_t d, msgpack::object& o)
244 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
245  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
246 
247 inline void unpack_int64(int64_t d, msgpack::object& o)
248 { if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
249  else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
250 
251 inline void unpack_float(float d, msgpack::object& o)
252 { o.type = msgpack::type::FLOAT; o.via.f64 = d; }
253 
254 inline void unpack_double(double d, msgpack::object& o)
255 { o.type = msgpack::type::FLOAT; o.via.f64 = d; }
256 
258 { o.type = msgpack::type::NIL; }
259 
261 { o.type = msgpack::type::BOOLEAN; o.via.boolean = true; }
262 
264 { o.type = msgpack::type::BOOLEAN; o.via.boolean = false; }
265 
266 struct unpack_array {
267  void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
268  if (n > u.limit().array()) throw msgpack::array_size_overflow("array size overflow");
270  o.via.array.size = 0;
271  o.via.array.ptr = static_cast<msgpack::object*>(u.zone().allocate_align(n*sizeof(msgpack::object)));
272  }
273 };
274 
276 {
277 #if defined(__GNUC__) && !defined(__clang__)
278  std::memcpy(&c.via.array.ptr[c.via.array.size++], &o, sizeof(msgpack::object));
279 #else /* __GNUC__ && !__clang__ */
280  c.via.array.ptr[c.via.array.size++] = o;
281 #endif /* __GNUC__ && !__clang__ */
282 }
283 
284 struct unpack_map {
285  void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
286  if (n > u.limit().map()) throw msgpack::map_size_overflow("map size overflow");
288  o.via.map.size = 0;
289  o.via.map.ptr = static_cast<msgpack::object_kv*>(u.zone().allocate_align(n*sizeof(msgpack::object_kv)));
290  }
291 };
292 
294 {
295 #if defined(__GNUC__) && !defined(__clang__)
296  std::memcpy(&c.via.map.ptr[c.via.map.size].key, &k, sizeof(msgpack::object));
297  std::memcpy(&c.via.map.ptr[c.via.map.size].val, &v, sizeof(msgpack::object));
298 #else /* __GNUC__ && !__clang__ */
299  c.via.map.ptr[c.via.map.size].key = k;
300  c.via.map.ptr[c.via.map.size].val = v;
301 #endif /* __GNUC__ && !__clang__ */
302  ++c.via.map.size;
303 }
304 
305 inline void unpack_str(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
306 {
308  if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
309  o.via.str.ptr = p;
310  u.set_referenced(true);
311  }
312  else {
313  if (l > u.limit().str()) throw msgpack::str_size_overflow("str size overflow");
314  char* tmp = static_cast<char*>(u.zone().allocate_align(l));
315  std::memcpy(tmp, p, l);
316  o.via.str.ptr = tmp;
317  }
318  o.via.str.size = l;
319 }
320 
321 inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
322 {
324  if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
325  o.via.bin.ptr = p;
326  u.set_referenced(true);
327  }
328  else {
329  if (l > u.limit().bin()) throw msgpack::bin_size_overflow("bin size overflow");
330  char* tmp = static_cast<char*>(u.zone().allocate_align(l));
331  std::memcpy(tmp, p, l);
332  o.via.bin.ptr = tmp;
333  }
334  o.via.bin.size = l;
335 }
336 
337 inline void unpack_ext(unpack_user& u, const char* p, std::size_t l, msgpack::object& o)
338 {
340  if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
341  o.via.ext.ptr = p;
342  u.set_referenced(true);
343  }
344  else {
345  if (l > u.limit().ext()) throw msgpack::ext_size_overflow("ext size overflow");
346  char* tmp = static_cast<char*>(u.zone().allocate_align(l));
347  std::memcpy(tmp, p, l);
348  o.via.ext.ptr = tmp;
349  }
350  o.via.ext.size = static_cast<uint32_t>(l - 1);
351 }
352 
353 
355 public:
356  msgpack::object const& obj() const { return m_obj; }
357  msgpack::object& obj() { return m_obj; }
358  void set_obj(msgpack::object const& obj) { m_obj = obj; }
359  std::size_t count() const { return m_count; }
360  void set_count(std::size_t count) { m_count = count; }
361  std::size_t decr_count() { return --m_count; }
362  uint32_t container_type() const { return m_container_type; }
363  void set_container_type(uint32_t container_type) { m_container_type = container_type; }
364  msgpack::object const& map_key() const { return m_map_key; }
365  void set_map_key(msgpack::object const& map_key) { m_map_key = map_key; }
366 private:
367  msgpack::object m_obj;
368  std::size_t m_count;
369  uint32_t m_container_type;
370  msgpack::object m_map_key;
371 };
372 
373 inline void init_count(void* buffer)
374 {
375 #if defined(MSGPACK_USE_CPP03)
376  *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer) = 1;
377 #else // defined(MSGPACK_USE_CPP03)
378  new (buffer) std::atomic<unsigned int>(1);
379 #endif // defined(MSGPACK_USE_CPP03)
380 }
381 
382 inline void decr_count(void* buffer)
383 {
384 #if defined(MSGPACK_USE_CPP03)
385  if(_msgpack_sync_decr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer)) == 0) {
386  free(buffer);
387  }
388 #else // defined(MSGPACK_USE_CPP03)
389  if (--*reinterpret_cast<std::atomic<unsigned int>*>(buffer) == 0) {
390  free(buffer);
391  }
392 #endif // defined(MSGPACK_USE_CPP03)
393 }
394 
395 inline void incr_count(void* buffer)
396 {
397 #if defined(MSGPACK_USE_CPP03)
398  _msgpack_sync_incr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer));
399 #else // defined(MSGPACK_USE_CPP03)
400  ++*reinterpret_cast<std::atomic<unsigned int>*>(buffer);
401 #endif // defined(MSGPACK_USE_CPP03)
402 }
403 
404 #if defined(MSGPACK_USE_CPP03)
405 inline _msgpack_atomic_counter_t get_count(void* buffer)
406 {
407  return *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer);
408 }
409 #else // defined(MSGPACK_USE_CPP03)
410 inline std::atomic<unsigned int> const& get_count(void* buffer)
411 {
412  return *reinterpret_cast<std::atomic<unsigned int>*>(buffer);
413 }
414 #endif // defined(MSGPACK_USE_CPP03)
415 
416 struct fix_tag {
417  char f1[65]; // FIXME unique size is required. or use is_same meta function.
418 };
419 
420 template <typename T>
421 struct value {
422  typedef T type;
423 };
424 template <>
425 struct value<fix_tag> {
426  typedef uint32_t type;
427 };
428 
429 template <typename T>
430 inline void load(uint32_t& dst, const char* n, typename msgpack::enable_if<sizeof(T) == sizeof(fix_tag)>::type* = nullptr) {
431  dst = static_cast<uint32_t>(*reinterpret_cast<const uint8_t*>(n)) & 0x0f;
432 }
433 
434 template <typename T>
435 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 1>::type* = nullptr) {
436  dst = static_cast<T>(*reinterpret_cast<const uint8_t*>(n));
437 }
438 
439 template <typename T>
440 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 2>::type* = nullptr) {
441  _msgpack_load16(T, n, &dst);
442 }
443 
444 template <typename T>
445 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 4>::type* = nullptr) {
446  _msgpack_load32(T, n, &dst);
447 }
448 
449 template <typename T>
450 inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) == 8>::type* = nullptr) {
451  _msgpack_load64(T, n, &dst);
452 }
453 
454 class context {
455 public:
456  context(unpack_reference_func f, void* user_data, unpack_limit const& limit)
457  :m_trail(0), m_user(f, user_data, limit), m_cs(MSGPACK_CS_HEADER)
458  {
459  m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
460  m_stack.push_back(unpack_stack());
461  }
462 
463  void init()
464  {
465  m_cs = MSGPACK_CS_HEADER;
466  m_trail = 0;
467  m_stack.resize(1);
468  m_stack[0].set_obj(msgpack::object());
469  }
470 
471  msgpack::object const& data() const
472  {
473  return m_stack[0].obj();
474  }
475 
477  {
478  return m_user;
479  }
480 
481  unpack_user const& user() const
482  {
483  return m_user;
484  }
485 
486  int execute(const char* data, std::size_t len, std::size_t& off);
487 
488 private:
489  template <typename T>
490  static uint32_t next_cs(T p)
491  {
492  return static_cast<uint32_t>(*p) & 0x1f;
493  }
494 
495  template <typename T, typename Func>
496  int push_aggregate(
497  Func const& f,
498  uint32_t container_type,
499  msgpack::object& obj,
500  const char* load_pos,
501  std::size_t& off) {
502  typename value<T>::type tmp;
503  load<T>(tmp, load_pos);
504  f(m_user, tmp, m_stack.back().obj());
505  if(tmp == 0) {
506  obj = m_stack.back().obj();
507  int ret = push_proc(obj, off);
508  if (ret != 0) return ret;
509  }
510  else {
511  m_stack.back().set_container_type(container_type);
512  m_stack.back().set_count(tmp);
513  if (m_stack.size() <= m_user.limit().depth()) {
514  m_stack.push_back(unpack_stack());
515  }
516  else {
517  throw msgpack::depth_size_overflow("depth size overflow");
518  }
519  m_cs = MSGPACK_CS_HEADER;
520  ++m_current;
521  }
522  return 0;
523  }
524 
525  int push_item(msgpack::object& obj) {
526  bool finish = false;
527  while (!finish) {
528  if(m_stack.size() == 1) {
529  return 1;
530  }
531  unpack_stack& sp = *(m_stack.end() - 2);
532  switch(sp.container_type()) {
533  case MSGPACK_CT_ARRAY_ITEM:
534  unpack_array_item(sp.obj(), obj);
535  if(sp.decr_count() == 0) {
536  obj = sp.obj();
537  m_stack.pop_back();
538  }
539  else {
540  finish = true;
541  }
542  break;
543  case MSGPACK_CT_MAP_KEY:
544  sp.set_map_key(obj);
545  sp.set_container_type(MSGPACK_CT_MAP_VALUE);
546  finish = true;
547  break;
548  case MSGPACK_CT_MAP_VALUE:
549  unpack_map_item(sp.obj(), sp.map_key(), obj);
550  if(sp.decr_count() == 0) {
551  obj = sp.obj();
552  m_stack.pop_back();
553  }
554  else {
555  sp.set_container_type(MSGPACK_CT_MAP_KEY);
556  finish = true;
557  }
558  break;
559  default:
560  return -1;
561  }
562  }
563  return 0;
564  }
565 
566  int push_proc(msgpack::object& obj, std::size_t& off) {
567  int ret = push_item(obj);
568  if (ret > 0) {
569  m_stack[0].set_obj(obj);
570  ++m_current;
571  /*printf("-- finish --\n"); */
572  off = m_current - m_start;
573  }
574  else if (ret < 0) {
575  off = m_current - m_start;
576  }
577  else {
578  m_cs = MSGPACK_CS_HEADER;
579  ++m_current;
580  }
581  return ret;
582  }
583 
584  template <std::size_t N>
585  static void check_ext_size(std::size_t /*size*/) {
586  }
587 
588 private:
589  char const* m_start;
590  char const* m_current;
591 
592  std::size_t m_trail;
593  unpack_user m_user;
594  uint32_t m_cs;
595  std::vector<unpack_stack> m_stack;
596 };
597 
598 template <>
599 inline void context::check_ext_size<4>(std::size_t size) {
600  if (size == 0xffffffff) throw msgpack::ext_size_overflow("ext size overflow");
601 }
602 
603 inline int context::execute(const char* data, std::size_t len, std::size_t& off)
604 {
605  assert(len >= off);
606 
607  m_start = data;
608  m_current = data + off;
609  const char* const pe = data + len;
610  const char* n = nullptr;
611 
612  msgpack::object obj;
613 
614  if(m_current == pe) {
615  off = m_current - m_start;
616  return 0;
617  }
618  bool fixed_trail_again = false;
619  do {
620  if (m_cs == MSGPACK_CS_HEADER) {
621  fixed_trail_again = false;
622  int selector = *reinterpret_cast<const unsigned char*>(m_current);
623  if (0x00 <= selector && selector <= 0x7f) { // Positive Fixnum
624  unpack_uint8(*reinterpret_cast<const uint8_t*>(m_current), obj);
625  int ret = push_proc(obj, off);
626  if (ret != 0) return ret;
627  } else if(0xe0 <= selector && selector <= 0xff) { // Negative Fixnum
628  unpack_int8(*reinterpret_cast<const int8_t*>(m_current), obj);
629  int ret = push_proc(obj, off);
630  if (ret != 0) return ret;
631  } else if (0xc4 <= selector && selector <= 0xdf) {
632  const uint32_t trail[] = {
633  1, // bin 8 0xc4
634  2, // bin 16 0xc5
635  4, // bin 32 0xc6
636  1, // ext 8 0xc7
637  2, // ext 16 0xc8
638  4, // ext 32 0xc9
639  4, // float 32 0xca
640  8, // float 64 0xcb
641  1, // uint 8 0xcc
642  2, // uint 16 0xcd
643  4, // uint 32 0xce
644  8, // uint 64 0xcf
645  1, // int 8 0xd0
646  2, // int 16 0xd1
647  4, // int 32 0xd2
648  8, // int 64 0xd3
649  2, // fixext 1 0xd4
650  3, // fixext 2 0xd5
651  5, // fixext 4 0xd6
652  9, // fixext 8 0xd7
653  17,// fixext 16 0xd8
654  1, // str 8 0xd9
655  2, // str 16 0xda
656  4, // str 32 0xdb
657  2, // array 16 0xdc
658  4, // array 32 0xdd
659  2, // map 16 0xde
660  4, // map 32 0xdf
661  };
662  m_trail = trail[selector - 0xc4];
663  m_cs = next_cs(m_current);
664  fixed_trail_again = true;
665  } else if(0xa0 <= selector && selector <= 0xbf) { // FixStr
666  m_trail = static_cast<uint32_t>(*m_current) & 0x1f;
667  if(m_trail == 0) {
668  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
669  int ret = push_proc(obj, off);
670  if (ret != 0) return ret;
671  }
672  else {
673  m_cs = MSGPACK_ACS_STR_VALUE;
674  fixed_trail_again = true;
675  }
676 
677  } else if(0x90 <= selector && selector <= 0x9f) { // FixArray
678  int ret = push_aggregate<fix_tag>(
679  unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, m_current, off);
680  if (ret != 0) return ret;
681  } else if(0x80 <= selector && selector <= 0x8f) { // FixMap
682  int ret = push_aggregate<fix_tag>(
683  unpack_map(), MSGPACK_CT_MAP_KEY, obj, m_current, off);
684  if (ret != 0) return ret;
685  } else if(selector == 0xc2) { // false
686  unpack_false(obj);
687  int ret = push_proc(obj, off);
688  if (ret != 0) return ret;
689  } else if(selector == 0xc3) { // true
690  unpack_true(obj);
691  int ret = push_proc(obj, off);
692  if (ret != 0) return ret;
693  } else if(selector == 0xc0) { // nil
694  unpack_nil(obj);
695  int ret = push_proc(obj, off);
696  if (ret != 0) return ret;
697  } else {
698  off = m_current - m_start;
699  return -1;
700  }
701  // end MSGPACK_CS_HEADER
702  }
703  if (m_cs != MSGPACK_CS_HEADER || fixed_trail_again) {
704  if (fixed_trail_again) {
705  ++m_current;
706  fixed_trail_again = false;
707  }
708  if(static_cast<std::size_t>(pe - m_current) < m_trail) {
709  off = m_current - m_start;
710  return 0;
711  }
712  n = m_current;
713  m_current += m_trail - 1;
714  switch(m_cs) {
715  //case MSGPACK_CS_
716  //case MSGPACK_CS_
717  case MSGPACK_CS_FLOAT: {
718  union { uint32_t i; float f; } mem;
719  load<uint32_t>(mem.i, n);
720  unpack_float(mem.f, obj);
721  int ret = push_proc(obj, off);
722  if (ret != 0) return ret;
723  } break;
724  case MSGPACK_CS_DOUBLE: {
725  union { uint64_t i; double f; } mem;
726  load<uint64_t>(mem.i, n);
727 #if defined(TARGET_OS_IPHONE)
728  // ok
729 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
730  // https://github.com/msgpack/msgpack-perl/pull/1
731  mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
732 #endif
733  unpack_double(mem.f, obj);
734  int ret = push_proc(obj, off);
735  if (ret != 0) return ret;
736  } break;
737  case MSGPACK_CS_UINT_8: {
738  uint8_t tmp;
739  load<uint8_t>(tmp, n);
740  unpack_uint8(tmp, obj);
741  int ret = push_proc(obj, off);
742  if (ret != 0) return ret;
743  } break;
744  case MSGPACK_CS_UINT_16: {
745  uint16_t tmp;
746  load<uint16_t>(tmp, n);
747  unpack_uint16(tmp, obj);
748  int ret = push_proc(obj, off);
749  if (ret != 0) return ret;
750  } break;
751  case MSGPACK_CS_UINT_32: {
752  uint32_t tmp;
753  load<uint32_t>(tmp, n);
754  unpack_uint32(tmp, obj);
755  int ret = push_proc(obj, off);
756  if (ret != 0) return ret;
757  } break;
758  case MSGPACK_CS_UINT_64: {
759  uint64_t tmp;
760  load<uint64_t>(tmp, n);
761  unpack_uint64(tmp, obj);
762  int ret = push_proc(obj, off);
763  if (ret != 0) return ret;
764  } break;
765  case MSGPACK_CS_INT_8: {
766  int8_t tmp;
767  load<int8_t>(tmp, n);
768  unpack_int8(tmp, obj);
769  int ret = push_proc(obj, off);
770  if (ret != 0) return ret;
771  } break;
772  case MSGPACK_CS_INT_16: {
773  int16_t tmp;
774  load<int16_t>(tmp, n);
775  unpack_int16(tmp, obj);
776  int ret = push_proc(obj, off);
777  if (ret != 0) return ret;
778  } break;
779  case MSGPACK_CS_INT_32: {
780  int32_t tmp;
781  load<int32_t>(tmp, n);
782  unpack_int32(tmp, obj);
783  int ret = push_proc(obj, off);
784  if (ret != 0) return ret;
785  } break;
786  case MSGPACK_CS_INT_64: {
787  int64_t tmp;
788  load<int64_t>(tmp, n);
789  unpack_int64(tmp, obj);
790  int ret = push_proc(obj, off);
791  if (ret != 0) return ret;
792  } break;
793  case MSGPACK_CS_FIXEXT_1: {
794  unpack_ext(m_user, n, 1+1, obj);
795  int ret = push_proc(obj, off);
796  if (ret != 0) return ret;
797  } break;
798  case MSGPACK_CS_FIXEXT_2: {
799  unpack_ext(m_user, n, 2+1, obj);
800  int ret = push_proc(obj, off);
801  if (ret != 0) return ret;
802  } break;
803  case MSGPACK_CS_FIXEXT_4: {
804  unpack_ext(m_user, n, 4+1, obj);
805  int ret = push_proc(obj, off);
806  if (ret != 0) return ret;
807  } break;
808  case MSGPACK_CS_FIXEXT_8: {
809  unpack_ext(m_user, n, 8+1, obj);
810  int ret = push_proc(obj, off);
811  if (ret != 0) return ret;
812  } break;
813  case MSGPACK_CS_FIXEXT_16: {
814  unpack_ext(m_user, n, 16+1, obj);
815  int ret = push_proc(obj, off);
816  if (ret != 0) return ret;
817  } break;
818  case MSGPACK_CS_STR_8: {
819  uint8_t tmp;
820  load<uint8_t>(tmp, n);
821  m_trail = tmp;
822  if(m_trail == 0) {
823  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
824  int ret = push_proc(obj, off);
825  if (ret != 0) return ret;
826  }
827  else {
828  m_cs = MSGPACK_ACS_STR_VALUE;
829  fixed_trail_again = true;
830  }
831  } break;
832  case MSGPACK_CS_BIN_8: {
833  uint8_t tmp;
834  load<uint8_t>(tmp, n);
835  m_trail = tmp;
836  if(m_trail == 0) {
837  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
838  int ret = push_proc(obj, off);
839  if (ret != 0) return ret;
840  }
841  else {
842  m_cs = MSGPACK_ACS_BIN_VALUE;
843  fixed_trail_again = true;
844  }
845  } break;
846  case MSGPACK_CS_EXT_8: {
847  uint8_t tmp;
848  load<uint8_t>(tmp, n);
849  m_trail = tmp + 1;
850  if(m_trail == 0) {
851  unpack_ext(m_user, n, m_trail, obj);
852  int ret = push_proc(obj, off);
853  if (ret != 0) return ret;
854  }
855  else {
856  m_cs = MSGPACK_ACS_EXT_VALUE;
857  fixed_trail_again = true;
858  }
859  } break;
860  case MSGPACK_CS_STR_16: {
861  uint16_t tmp;
862  load<uint16_t>(tmp, n);
863  m_trail = tmp;
864  if(m_trail == 0) {
865  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
866  int ret = push_proc(obj, off);
867  if (ret != 0) return ret;
868  }
869  else {
870  m_cs = MSGPACK_ACS_STR_VALUE;
871  fixed_trail_again = true;
872  }
873  } break;
874  case MSGPACK_CS_BIN_16: {
875  uint16_t tmp;
876  load<uint16_t>(tmp, n);
877  m_trail = tmp;
878  if(m_trail == 0) {
879  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
880  int ret = push_proc(obj, off);
881  if (ret != 0) return ret;
882  }
883  else {
884  m_cs = MSGPACK_ACS_BIN_VALUE;
885  fixed_trail_again = true;
886  }
887  } break;
888  case MSGPACK_CS_EXT_16: {
889  uint16_t tmp;
890  load<uint16_t>(tmp, n);
891  m_trail = tmp + 1;
892  if(m_trail == 0) {
893  unpack_ext(m_user, n, m_trail, obj);
894  int ret = push_proc(obj, off);
895  if (ret != 0) return ret;
896  }
897  else {
898  m_cs = MSGPACK_ACS_EXT_VALUE;
899  fixed_trail_again = true;
900  }
901  } break;
902  case MSGPACK_CS_STR_32: {
903  uint32_t tmp;
904  load<uint32_t>(tmp, n);
905  m_trail = tmp;
906  if(m_trail == 0) {
907  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
908  int ret = push_proc(obj, off);
909  if (ret != 0) return ret;
910  }
911  else {
912  m_cs = MSGPACK_ACS_STR_VALUE;
913  fixed_trail_again = true;
914  }
915  } break;
916  case MSGPACK_CS_BIN_32: {
917  uint32_t tmp;
918  load<uint32_t>(tmp, n);
919  m_trail = tmp;
920  if(m_trail == 0) {
921  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
922  int ret = push_proc(obj, off);
923  if (ret != 0) return ret;
924  }
925  else {
926  m_cs = MSGPACK_ACS_BIN_VALUE;
927  fixed_trail_again = true;
928  }
929  } break;
930  case MSGPACK_CS_EXT_32: {
931  uint32_t tmp;
932  load<uint32_t>(tmp, n);
933  check_ext_size<sizeof(std::size_t)>(tmp);
934  m_trail = tmp;
935  ++m_trail;
936  if(m_trail == 0) {
937  unpack_ext(m_user, n, m_trail, obj);
938  int ret = push_proc(obj, off);
939  if (ret != 0) return ret;
940  }
941  else {
942  m_cs = MSGPACK_ACS_EXT_VALUE;
943  fixed_trail_again = true;
944  }
945  } break;
946  case MSGPACK_ACS_STR_VALUE: {
947  unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
948  int ret = push_proc(obj, off);
949  if (ret != 0) return ret;
950  } break;
951  case MSGPACK_ACS_BIN_VALUE: {
952  unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
953  int ret = push_proc(obj, off);
954  if (ret != 0) return ret;
955  } break;
956  case MSGPACK_ACS_EXT_VALUE: {
957  unpack_ext(m_user, n, m_trail, obj);
958  int ret = push_proc(obj, off);
959  if (ret != 0) return ret;
960  } break;
961  case MSGPACK_CS_ARRAY_16: {
962  int ret = push_aggregate<uint16_t>(
963  unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
964  if (ret != 0) return ret;
965  } break;
966  case MSGPACK_CS_ARRAY_32: {
967  /* FIXME security guard */
968  int ret = push_aggregate<uint32_t>(
969  unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
970  if (ret != 0) return ret;
971  } break;
972  case MSGPACK_CS_MAP_16: {
973  int ret = push_aggregate<uint16_t>(
974  unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
975  if (ret != 0) return ret;
976  } break;
977  case MSGPACK_CS_MAP_32: {
978  /* FIXME security guard */
979  int ret = push_aggregate<uint32_t>(
980  unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
981  if (ret != 0) return ret;
982  } break;
983  default:
984  off = m_current - m_start;
985  return -1;
986  }
987  }
988  } while(m_current != pe);
989 
990  off = m_current - m_start;
991  return 0;
992 }
993 
994 } // detail
995 
996 
998 
1000 class unpacker {
1001 public:
1003 
1011  unpacker(unpack_reference_func f = &unpacker::default_reference_func,
1012  void* user_data = nullptr,
1013  std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE,
1014  unpack_limit const& limit = unpack_limit());
1015 
1016 #if !defined(MSGPACK_USE_CPP03)
1017  unpacker(unpacker&& other);
1018  unpacker& operator=(unpacker&& other);
1019 #endif // !defined(MSGPACK_USE_CPP03)
1020 
1021  ~unpacker();
1022 
1023 public:
1025 
1032  void reserve_buffer(std::size_t size = MSGPACK_UNPACKER_RESERVE_SIZE);
1033 
1035 
1040  char* buffer();
1041 
1043 
1049  std::size_t buffer_capacity() const;
1050 
1052 
1061  void buffer_consumed(std::size_t size);
1062 
1064 
1077  bool next(unpacked* result);
1078 
1080 
1093  bool next(unpacked& result, bool& referenced);
1094 
1096 
1107  bool next(unpacked& result);
1108 
1110 
1113  std::size_t message_size() const;
1114 
1116  bool execute();
1117 
1119  msgpack::object const& data();
1120 
1122  msgpack::zone* release_zone();
1123 
1125  void reset_zone();
1126 
1128  void reset();
1129 
1130 public:
1132 
1138  std::size_t parsed_size() const;
1139 
1141 
1147  char* nonparsed_buffer();
1148 
1150 
1156  std::size_t nonparsed_size() const;
1157 
1159 
1166  void skip_nonparsed_buffer(std::size_t size);
1167 
1169 
1173  void remove_nonparsed_buffer();
1174 
1175 private:
1176  void expand_buffer(std::size_t size);
1177  int execute_imp();
1178  bool flush_zone();
1179  static bool default_reference_func(msgpack::type::object_type type, std::size_t len, void*);
1180 
1181 private:
1182  char* m_buffer;
1183  std::size_t m_used;
1184  std::size_t m_free;
1185  std::size_t m_off;
1186  std::size_t m_parsed;
1188  std::size_t m_initial_buffer_size;
1189  detail::context m_ctx;
1190 
1191 #if defined(MSGPACK_USE_CPP03)
1192 private:
1193  unpacker(const unpacker&);
1194  unpacker& operator=(const unpacker&);
1195 #else // defined(MSGPACK_USE_CPP03)
1196  unpacker(const unpacker&) = delete;
1197  unpacker& operator=(const unpacker&) = delete;
1198 #endif // defined(MSGPACK_USE_CPP03)
1199 };
1200 
1202 
1214 unpacked unpack(
1215  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1216  unpack_reference_func f = nullptr, void* user_data = nullptr,
1217  unpack_limit const& limit = unpack_limit());
1218 
1220 
1231 unpacked unpack(
1232  const char* data, std::size_t len, std::size_t& off,
1233  unpack_reference_func f = nullptr, void* user_data = nullptr,
1234  unpack_limit const& limit = unpack_limit());
1235 
1237 
1248 unpacked unpack(
1249  const char* data, std::size_t len, bool& referenced,
1250  unpack_reference_func f = nullptr, void* user_data = nullptr,
1251  unpack_limit const& limit = unpack_limit());
1252 
1254 
1264 unpacked unpack(
1265  const char* data, std::size_t len,
1266  unpack_reference_func f = nullptr, void* user_data = nullptr,
1267  unpack_limit const& limit = unpack_limit());
1268 
1269 
1271 
1283 void unpack(unpacked& result,
1284  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1285  unpack_reference_func f = nullptr, void* user_data = nullptr,
1286  unpack_limit const& limit = unpack_limit());
1287 
1289 
1300 void unpack(unpacked& result,
1301  const char* data, std::size_t len, std::size_t& off,
1302  unpack_reference_func f = nullptr, void* user_data = nullptr,
1303  unpack_limit const& limit = unpack_limit());
1304 
1306 
1317 void unpack(unpacked& result,
1318  const char* data, std::size_t len, bool& referenced,
1319  unpack_reference_func f = nullptr, void* user_data = nullptr,
1320  unpack_limit const& limit = unpack_limit());
1321 
1323 
1333 void unpack(unpacked& result,
1334  const char* data, std::size_t len,
1335  unpack_reference_func f = nullptr, void* user_data = nullptr,
1336  unpack_limit const& limit = unpack_limit());
1337 
1339 
1353  msgpack::zone& z,
1354  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1355  unpack_reference_func f = nullptr, void* user_data = nullptr,
1356  unpack_limit const& limit = unpack_limit());
1357 
1359 
1372  msgpack::zone& z,
1373  const char* data, std::size_t len, std::size_t& off,
1374  unpack_reference_func f = nullptr, void* user_data = nullptr,
1375  unpack_limit const& limit = unpack_limit());
1376 
1378 
1391  msgpack::zone& z,
1392  const char* data, std::size_t len, bool& referenced,
1393  unpack_reference_func f = nullptr, void* user_data = nullptr,
1394  unpack_limit const& limit = unpack_limit());
1395 
1397 
1409  msgpack::zone& z,
1410  const char* data, std::size_t len,
1411  unpack_reference_func f = nullptr, void* user_data = nullptr,
1412  unpack_limit const& limit = unpack_limit());
1413 
1414 
1416 
1428 void unpack(unpacked* result,
1429  const char* data, std::size_t len, std::size_t* off = nullptr, bool* referenced = nullptr,
1430  unpack_reference_func f = nullptr, void* user_data = nullptr,
1431  unpack_limit const& limit = unpack_limit());
1432 
1433 
1434 // for internal use
1435 typedef enum {
1440 } unpack_return;
1441 
1443  void* user_data,
1444  std::size_t initial_buffer_size,
1445  unpack_limit const& limit)
1446  :m_z(new msgpack::zone), m_ctx(f, user_data, limit)
1447 {
1448  if(initial_buffer_size < COUNTER_SIZE) {
1449  initial_buffer_size = COUNTER_SIZE;
1450  }
1451 
1452  char* buffer = static_cast<char*>(::malloc(initial_buffer_size));
1453  if(!buffer) {
1454  throw std::bad_alloc();
1455  }
1456 
1457  m_buffer = buffer;
1458  m_used = COUNTER_SIZE;
1459  m_free = initial_buffer_size - m_used;
1460  m_off = COUNTER_SIZE;
1461  m_parsed = 0;
1462  m_initial_buffer_size = initial_buffer_size;
1463 
1464  detail::init_count(m_buffer);
1465 
1466  m_ctx.init();
1467  m_ctx.user().set_zone(*m_z);
1468  m_ctx.user().set_referenced(false);
1469 }
1470 
1471 #if !defined(MSGPACK_USE_CPP03)
1472 // Move constructor and move assignment operator
1473 
1474 inline unpacker::unpacker(unpacker&& other)
1475  :m_buffer(other.m_buffer),
1476  m_used(other.m_used),
1477  m_free(other.m_free),
1478  m_off(other.m_off),
1479  m_parsed(other.m_parsed),
1480  m_z(std::move(other.m_z)),
1481  m_initial_buffer_size(other.m_initial_buffer_size),
1482  m_ctx(other.m_ctx) {
1483  other.m_buffer = nullptr;
1484 }
1485 
1486 inline unpacker& unpacker::operator=(unpacker&& other) {
1487  this->~unpacker();
1488  new (this) unpacker(std::move(other));
1489  return *this;
1490 }
1491 
1492 #endif // !defined(MSGPACK_USE_CPP03)
1493 
1494 
1496 {
1497  // These checks are required for move operations.
1498  if (m_buffer) detail::decr_count(m_buffer);
1499 }
1500 
1501 
1502 inline void unpacker::reserve_buffer(std::size_t size)
1503 {
1504  if(m_free >= size) return;
1505  expand_buffer(size);
1506 }
1507 
1508 inline void unpacker::expand_buffer(std::size_t size)
1509 {
1510  if(m_used == m_off && detail::get_count(m_buffer) == 1
1511  && !m_ctx.user().referenced()) {
1512  // rewind buffer
1513  m_free += m_used - COUNTER_SIZE;
1514  m_used = COUNTER_SIZE;
1515  m_off = COUNTER_SIZE;
1516 
1517  if(m_free >= size) return;
1518  }
1519 
1520  if(m_off == COUNTER_SIZE) {
1521  std::size_t next_size = (m_used + m_free) * 2; // include COUNTER_SIZE
1522  while(next_size < size + m_used) {
1523  std::size_t tmp_next_size = next_size * 2;
1524  if (tmp_next_size <= next_size) {
1525  next_size = size + m_used;
1526  break;
1527  }
1528  next_size = tmp_next_size;
1529  }
1530 
1531  char* tmp = static_cast<char*>(::realloc(m_buffer, next_size));
1532  if(!tmp) {
1533  throw std::bad_alloc();
1534  }
1535 
1536  m_buffer = tmp;
1537  m_free = next_size - m_used;
1538 
1539  } else {
1540  std::size_t next_size = m_initial_buffer_size; // include COUNTER_SIZE
1541  std::size_t not_parsed = m_used - m_off;
1542  while(next_size < size + not_parsed + COUNTER_SIZE) {
1543  std::size_t tmp_next_size = next_size * 2;
1544  if (tmp_next_size <= next_size) {
1545  next_size = size + not_parsed + COUNTER_SIZE;
1546  break;
1547  }
1548  next_size = tmp_next_size;
1549  }
1550 
1551  char* tmp = static_cast<char*>(::malloc(next_size));
1552  if(!tmp) {
1553  throw std::bad_alloc();
1554  }
1555 
1556  detail::init_count(tmp);
1557 
1558  std::memcpy(tmp+COUNTER_SIZE, m_buffer + m_off, not_parsed);
1559 
1560  if(m_ctx.user().referenced()) {
1561  try {
1562  m_z->push_finalizer(&detail::decr_count, m_buffer);
1563  }
1564  catch (...) {
1565  ::free(tmp);
1566  throw;
1567  }
1568  m_ctx.user().set_referenced(false);
1569  } else {
1570  detail::decr_count(m_buffer);
1571  }
1572 
1573  m_buffer = tmp;
1574  m_used = not_parsed + COUNTER_SIZE;
1575  m_free = next_size - m_used;
1576  m_off = COUNTER_SIZE;
1577  }
1578 }
1579 
1580 inline char* unpacker::buffer()
1581 {
1582  return m_buffer + m_used;
1583 }
1584 
1585 inline std::size_t unpacker::buffer_capacity() const
1586 {
1587  return m_free;
1588 }
1589 
1590 inline void unpacker::buffer_consumed(std::size_t size)
1591 {
1592  m_used += size;
1593  m_free -= size;
1594 }
1595 
1596 inline bool unpacker::next(unpacked& result, bool& referenced)
1597 {
1598  referenced = false;
1599  int ret = execute_imp();
1600  if(ret < 0) {
1601  throw msgpack::parse_error("parse error");
1602  }
1603 
1604  if(ret == 0) {
1605  result.zone().reset();
1606  result.set(object());
1607  return false;
1608 
1609  } else {
1610  referenced = m_ctx.user().referenced();
1611  result.zone().reset( release_zone() );
1612  result.set(data());
1613  reset();
1614  return true;
1615  }
1616 }
1617 
1618 inline bool unpacker::next(unpacked& result)
1619 {
1620  bool referenced;
1621  return next(result, referenced);
1622 }
1623 
1624 inline bool unpacker::next(unpacked* result)
1625 {
1626  return next(*result);
1627 }
1628 
1629 
1630 inline bool unpacker::execute()
1631 {
1632  int ret = execute_imp();
1633  if(ret < 0) {
1634  throw msgpack::parse_error("parse error");
1635  } else if(ret == 0) {
1636  return false;
1637  } else {
1638  return true;
1639  }
1640 }
1641 
1642 inline int unpacker::execute_imp()
1643 {
1644  std::size_t off = m_off;
1645  int ret = m_ctx.execute(m_buffer, m_used, m_off);
1646  if(m_off > off) {
1647  m_parsed += m_off - off;
1648  }
1649  return ret;
1650 }
1651 
1653 {
1654  return m_ctx.data();
1655 }
1656 
1658 {
1659  if(!flush_zone()) {
1660  return nullptr;
1661  }
1662 
1663  msgpack::zone* r = new msgpack::zone;
1664  msgpack::zone* old = m_z.release();
1665  m_z.reset(r);
1666  m_ctx.user().set_zone(*m_z);
1667 
1668  return old;
1669 }
1670 
1672 {
1673  m_z->clear();
1674 }
1675 
1676 inline bool unpacker::flush_zone()
1677 {
1678  if(m_ctx.user().referenced()) {
1679  try {
1680  m_z->push_finalizer(&detail::decr_count, m_buffer);
1681  } catch (...) {
1682  return false;
1683  }
1684  m_ctx.user().set_referenced(false);
1685 
1686  detail::incr_count(m_buffer);
1687  }
1688 
1689  return true;
1690 }
1691 
1692 inline void unpacker::reset()
1693 {
1694  m_ctx.init();
1695  // don't reset referenced flag
1696  m_parsed = 0;
1697 }
1698 
1699 inline std::size_t unpacker::message_size() const
1700 {
1701  return m_parsed - m_off + m_used;
1702 }
1703 
1704 inline std::size_t unpacker::parsed_size() const
1705 {
1706  return m_parsed;
1707 }
1708 
1710 {
1711  return m_buffer + m_off;
1712 }
1713 
1714 inline std::size_t unpacker::nonparsed_size() const
1715 {
1716  return m_used - m_off;
1717 }
1718 
1719 inline void unpacker::skip_nonparsed_buffer(std::size_t size)
1720 {
1721  m_off += size;
1722 }
1723 
1725 {
1726  m_used = m_off;
1727 }
1728 
1729 namespace detail {
1730 
1731 inline unpack_return
1732 unpack_imp(const char* data, std::size_t len, std::size_t& off,
1733  msgpack::zone& result_zone, msgpack::object& result, bool& referenced,
1734  unpack_reference_func f = nullptr, void* user_data = nullptr,
1735  unpack_limit const& limit = unpack_limit())
1736 {
1737  std::size_t noff = off;
1738 
1739  if(len <= noff) {
1740  // FIXME
1741  return UNPACK_CONTINUE;
1742  }
1743 
1744  detail::context ctx(f, user_data, limit);
1745  ctx.init();
1746 
1747  ctx.user().set_zone(result_zone);
1748  ctx.user().set_referenced(false);
1749  referenced = false;
1750 
1751  int e = ctx.execute(data, len, noff);
1752  if(e < 0) {
1753  return UNPACK_PARSE_ERROR;
1754  }
1755 
1756  referenced = ctx.user().referenced();
1757  off = noff;
1758 
1759  if(e == 0) {
1760  return UNPACK_CONTINUE;
1761  }
1762 
1763  result = ctx.data();
1764 
1765  if(noff < len) {
1766  return UNPACK_EXTRA_BYTES;
1767  }
1768 
1769  return UNPACK_SUCCESS;
1770 }
1771 
1772 } // detail
1773 
1774 // reference version
1775 
1776 inline unpacked unpack(
1777  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1778  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1779 {
1780  msgpack::object obj;
1782  referenced = false;
1783  std::size_t noff = off;
1785  data, len, noff, *z, obj, referenced, f, user_data, limit);
1786 
1787  switch(ret) {
1788  case UNPACK_SUCCESS:
1789  off = noff;
1790  return unpacked(obj, msgpack::move(z));
1791  case UNPACK_EXTRA_BYTES:
1792  off = noff;
1793  return unpacked(obj, msgpack::move(z));
1794  case UNPACK_CONTINUE:
1795  throw msgpack::insufficient_bytes("insufficient bytes");
1796  case UNPACK_PARSE_ERROR:
1797  default:
1798  throw msgpack::parse_error("parse error");
1799  }
1800  return unpacked();
1801 }
1802 
1803 inline unpacked unpack(
1804  const char* data, std::size_t len, std::size_t& off,
1805  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1806 {
1807  bool referenced;
1808  return unpack(data, len, off, referenced, f, user_data, limit);
1809 }
1810 
1811 inline unpacked unpack(
1812  const char* data, std::size_t len, bool& referenced,
1813  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1814 {
1815  std::size_t off = 0;
1816  return unpack(data, len, off, referenced, f, user_data, limit);
1817 }
1818 
1819 inline unpacked unpack(
1820  const char* data, std::size_t len,
1821  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1822 {
1823  bool referenced;
1824  std::size_t off = 0;
1825  return unpack(data, len, off, referenced, f, user_data, limit);
1826 }
1827 
1828 inline void unpack(unpacked& result,
1829  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1830  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1831 {
1832  msgpack::object obj;
1834  referenced = false;
1835  std::size_t noff = off;
1837  data, len, noff, *z, obj, referenced, f, user_data, limit);
1838 
1839  switch(ret) {
1840  case UNPACK_SUCCESS:
1841  off = noff;
1842  result.set(obj);
1843  result.zone() = msgpack::move(z);
1844  return;
1845  case UNPACK_EXTRA_BYTES:
1846  off = noff;
1847  result.set(obj);
1848  result.zone() = msgpack::move(z);
1849  return;
1850  case UNPACK_CONTINUE:
1851  throw msgpack::insufficient_bytes("insufficient bytes");
1852  case UNPACK_PARSE_ERROR:
1853  default:
1854  throw msgpack::parse_error("parse error");
1855  }
1856 }
1857 
1858 inline void unpack(unpacked& result,
1859  const char* data, std::size_t len, std::size_t& off,
1860  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1861 {
1862  bool referenced;
1863  unpack(result, data, len, off, referenced, f, user_data, limit);
1864 }
1865 
1866 inline void unpack(unpacked& result,
1867  const char* data, std::size_t len, bool& referenced,
1868  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1869 {
1870  std::size_t off = 0;
1871  unpack(result, data, len, off, referenced, f, user_data, limit);
1872 }
1873 
1874 inline void unpack(unpacked& result,
1875  const char* data, std::size_t len,
1876  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1877 {
1878  bool referenced;
1879  std::size_t off = 0;
1880  unpack(result, data, len, off, referenced, f, user_data, limit);
1881 }
1882 
1883 
1885  msgpack::zone& z,
1886  const char* data, std::size_t len, std::size_t& off, bool& referenced,
1887  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1888 {
1889  msgpack::object obj;
1890  std::size_t noff = off;
1891  referenced = false;
1893  data, len, noff, z, obj, referenced, f, user_data, limit);
1894 
1895  switch(ret) {
1896  case UNPACK_SUCCESS:
1897  off = noff;
1898  return obj;
1899  case UNPACK_EXTRA_BYTES:
1900  off = noff;
1901  return obj;
1902  case UNPACK_CONTINUE:
1903  throw msgpack::insufficient_bytes("insufficient bytes");
1904  case UNPACK_PARSE_ERROR:
1905  default:
1906  throw msgpack::parse_error("parse error");
1907  }
1908  return obj;
1909 }
1910 
1912  msgpack::zone& z,
1913  const char* data, std::size_t len, std::size_t& off,
1914  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1915 {
1916  bool referenced;
1917  return unpack(z, data, len, off, referenced, f, user_data, limit);
1918 }
1919 
1921  msgpack::zone& z,
1922  const char* data, std::size_t len, bool& referenced,
1923  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1924 {
1925  std::size_t off = 0;
1926  return unpack(z, data, len, off, referenced, f, user_data, limit);
1927 }
1928 
1930  msgpack::zone& z,
1931  const char* data, std::size_t len,
1932  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1933 {
1934  bool referenced;
1935  std::size_t off = 0;
1936  return unpack(z, data, len, off, referenced, f, user_data, limit);
1937 }
1938 
1939 // obsolete
1940 // pointer version
1941 inline void unpack(unpacked* result,
1942  const char* data, std::size_t len, std::size_t* off, bool* referenced,
1943  unpack_reference_func f, void* user_data, unpack_limit const& limit)
1944 {
1945  if (off)
1946  if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data, limit);
1947  else unpack(*result, data, len, *off, f, user_data, limit);
1948  else
1949  if (referenced) unpack(*result, data, len, *referenced, f, user_data, limit);
1950  else unpack(*result, data, len, f, user_data, limit);
1951 }
1952 
1953 inline bool unpacker::default_reference_func(msgpack::type::object_type /*type*/, std::size_t /*len*/, void*)
1954 {
1955  return true;
1956 }
1957 
1959 } // MSGPACK_API_VERSION_NAMESPACE(v1)
1961 
1962 } // namespace msgpack
1963 
1964 
1965 #endif /* msgpack/unpack.hpp */
uint32_t type
Definition: unpack.hpp:426
ext_size_overflow(const std::string &msg)
Definition: unpack.hpp:149
unpack_return
Definition: unpack.hpp:1435
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE
Definition: unpack.hpp:43
Definition: object_fwd.hpp:37
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:58
Definition: unpack.hpp:199
Definition: unpack.hpp:266
void operator()(unpack_user &u, uint32_t n, msgpack::object &o) const
Definition: unpack.hpp:267
char * nonparsed_buffer()
Get the address that is not parsed in the buffer.
Definition: unpack.hpp:1709
Definition: unpack.hpp:284
void unpack_int8(int8_t d, msgpack::object &o)
Definition: unpack.hpp:235
msgpack::object_kv * ptr
Definition: object_fwd.hpp:56
void incr_count(void *buffer)
Definition: unpack.hpp:395
Definition: unpack.hpp:166
Definition: unpack.hpp:130
context(unpack_reference_func f, void *user_data, unpack_limit const &limit)
Definition: unpack.hpp:456
uint32_t size
Definition: object_fwd.hpp:50
unpack_error(const std::string &msg)
Definition: unpack.hpp:77
std::size_t bin() const
Definition: unpack.hpp:184
void set_referenced(bool referenced)
Definition: unpack.hpp:209
const size_t COUNTER_SIZE
Definition: unpack.hpp:40
std::size_t ext() const
Definition: unpack.hpp:185
void * allocate_align(size_t size, size_t align=MSGPACK_ZONE_ALIGN)
Definition: cpp03_zone.hpp:248
~unpacker()
Definition: unpack.hpp:1495
void operator()(unpack_user &u, uint32_t n, msgpack::object &o) const
Definition: unpack.hpp:285
Definition: unpack.hpp:1437
Definition: object_fwd.hpp:30
const char * ptr
Definition: object_fwd.hpp:66
void unpack_ext(unpack_user &u, const char *p, std::size_t l, msgpack::object &o)
Definition: unpack.hpp:337
map_size_overflow(const std::string &msg)
Definition: unpack.hpp:122
void set_container_type(uint32_t container_type)
Definition: unpack.hpp:363
uint32_t container_type() const
Definition: unpack.hpp:362
void unpack_uint32(uint32_t d, msgpack::object &o)
Definition: unpack.hpp:229
std::size_t map() const
Definition: unpack.hpp:182
std::size_t nonparsed_size() const
Get the size of the buffer that is not parsed.
Definition: unpack.hpp:1714
void set(msgpack::object const &obj)
Definition: object.hpp:47
depth_size_overflow(const std::string &msg)
Definition: unpack.hpp:158
union_type via
Definition: object_fwd.hpp:123
std::size_t count() const
Definition: unpack.hpp:359
void unpack_str(unpack_user &u, const char *p, uint32_t l, msgpack::object &o)
Definition: unpack.hpp:305
bool execute()
Definition: unpack.hpp:1630
Definition: unpack.hpp:76
void load(T &dst, const char *n, typename msgpack::enable_if< sizeof(T)==8 >::type *=nullptr)
Definition: unpack.hpp:450
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.hpp:74
Definition: object_fwd.hpp:38
Definition: unpack.hpp:157
object_handle unpacked
Definition: unpack.hpp:997
void unpack_int16(int16_t d, msgpack::object &o)
Definition: unpack.hpp:239
void unpack_bin(unpack_user &u, const char *p, uint32_t l, msgpack::object &o)
Definition: unpack.hpp:321
const char * ptr
Definition: object_fwd.hpp:73
msgpack::object * ptr
Definition: object_fwd.hpp:51
parse_error(const std::string &msg)
Definition: unpack.hpp:86
void unpack_uint8(uint8_t d, msgpack::object &o)
Definition: unpack.hpp:223
msgpack::zone const & zone() const
Definition: unpack.hpp:205
int execute(const char *data, std::size_t len, std::size_t &off)
Definition: unpack.hpp:603
msgpack::object val
Definition: object_fwd.hpp:257
uint32_t size
Definition: object_fwd.hpp:65
T type
Definition: unpack.hpp:422
Definition: adaptor_base.hpp:15
Definition: unpack.hpp:85
Definition: unpack.hpp:148
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:1732
const char * ptr
Definition: object_fwd.hpp:61
std::size_t parsed_size() const
Get parsed message size.
Definition: unpack.hpp:1704
Definition: cpp03_zone.hpp:34
void unpack_false(msgpack::object &o)
Definition: unpack.hpp:263
Definition: object_fwd.hpp:33
object_type
Definition: object_fwd.hpp:28
unpack_limit(std::size_t array=0xffffffff, std::size_t map=0xffffffff, std::size_t str=0xffffffff, std::size_t bin=0xffffffff, std::size_t ext=0xffffffff, std::size_t depth=0xffffffff)
Definition: unpack.hpp:168
bool boolean
Definition: object_fwd.hpp:108
Definition: unpack.hpp:1438
void set_obj(msgpack::object const &obj)
Definition: unpack.hpp:358
str_size_overflow(const std::string &msg)
Definition: unpack.hpp:131
Definition: unpack.hpp:1436
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:1442
Definition: object_fwd.hpp:255
Definition: cpp_config.hpp:44
void remove_nonparsed_buffer()
Remove nonparsed buffer and reset the current position as a new start point.
Definition: unpack.hpp:1724
Definition: unpack.hpp:103
Definition: object_fwd.hpp:29
int64_t i64
Definition: object_fwd.hpp:110
Definition: object_fwd.hpp:32
array_size_overflow(const std::string &msg)
Definition: unpack.hpp:113
void reserve_buffer(std::size_t size=MSGPACK_UNPACKER_RESERVE_SIZE)
Reserve a buffer memory.
Definition: unpack.hpp:1502
Definition: unpack.hpp:454
void unpack_float(float d, msgpack::object &o)
Definition: unpack.hpp:251
Definition: unpack.hpp:139
void init_count(void *buffer)
Definition: unpack.hpp:373
void unpack_double(double d, msgpack::object &o)
Definition: unpack.hpp:254
unpack_reference_func reference_func() const
Definition: unpack.hpp:210
msgpack::object & obj()
Definition: unpack.hpp:357
void unpack_uint64(uint64_t d, msgpack::object &o)
Definition: unpack.hpp:232
uint32_t size
Definition: object_fwd.hpp:72
Definition: unpack.hpp:94
Definition: unpack.hpp:112
_msgpack_atomic_counter_t get_count(void *buffer)
Definition: unpack.hpp:405
void reset_zone()
Definition: unpack.hpp:1671
unpack_limit const & limit() const
Definition: unpack.hpp:212
msgpack::zone * release_zone()
Definition: unpack.hpp:1657
void unpack_int64(int64_t d, msgpack::object &o)
Definition: unpack.hpp:247
std::size_t str() const
Definition: unpack.hpp:183
void unpack_uint16(uint16_t d, msgpack::object &o)
Definition: unpack.hpp:226
void unpack_true(msgpack::object &o)
Definition: unpack.hpp:260
void set_map_key(msgpack::object const &map_key)
Definition: unpack.hpp:365
void buffer_consumed(std::size_t size)
Notify a buffer consumed information to msgpack::unpacker.
Definition: unpack.hpp:1590
double f64
Definition: object_fwd.hpp:114
msgpack::object const & data()
Definition: unpack.hpp:1652
Definition: object_fwd.hpp:41
insufficient_bytes(const std::string &msg)
Definition: unpack.hpp:95
msgpack::object_array array
Definition: object_fwd.hpp:115
char * buffer()
Get buffer pointer.
Definition: unpack.hpp:1580
void init()
Definition: unpack.hpp:463
Definition: cpp_config.hpp:64
msgpack::object_map map
Definition: object_fwd.hpp:116
msgpack::object_str str
Definition: object_fwd.hpp:117
std::size_t array() const
Definition: unpack.hpp:181
Object class that corresponding to MessagePack format object.
Definition: object_fwd.hpp:106
Definition: unpack.hpp:121
std::size_t message_size() const
Get message size.
Definition: unpack.hpp:1699
unpack_user & user()
Definition: unpack.hpp:476
msgpack::type::object_type type
Definition: object_fwd.hpp:122
msgpack::object const & data() const
Definition: unpack.hpp:471
msgpack::object const & map_key() const
Definition: unpack.hpp:364
Definition: unpack.hpp:354
Definition: object_fwd.hpp:39
void reset()
Definition: unpack.hpp:1692
msgpack::object key
Definition: object_fwd.hpp:256
Definition: unpack.hpp:1439
uint32_t size
Definition: object_fwd.hpp:55
Definition: object_fwd.hpp:40
msgpack::unique_ptr< msgpack::zone > & zone()
Get unique_ptr reference of zone.
Definition: object.hpp:61
void set_count(std::size_t count)
Definition: unpack.hpp:360
uint32_t size
Definition: object_fwd.hpp:60
size_overflow(const std::string &msg)
Definition: unpack.hpp:104
void unpack_nil(msgpack::object &o)
Definition: unpack.hpp:257
msgpack::zone & zone()
Definition: unpack.hpp:206
void unpack_map_item(msgpack::object &c, msgpack::object const &k, msgpack::object const &v)
Definition: unpack.hpp:293
void decr_count(void *buffer)
Definition: unpack.hpp:382
Unpacking class for a stream deserialization.
Definition: unpack.hpp:1000
Definition: unpack.hpp:416
std::size_t buffer_capacity() const
Get buffer capacity.
Definition: unpack.hpp:1585
void unpack_int32(int32_t d, msgpack::object &o)
Definition: unpack.hpp:243
unpack_limit & limit()
Definition: unpack.hpp:213
void unpack_array_item(msgpack::object &c, msgpack::object const &o)
Definition: unpack.hpp:275
T & move(T &t)
Definition: cpp_config.hpp:52
unpacked unpack(const char *data, std::size_t len, std::size_t &off, bool &referenced, unpack_reference_func f=nullptr, void *user_data=nullptr, unpack_limit const &limit=unpack_limit())
Unpack msgpack::object from a buffer.
Definition: unpack.hpp:1776
void * user_data() const
Definition: unpack.hpp:211
void set_zone(msgpack::zone &zone)
Definition: unpack.hpp:207
msgpack::object_ext ext
Definition: object_fwd.hpp:119
#define MSGPACK_UNPACKER_RESERVE_SIZE
Definition: unpack.hpp:47
Definition: unpack.hpp:421
std::size_t decr_count()
Definition: unpack.hpp:361
msgpack::object const & obj() const
Definition: unpack.hpp:356
void skip_nonparsed_buffer(std::size_t size)
Skip the specified size of non-parsed buffer.
Definition: unpack.hpp:1719
unpack_user(unpack_reference_func f=nullptr, void *user_data=nullptr, unpack_limit const &limit=unpack_limit())
Definition: unpack.hpp:201
unpack_user const & user() const
Definition: unpack.hpp:481
std::size_t depth() const
Definition: unpack.hpp:186
bin_size_overflow(const std::string &msg)
Definition: unpack.hpp:140
The class holds object and zone.
Definition: object.hpp:33
bool next(unpacked *result)
Unpack one msgpack::object. [obsolete].
Definition: unpack.hpp:1624
bool referenced() const
Definition: unpack.hpp:208
Definition: object_fwd.hpp:31
uint64_t u64
Definition: object_fwd.hpp:109
msgpack::object_bin bin
Definition: object_fwd.hpp:118