MessagePack for C++
parse.hpp
Go to the documentation of this file.
1 //
2 // MessagePack for C++ deserializing routine
3 //
4 // Copyright (C) 2016-2017 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_V2_PARSE_HPP
11 #define MSGPACK_V2_PARSE_HPP
12 
13 #if MSGPACK_DEFAULT_API_VERSION >= 2
14 
15 #include <cstddef>
16 
17 #include "msgpack/unpack_define.h"
18 #include "msgpack/parse_return.hpp"
20 #include "msgpack/unpack_decl.hpp"
21 
22 namespace msgpack {
23 
27 
28 namespace detail {
29 
30 using v1::detail::fix_tag;
31 using v1::detail::value;
32 using v1::detail::load;
33 
34 template <typename VisitorHolder>
35 class context {
36 public:
37  context()
38  :m_trail(0), m_cs(MSGPACK_CS_HEADER)
39  {
40  }
41 
42  void init()
43  {
44  m_cs = MSGPACK_CS_HEADER;
45  m_trail = 0;
46  m_stack.clear();
47  holder().visitor().init();
48  }
49 
50  parse_return execute(const char* data, std::size_t len, std::size_t& off);
51 
52 private:
53  template <typename T>
54  static uint32_t next_cs(T p)
55  {
56  return static_cast<uint32_t>(*p) & 0x1f;
57  }
58 
59  VisitorHolder& holder() {
60  return static_cast<VisitorHolder&>(*this);
61  }
62 
63  template <typename T, typename StartVisitor, typename EndVisitor>
64  parse_return start_aggregate(
65  StartVisitor const& sv,
66  EndVisitor const& ev,
67  const char* load_pos,
68  std::size_t& off) {
69  typename value<T>::type size;
70  load<T>(size, load_pos);
71  ++m_current;
72  if (size == 0) {
73  if (!sv(size)) {
74  off = static_cast<std::size_t>(m_current - m_start);
75  return PARSE_STOP_VISITOR;
76  }
77  if (!ev()) {
78  off = static_cast<std::size_t>(m_current - m_start);
79  return PARSE_STOP_VISITOR;
80  }
81  parse_return ret = m_stack.consume(holder());
82  if (ret != PARSE_CONTINUE) {
83  off = static_cast<std::size_t>(m_current - m_start);
84  return ret;
85  }
86  }
87  else {
88  if (!sv(size)) {
89  off = static_cast<std::size_t>(m_current - m_start);
90  return PARSE_STOP_VISITOR;
91  }
92  parse_return ret = m_stack.push(holder(), sv.type(), static_cast<uint32_t>(size));
93  if (ret != PARSE_CONTINUE) {
94  off = static_cast<std::size_t>(m_current - m_start);
95  return ret;
96  }
97  }
98  m_cs = MSGPACK_CS_HEADER;
99  return PARSE_CONTINUE;
100  }
101 
102  parse_return after_visit_proc(bool visit_result, std::size_t& off) {
103  ++m_current;
104  if (!visit_result) {
105  off = static_cast<std::size_t>(m_current - m_start);
106  return PARSE_STOP_VISITOR;
107  }
108  parse_return ret = m_stack.consume(holder());
109  if (ret != PARSE_CONTINUE) {
110  off = static_cast<std::size_t>(m_current - m_start);
111  }
112  m_cs = MSGPACK_CS_HEADER;
113  return ret;
114  }
115 
116  struct array_sv {
117  array_sv(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
118  bool operator()(uint32_t size) const {
119  return m_visitor_holder.visitor().start_array(size);
120  }
121  msgpack_container_type type() const { return MSGPACK_CT_ARRAY_ITEM; }
122  private:
123  VisitorHolder& m_visitor_holder;
124  };
125  struct array_ev {
126  array_ev(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
127  bool operator()() const {
128  return m_visitor_holder.visitor().end_array();
129  }
130  private:
131  VisitorHolder& m_visitor_holder;
132  };
133  struct map_sv {
134  map_sv(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
135  bool operator()(uint32_t size) const {
136  return m_visitor_holder.visitor().start_map(size);
137  }
138  msgpack_container_type type() const { return MSGPACK_CT_MAP_KEY; }
139  private:
140  VisitorHolder& m_visitor_holder;
141  };
142  struct map_ev {
143  map_ev(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
144  bool operator()() const {
145  return m_visitor_holder.visitor().end_map();
146  }
147  private:
148  VisitorHolder& m_visitor_holder;
149  };
150 
151  struct unpack_stack {
152  struct stack_elem {
153  stack_elem(msgpack_container_type type, uint32_t rest):m_type(type), m_rest(rest) {}
154  msgpack_container_type m_type;
155  uint32_t m_rest;
156  };
157  unpack_stack() {
158  m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
159  }
160  parse_return push(VisitorHolder& visitor_holder, msgpack_container_type type, uint32_t rest) {
161  m_stack.push_back(stack_elem(type, rest));
162  switch (type) {
163  case MSGPACK_CT_ARRAY_ITEM:
164  return visitor_holder.visitor().start_array_item() ? PARSE_CONTINUE : PARSE_STOP_VISITOR;
165  case MSGPACK_CT_MAP_KEY:
166  return visitor_holder.visitor().start_map_key() ? PARSE_CONTINUE : PARSE_STOP_VISITOR;
167  case MSGPACK_CT_MAP_VALUE:
168  assert(0);
169  return PARSE_STOP_VISITOR;
170  }
171  assert(0);
172  return PARSE_STOP_VISITOR;
173  }
174  parse_return consume(VisitorHolder& visitor_holder) {
175  while (!m_stack.empty()) {
176  stack_elem& e = m_stack.back();
177  switch (e.m_type) {
178  case MSGPACK_CT_ARRAY_ITEM:
179  if (!visitor_holder.visitor().end_array_item()) return PARSE_STOP_VISITOR;
180  if (--e.m_rest == 0) {
181  m_stack.pop_back();
182  if (!visitor_holder.visitor().end_array()) return PARSE_STOP_VISITOR;
183  }
184  else {
185  if (!visitor_holder.visitor().start_array_item()) return PARSE_STOP_VISITOR;
186  return PARSE_CONTINUE;
187  }
188  break;
189  case MSGPACK_CT_MAP_KEY:
190  if (!visitor_holder.visitor().end_map_key()) return PARSE_STOP_VISITOR;
191  if (!visitor_holder.visitor().start_map_value()) return PARSE_STOP_VISITOR;
192  e.m_type = MSGPACK_CT_MAP_VALUE;
193  return PARSE_CONTINUE;
194  case MSGPACK_CT_MAP_VALUE:
195  if (!visitor_holder.visitor().end_map_value()) return PARSE_STOP_VISITOR;
196  if (--e.m_rest == 0) {
197  m_stack.pop_back();
198  if (!visitor_holder.visitor().end_map()) return PARSE_STOP_VISITOR;
199  }
200  else {
201  e.m_type = MSGPACK_CT_MAP_KEY;
202  if (!visitor_holder.visitor().start_map_key()) return PARSE_STOP_VISITOR;
203  return PARSE_CONTINUE;
204  }
205  break;
206  }
207  }
208  return PARSE_SUCCESS;
209  }
210  bool empty() const { return m_stack.empty(); }
211  void clear() { m_stack.clear(); }
212  private:
213  std::vector<stack_elem> m_stack;
214  };
215 
216  char const* m_start;
217  char const* m_current;
218 
219  std::size_t m_trail;
220  uint32_t m_cs;
221  uint32_t m_num_elements;
222  unpack_stack m_stack;
223 };
224 
225 template <std::size_t N>
226 inline void check_ext_size(std::size_t /*size*/) {
227 }
228 
229 template <>
230 inline void check_ext_size<4>(std::size_t size) {
231  if (size == 0xffffffff) throw msgpack::ext_size_overflow("ext size overflow");
232 }
233 
234 template <typename VisitorHolder>
235 inline parse_return context<VisitorHolder>::execute(const char* data, std::size_t len, std::size_t& off)
236 {
237  assert(len >= off);
238 
239  m_start = data;
240  m_current = data + off;
241  const char* const pe = data + len;
242  const char* n = MSGPACK_NULLPTR;
243 
244  if(m_current == pe) {
245  off = static_cast<std::size_t>(m_current - m_start);
246  return PARSE_CONTINUE;
247  }
248  bool fixed_trail_again = false;
249  do {
250  if (m_cs == MSGPACK_CS_HEADER) {
251  fixed_trail_again = false;
252  int selector = *reinterpret_cast<const unsigned char*>(m_current);
253  if (0x00 <= selector && selector <= 0x7f) { // Positive Fixnum
254  uint8_t tmp = *reinterpret_cast<const uint8_t*>(m_current);
255  bool visret = holder().visitor().visit_positive_integer(tmp);
256  parse_return upr = after_visit_proc(visret, off);
257  if (upr != PARSE_CONTINUE) return upr;
258  } else if(0xe0 <= selector && selector <= 0xff) { // Negative Fixnum
259  int8_t tmp = *reinterpret_cast<const int8_t*>(m_current);
260  bool visret = holder().visitor().visit_negative_integer(tmp);
261  parse_return upr = after_visit_proc(visret, off);
262  if (upr != PARSE_CONTINUE) return upr;
263  } else if (0xc4 <= selector && selector <= 0xdf) {
264  const uint32_t trail[] = {
265  1, // bin 8 0xc4
266  2, // bin 16 0xc5
267  4, // bin 32 0xc6
268  1, // ext 8 0xc7
269  2, // ext 16 0xc8
270  4, // ext 32 0xc9
271  4, // float 32 0xca
272  8, // float 64 0xcb
273  1, // uint 8 0xcc
274  2, // uint 16 0xcd
275  4, // uint 32 0xce
276  8, // uint 64 0xcf
277  1, // int 8 0xd0
278  2, // int 16 0xd1
279  4, // int 32 0xd2
280  8, // int 64 0xd3
281  2, // fixext 1 0xd4
282  3, // fixext 2 0xd5
283  5, // fixext 4 0xd6
284  9, // fixext 8 0xd7
285  17,// fixext 16 0xd8
286  1, // str 8 0xd9
287  2, // str 16 0xda
288  4, // str 32 0xdb
289  2, // array 16 0xdc
290  4, // array 32 0xdd
291  2, // map 16 0xde
292  4, // map 32 0xdf
293  };
294  m_trail = trail[selector - 0xc4];
295  m_cs = next_cs(m_current);
296  fixed_trail_again = true;
297  } else if(0xa0 <= selector && selector <= 0xbf) { // FixStr
298  m_trail = static_cast<uint32_t>(*m_current) & 0x1f;
299  if(m_trail == 0) {
300  bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
301  parse_return upr = after_visit_proc(visret, off);
302  if (upr != PARSE_CONTINUE) return upr;
303  }
304  else {
305  m_cs = MSGPACK_ACS_STR_VALUE;
306  fixed_trail_again = true;
307  }
308  } else if(0x90 <= selector && selector <= 0x9f) { // FixArray
309  parse_return ret = start_aggregate<fix_tag>(array_sv(holder()), array_ev(holder()), m_current, off);
310  if (ret != PARSE_CONTINUE) return ret;
311  } else if(0x80 <= selector && selector <= 0x8f) { // FixMap
312  parse_return ret = start_aggregate<fix_tag>(map_sv(holder()), map_ev(holder()), m_current, off);
313  if (ret != PARSE_CONTINUE) return ret;
314  } else if(selector == 0xc2) { // false
315  bool visret = holder().visitor().visit_boolean(false);
316  parse_return upr = after_visit_proc(visret, off);
317  if (upr != PARSE_CONTINUE) return upr;
318  } else if(selector == 0xc3) { // true
319  bool visret = holder().visitor().visit_boolean(true);
320  parse_return upr = after_visit_proc(visret, off);
321  if (upr != PARSE_CONTINUE) return upr;
322  } else if(selector == 0xc0) { // nil
323  bool visret = holder().visitor().visit_nil();
324  parse_return upr = after_visit_proc(visret, off);
325  if (upr != PARSE_CONTINUE) return upr;
326  } else {
327  off = static_cast<std::size_t>(m_current - m_start);
328  holder().visitor().parse_error(off - 1, off);
329  return PARSE_PARSE_ERROR;
330  }
331  // end MSGPACK_CS_HEADER
332  }
333  if (m_cs != MSGPACK_CS_HEADER || fixed_trail_again) {
334  if (fixed_trail_again) {
335  ++m_current;
336  fixed_trail_again = false;
337  }
338  if(static_cast<std::size_t>(pe - m_current) < m_trail) {
339  off = static_cast<std::size_t>(m_current - m_start);
340  return PARSE_CONTINUE;
341  }
342  n = m_current;
343  m_current += m_trail - 1;
344  switch(m_cs) {
345  //case MSGPACK_CS_
346  //case MSGPACK_CS_
347  case MSGPACK_CS_FLOAT: {
348  union { uint32_t i; float f; } mem;
349  load<uint32_t>(mem.i, n);
350  bool visret = holder().visitor().visit_float32(mem.f);
351  parse_return upr = after_visit_proc(visret, off);
352  if (upr != PARSE_CONTINUE) return upr;
353  } break;
354  case MSGPACK_CS_DOUBLE: {
355  union { uint64_t i; double f; } mem;
356  load<uint64_t>(mem.i, n);
357 #if defined(TARGET_OS_IPHONE)
358  // ok
359 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
360  // https://github.com/msgpack/msgpack-perl/pull/1
361  mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
362 #endif
363  bool visret = holder().visitor().visit_float64(mem.f);
364  parse_return upr = after_visit_proc(visret, off);
365  if (upr != PARSE_CONTINUE) return upr;
366  } break;
367  case MSGPACK_CS_UINT_8: {
368  uint8_t tmp;
369  load<uint8_t>(tmp, n);
370  bool visret = holder().visitor().visit_positive_integer(tmp);
371  parse_return upr = after_visit_proc(visret, off);
372  if (upr != PARSE_CONTINUE) return upr;
373  } break;
374  case MSGPACK_CS_UINT_16: {
375  uint16_t tmp;
376  load<uint16_t>(tmp, n);
377  bool visret = holder().visitor().visit_positive_integer(tmp);
378  parse_return upr = after_visit_proc(visret, off);
379  if (upr != PARSE_CONTINUE) return upr;
380  } break;
381  case MSGPACK_CS_UINT_32: {
382  uint32_t tmp;
383  load<uint32_t>(tmp, n);
384  bool visret = holder().visitor().visit_positive_integer(tmp);
385  parse_return upr = after_visit_proc(visret, off);
386  if (upr != PARSE_CONTINUE) return upr;
387  } break;
388  case MSGPACK_CS_UINT_64: {
389  uint64_t tmp;
390  load<uint64_t>(tmp, n);
391  bool visret = holder().visitor().visit_positive_integer(tmp);
392  parse_return upr = after_visit_proc(visret, off);
393  if (upr != PARSE_CONTINUE) return upr;
394  } break;
395  case MSGPACK_CS_INT_8: {
396  int8_t tmp;
397  load<int8_t>(tmp, n);
398  bool visret = holder().visitor().visit_negative_integer(tmp);
399  parse_return upr = after_visit_proc(visret, off);
400  if (upr != PARSE_CONTINUE) return upr;
401  } break;
402  case MSGPACK_CS_INT_16: {
403  int16_t tmp;
404  load<int16_t>(tmp, n);
405  bool visret = holder().visitor().visit_negative_integer(tmp);
406  parse_return upr = after_visit_proc(visret, off);
407  if (upr != PARSE_CONTINUE) return upr;
408  } break;
409  case MSGPACK_CS_INT_32: {
410  int32_t tmp;
411  load<int32_t>(tmp, n);
412  bool visret = holder().visitor().visit_negative_integer(tmp);
413  parse_return upr = after_visit_proc(visret, off);
414  if (upr != PARSE_CONTINUE) return upr;
415  } break;
416  case MSGPACK_CS_INT_64: {
417  int64_t tmp;
418  load<int64_t>(tmp, n);
419  bool visret = holder().visitor().visit_negative_integer(tmp);
420  parse_return upr = after_visit_proc(visret, off);
421  if (upr != PARSE_CONTINUE) return upr;
422  } break;
423  case MSGPACK_CS_FIXEXT_1: {
424  bool visret = holder().visitor().visit_ext(n, 1+1);
425  parse_return upr = after_visit_proc(visret, off);
426  if (upr != PARSE_CONTINUE) return upr;
427  } break;
428  case MSGPACK_CS_FIXEXT_2: {
429  bool visret = holder().visitor().visit_ext(n, 2+1);
430  parse_return upr = after_visit_proc(visret, off);
431  if (upr != PARSE_CONTINUE) return upr;
432  } break;
433  case MSGPACK_CS_FIXEXT_4: {
434  bool visret = holder().visitor().visit_ext(n, 4+1);
435  parse_return upr = after_visit_proc(visret, off);
436  if (upr != PARSE_CONTINUE) return upr;
437  } break;
438  case MSGPACK_CS_FIXEXT_8: {
439  bool visret = holder().visitor().visit_ext(n, 8+1);
440  parse_return upr = after_visit_proc(visret, off);
441  if (upr != PARSE_CONTINUE) return upr;
442  } break;
443  case MSGPACK_CS_FIXEXT_16: {
444  bool visret = holder().visitor().visit_ext(n, 16+1);
445  parse_return upr = after_visit_proc(visret, off);
446  if (upr != PARSE_CONTINUE) return upr;
447  } break;
448  case MSGPACK_CS_STR_8: {
449  uint8_t tmp;
450  load<uint8_t>(tmp, n);
451  m_trail = tmp;
452  if(m_trail == 0) {
453  bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
454  parse_return upr = after_visit_proc(visret, off);
455  if (upr != PARSE_CONTINUE) return upr;
456  }
457  else {
458  m_cs = MSGPACK_ACS_STR_VALUE;
459  fixed_trail_again = true;
460  }
461  } break;
462  case MSGPACK_CS_BIN_8: {
463  uint8_t tmp;
464  load<uint8_t>(tmp, n);
465  m_trail = tmp;
466  if(m_trail == 0) {
467  bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
468  parse_return upr = after_visit_proc(visret, off);
469  if (upr != PARSE_CONTINUE) return upr;
470  }
471  else {
472  m_cs = MSGPACK_ACS_BIN_VALUE;
473  fixed_trail_again = true;
474  }
475  } break;
476  case MSGPACK_CS_EXT_8: {
477  uint8_t tmp;
478  load<uint8_t>(tmp, n);
479  m_trail = tmp + 1;
480  if(m_trail == 0) {
481  bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
482  parse_return upr = after_visit_proc(visret, off);
483  if (upr != PARSE_CONTINUE) return upr;
484  }
485  else {
486  m_cs = MSGPACK_ACS_EXT_VALUE;
487  fixed_trail_again = true;
488  }
489  } break;
490  case MSGPACK_CS_STR_16: {
491  uint16_t tmp;
492  load<uint16_t>(tmp, n);
493  m_trail = tmp;
494  if(m_trail == 0) {
495  bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
496  parse_return upr = after_visit_proc(visret, off);
497  if (upr != PARSE_CONTINUE) return upr;
498  }
499  else {
500  m_cs = MSGPACK_ACS_STR_VALUE;
501  fixed_trail_again = true;
502  }
503  } break;
504  case MSGPACK_CS_BIN_16: {
505  uint16_t tmp;
506  load<uint16_t>(tmp, n);
507  m_trail = tmp;
508  if(m_trail == 0) {
509  bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
510  parse_return upr = after_visit_proc(visret, off);
511  if (upr != PARSE_CONTINUE) return upr;
512  }
513  else {
514  m_cs = MSGPACK_ACS_BIN_VALUE;
515  fixed_trail_again = true;
516  }
517  } break;
518  case MSGPACK_CS_EXT_16: {
519  uint16_t tmp;
520  load<uint16_t>(tmp, n);
521  m_trail = tmp + 1;
522  if(m_trail == 0) {
523  bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
524  parse_return upr = after_visit_proc(visret, off);
525  if (upr != PARSE_CONTINUE) return upr;
526  }
527  else {
528  m_cs = MSGPACK_ACS_EXT_VALUE;
529  fixed_trail_again = true;
530  }
531  } break;
532  case MSGPACK_CS_STR_32: {
533  uint32_t tmp;
534  load<uint32_t>(tmp, n);
535  m_trail = tmp;
536  if(m_trail == 0) {
537  bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
538  parse_return upr = after_visit_proc(visret, off);
539  if (upr != PARSE_CONTINUE) return upr;
540  }
541  else {
542  m_cs = MSGPACK_ACS_STR_VALUE;
543  fixed_trail_again = true;
544  }
545  } break;
546  case MSGPACK_CS_BIN_32: {
547  uint32_t tmp;
548  load<uint32_t>(tmp, n);
549  m_trail = tmp;
550  if(m_trail == 0) {
551  bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
552  parse_return upr = after_visit_proc(visret, off);
553  if (upr != PARSE_CONTINUE) return upr;
554  }
555  else {
556  m_cs = MSGPACK_ACS_BIN_VALUE;
557  fixed_trail_again = true;
558  }
559  } break;
560  case MSGPACK_CS_EXT_32: {
561  uint32_t tmp;
562  load<uint32_t>(tmp, n);
563  check_ext_size<sizeof(std::size_t)>(tmp);
564  m_trail = tmp;
565  ++m_trail;
566  if(m_trail == 0) {
567  bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
568  parse_return upr = after_visit_proc(visret, off);
569  if (upr != PARSE_CONTINUE) return upr;
570  }
571  else {
572  m_cs = MSGPACK_ACS_EXT_VALUE;
573  fixed_trail_again = true;
574  }
575  } break;
576  case MSGPACK_ACS_STR_VALUE: {
577  bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
578  parse_return upr = after_visit_proc(visret, off);
579  if (upr != PARSE_CONTINUE) return upr;
580  } break;
581  case MSGPACK_ACS_BIN_VALUE: {
582  bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
583  parse_return upr = after_visit_proc(visret, off);
584  if (upr != PARSE_CONTINUE) return upr;
585  } break;
586  case MSGPACK_ACS_EXT_VALUE: {
587  bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
588  parse_return upr = after_visit_proc(visret, off);
589  if (upr != PARSE_CONTINUE) return upr;
590  } break;
591  case MSGPACK_CS_ARRAY_16: {
592  parse_return ret = start_aggregate<uint16_t>(array_sv(holder()), array_ev(holder()), n, off);
593  if (ret != PARSE_CONTINUE) return ret;
594 
595  } break;
596  case MSGPACK_CS_ARRAY_32: {
597  parse_return ret = start_aggregate<uint32_t>(array_sv(holder()), array_ev(holder()), n, off);
598  if (ret != PARSE_CONTINUE) return ret;
599  } break;
600  case MSGPACK_CS_MAP_16: {
601  parse_return ret = start_aggregate<uint16_t>(map_sv(holder()), map_ev(holder()), n, off);
602  if (ret != PARSE_CONTINUE) return ret;
603  } break;
604  case MSGPACK_CS_MAP_32: {
605  parse_return ret = start_aggregate<uint32_t>(map_sv(holder()), map_ev(holder()), n, off);
606  if (ret != PARSE_CONTINUE) return ret;
607  } break;
608  default:
609  off = static_cast<std::size_t>(m_current - m_start);
610  holder().visitor().parse_error(static_cast<std::size_t>(n - m_start - 1), static_cast<std::size_t>(n - m_start));
611  return PARSE_PARSE_ERROR;
612  }
613  }
614  } while(m_current != pe);
615 
616  off = static_cast<std::size_t>(m_current - m_start);
617  return PARSE_CONTINUE;
618 }
619 
620 } // detail
621 
622 
624 
625 template <typename VisitorHolder, typename ReferencedBufferHook>
626 class parser : public detail::context<VisitorHolder> {
627  typedef parser<VisitorHolder, ReferencedBufferHook> this_type;
628  typedef detail::context<VisitorHolder> context_type;
629 public:
631 
639  parser(ReferencedBufferHook& hook,
640  std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
641 
642 #if !defined(MSGPACK_USE_CPP03)
643  parser(this_type&& other);
644  this_type& operator=(this_type&& other);
645 #endif // !defined(MSGPACK_USE_CPP03)
646 
647  ~parser();
648 
649 public:
651 
658  void reserve_buffer(std::size_t size = MSGPACK_UNPACKER_RESERVE_SIZE);
659 
661 
666  char* buffer();
667 
669 
675  std::size_t buffer_capacity() const;
676 
678 
687  void buffer_consumed(std::size_t size);
688 
690 
700  bool next();
701 
703 
706  std::size_t message_size() const;
707 
708 public:
710 
716  std::size_t parsed_size() const;
717 
719 
725  char* nonparsed_buffer();
726 
728 
734  std::size_t nonparsed_size() const;
735 
737 
744  void skip_nonparsed_buffer(std::size_t size);
745 
747 
751  void remove_nonparsed_buffer();
752 
753  void reset();
754 
755 protected:
756  char* get_raw_buffer() {
757  return m_buffer;
758  }
759 private:
760  void expand_buffer(std::size_t size);
761  parse_return execute_imp();
762 
763 private:
764  char* m_buffer;
765  std::size_t m_used;
766  std::size_t m_free;
767  std::size_t m_off;
768  std::size_t m_parsed;
769  std::size_t m_initial_buffer_size;
770  ReferencedBufferHook& m_referenced_buffer_hook;
771 
772 #if defined(MSGPACK_USE_CPP03)
773 private:
774  parser(const this_type&);
775  this_type& operator=(const this_type&);
776 #else // defined(MSGPACK_USE_CPP03)
777 public:
778  parser(const this_type&) = delete;
779  this_type& operator=(const this_type&) = delete;
780 #endif // defined(MSGPACK_USE_CPP03)
781 };
782 
783 template <typename VisitorHolder, typename ReferencedBufferHook>
784 inline parser<VisitorHolder, ReferencedBufferHook>::parser(
785  ReferencedBufferHook& hook,
786  std::size_t initial_buffer_size)
787  :m_referenced_buffer_hook(hook)
788 {
789  if(initial_buffer_size < COUNTER_SIZE) {
790  initial_buffer_size = COUNTER_SIZE;
791  }
792 
793  char* buffer = static_cast<char*>(::malloc(initial_buffer_size));
794  if(!buffer) {
795  throw std::bad_alloc();
796  }
797 
798  m_buffer = buffer;
799  m_used = COUNTER_SIZE;
800  m_free = initial_buffer_size - m_used;
801  m_off = COUNTER_SIZE;
802  m_parsed = 0;
803  m_initial_buffer_size = initial_buffer_size;
804 
805  detail::init_count(m_buffer);
806 }
807 
808 #if !defined(MSGPACK_USE_CPP03)
809 // Move constructor and move assignment operator
810 
811 template <typename VisitorHolder, typename ReferencedBufferHook>
812 inline parser<VisitorHolder, ReferencedBufferHook>::parser(this_type&& other)
813  :context_type(std::move(other)),
814  m_buffer(other.m_buffer),
815  m_used(other.m_used),
816  m_free(other.m_free),
817  m_off(other.m_off),
818  m_parsed(other.m_parsed),
819  m_initial_buffer_size(other.m_initial_buffer_size),
820  m_referenced_buffer_hook(other.m_referenced_buffer_hook) {
821  other.m_buffer = MSGPACK_NULLPTR;
822  other.m_used = 0;
823  other.m_free = 0;
824  other.m_off = 0;
825  other.m_parsed = 0;
826 }
827 
828 template <typename VisitorHolder, typename ReferencedBufferHook>
829 inline parser<VisitorHolder, ReferencedBufferHook>& parser<VisitorHolder, ReferencedBufferHook>::operator=(this_type&& other) {
830  this->~parser();
831  new (this) this_type(std::move(other));
832  return *this;
833 }
834 
835 #endif // !defined(MSGPACK_USE_CPP03)
836 
837 
838 template <typename VisitorHolder, typename ReferencedBufferHook>
839 inline parser<VisitorHolder, ReferencedBufferHook>::~parser()
840 {
841  // These checks are required for move operations.
842  if (m_buffer) detail::decr_count(m_buffer);
843 }
844 
845 
846 template <typename VisitorHolder, typename ReferencedBufferHook>
847 inline void parser<VisitorHolder, ReferencedBufferHook>::reserve_buffer(std::size_t size)
848 {
849  if(m_free >= size) return;
850  expand_buffer(size);
851 }
852 
853 template <typename VisitorHolder, typename ReferencedBufferHook>
854 inline void parser<VisitorHolder, ReferencedBufferHook>::expand_buffer(std::size_t size)
855 {
856  if(m_used == m_off && detail::get_count(m_buffer) == 1
857  && !static_cast<VisitorHolder&>(*this).visitor().referenced()) {
858  // rewind buffer
859  m_free += m_used - COUNTER_SIZE;
860  m_used = COUNTER_SIZE;
861  m_off = COUNTER_SIZE;
862 
863  if(m_free >= size) return;
864  }
865 
866  if(m_off == COUNTER_SIZE) {
867  std::size_t next_size = (m_used + m_free) * 2; // include COUNTER_SIZE
868  while(next_size < size + m_used) {
869  std::size_t tmp_next_size = next_size * 2;
870  if (tmp_next_size <= next_size) {
871  next_size = size + m_used;
872  break;
873  }
874  next_size = tmp_next_size;
875  }
876 
877  char* tmp = static_cast<char*>(::realloc(m_buffer, next_size));
878  if(!tmp) {
879  throw std::bad_alloc();
880  }
881 
882  m_buffer = tmp;
883  m_free = next_size - m_used;
884 
885  } else {
886  std::size_t next_size = m_initial_buffer_size; // include COUNTER_SIZE
887  std::size_t not_parsed = m_used - m_off;
888  while(next_size < size + not_parsed + COUNTER_SIZE) {
889  std::size_t tmp_next_size = next_size * 2;
890  if (tmp_next_size <= next_size) {
891  next_size = size + not_parsed + COUNTER_SIZE;
892  break;
893  }
894  next_size = tmp_next_size;
895  }
896 
897  char* tmp = static_cast<char*>(::malloc(next_size));
898  if(!tmp) {
899  throw std::bad_alloc();
900  }
901 
902  detail::init_count(tmp);
903 
904  std::memcpy(tmp+COUNTER_SIZE, m_buffer + m_off, not_parsed);
905 
906  if(static_cast<VisitorHolder&>(*this).referenced()) {
907  try {
908  m_referenced_buffer_hook(m_buffer);
909  }
910  catch (...) {
911  ::free(tmp);
912  throw;
913  }
914  static_cast<VisitorHolder&>(*this).set_referenced(false);
915  } else {
916  detail::decr_count(m_buffer);
917  }
918 
919  m_buffer = tmp;
920  m_used = not_parsed + COUNTER_SIZE;
921  m_free = next_size - m_used;
922  m_off = COUNTER_SIZE;
923  }
924 }
925 
926 template <typename VisitorHolder, typename ReferencedBufferHook>
927 inline char* parser<VisitorHolder, ReferencedBufferHook>::buffer()
928 {
929  return m_buffer + m_used;
930 }
931 
932 template <typename VisitorHolder, typename ReferencedBufferHook>
933 inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::buffer_capacity() const
934 {
935  return m_free;
936 }
937 
938 template <typename VisitorHolder, typename ReferencedBufferHook>
939 inline void parser<VisitorHolder, ReferencedBufferHook>::buffer_consumed(std::size_t size)
940 {
941  m_used += size;
942  m_free -= size;
943 }
944 
945 template <typename VisitorHolder, typename ReferencedBufferHook>
946  inline bool parser<VisitorHolder, ReferencedBufferHook>::next()
947 {
948  parse_return ret = execute_imp();
949  return ret == PARSE_SUCCESS;
950 }
951 
952 template <typename VisitorHolder, typename ReferencedBufferHook>
953 inline parse_return parser<VisitorHolder, ReferencedBufferHook>::execute_imp()
954 {
955  std::size_t off = m_off;
956  parse_return ret = context_type::execute(m_buffer, m_used, m_off);
957  if(m_off > off) {
958  m_parsed += m_off - off;
959  }
960  return ret;
961 }
962 
963 template <typename VisitorHolder, typename ReferencedBufferHook>
964 inline void parser<VisitorHolder, ReferencedBufferHook>::reset()
965 {
966  context_type::init();
967  // don't reset referenced flag
968  m_parsed = 0;
969 }
970 
971 template <typename VisitorHolder, typename ReferencedBufferHook>
972 inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::message_size() const
973 {
974  return m_parsed - m_off + m_used;
975 }
976 
977 template <typename VisitorHolder, typename ReferencedBufferHook>
978 inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::parsed_size() const
979 {
980  return m_parsed;
981 }
982 
983 template <typename VisitorHolder, typename ReferencedBufferHook>
984 inline char* parser<VisitorHolder, ReferencedBufferHook>::nonparsed_buffer()
985 {
986  return m_buffer + m_off;
987 }
988 
989 template <typename VisitorHolder, typename ReferencedBufferHook>
990 inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::nonparsed_size() const
991 {
992  return m_used - m_off;
993 }
994 
995 template <typename VisitorHolder, typename ReferencedBufferHook>
996 inline void parser<VisitorHolder, ReferencedBufferHook>::skip_nonparsed_buffer(std::size_t size)
997 {
998  m_off += size;
999 }
1000 
1001 template <typename VisitorHolder, typename ReferencedBufferHook>
1002 inline void parser<VisitorHolder, ReferencedBufferHook>::remove_nonparsed_buffer()
1003 {
1004  m_used = m_off;
1005 }
1006 
1007 template <typename Visitor>
1008 inline bool parse(const char* data, size_t len, size_t& off, Visitor& v) {
1009  parse_return ret = msgpack::detail::parse_imp(data, len, off, v);
1010  return ret == PARSE_SUCCESS || ret == PARSE_EXTRA_BYTES;
1011 }
1012 
1013 template <typename Visitor>
1014 inline bool parse(const char* data, size_t len, Visitor& v) {
1015  std::size_t off = 0;
1016  return msgpack::parse(data, len, off, v);
1017 }
1018 
1019 namespace detail {
1020 
1021 template <typename Visitor>
1022 struct parse_helper : detail::context<parse_helper<Visitor> > {
1023  parse_helper(Visitor& v):m_visitor(v) {}
1024  parse_return execute(const char* data, std::size_t len, std::size_t& off) {
1025  return detail::context<parse_helper<Visitor> >::execute(data, len, off);
1026  }
1027  Visitor& visitor() const { return m_visitor; }
1028  Visitor& m_visitor;
1029 };
1030 
1031 template <typename Visitor>
1032 inline parse_return
1033 parse_imp(const char* data, size_t len, size_t& off, Visitor& v) {
1034  std::size_t noff = off;
1035 
1036  if(len <= noff) {
1037  // FIXME
1038  v.insufficient_bytes(noff, noff);
1039  return PARSE_CONTINUE;
1040  }
1041  detail::parse_helper<Visitor> h(v);
1042  parse_return ret = h.execute(data, len, noff);
1043  switch (ret) {
1044  case PARSE_CONTINUE:
1045  off = noff;
1046  v.insufficient_bytes(noff - 1, noff);
1047  return ret;
1048  case PARSE_SUCCESS:
1049  off = noff;
1050  if(noff < len) {
1051  return PARSE_EXTRA_BYTES;
1052  }
1053  return ret;
1054  default:
1055  return ret;
1056  }
1057 }
1058 
1059 } // detail
1060 
1061 
1063 } // MSGPACK_API_VERSION_NAMESPACE(v2)
1065 
1066 } // namespace msgpack
1067 
1068 #endif // MSGPACK_DEFAULT_API_VERSION >= 2
1069 
1070 #endif // MSGPACK_V2_PARSE_HPP
msgpack::detail::load
msgpack::enable_if< sizeof(T)==sizeof(fix_tag)>::type load(uint32_t &dst, const char *n)
Definition: unpack.hpp:286
msgpack::detail::context::execute
int execute(const char *data, std::size_t len, std::size_t &off)
Definition: unpack.hpp:459
MSGPACK_UNPACKER_INIT_BUFFER_SIZE
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE
Definition: unpack_decl.hpp:43
unpack_decl.hpp
msgpack::detail::context::context
context(unpack_reference_func f, void *user_data, unpack_limit const &limit)
Definition: unpack.hpp:312
msgpack::PARSE_PARSE_ERROR
@ PARSE_PARSE_ERROR
Definition: parse_return.hpp:27
msgpack
Definition: adaptor_base.hpp:15
msgpack::PARSE_STOP_VISITOR
@ PARSE_STOP_VISITOR
Definition: parse_return.hpp:28
msgpack::parse_return
parse_return
Definition: parse_return.hpp:23
msgpack::PARSE_CONTINUE
@ PARSE_CONTINUE
Definition: parse_return.hpp:26
msgpack::detail::parse_imp
parse_return parse_imp(const char *data, size_t len, size_t &off, Visitor &v)
MSGPACK_API_VERSION_NAMESPACE
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:58
unpack_exception.hpp
parse_return.hpp
msgpack::detail::get_count
std::atomic< unsigned int > const & get_count(void *buffer)
Definition: unpack.hpp:270
msgpack::detail::context::init
void init()
Definition: unpack.hpp:319
msgpack::detail::context::data
msgpack::object const & data() const
Definition: unpack.hpp:327
v2
msgpack::type::size
std::size_t size(T const &t)
Definition: size_equal_only.hpp:24
MSGPACK_NULLPTR
#define MSGPACK_NULLPTR
Definition: cpp_config_decl.hpp:35
msgpack::detail::value::type
T type
Definition: unpack.hpp:278
msgpack::detail::decr_count
void decr_count(void *buffer)
Definition: unpack.hpp:242
msgpack::parse
bool parse(const char *data, size_t len, size_t &off, Visitor &v)
Unpack msgpack formatted data via a visitor.
msgpack::detail::init_count
void init_count(void *buffer)
Definition: unpack.hpp:233
COUNTER_SIZE
const size_t COUNTER_SIZE
Definition: unpack_decl.hpp:40
msgpack::move
T & move(T &t)
msgpack::ext_size_overflow
Definition: unpack_exception.hpp:97
MSGPACK_UNPACKER_RESERVE_SIZE
#define MSGPACK_UNPACKER_RESERVE_SIZE
Definition: unpack_decl.hpp:47
msgpack::PARSE_SUCCESS
@ PARSE_SUCCESS
Definition: parse_return.hpp:24
msgpack::PARSE_EXTRA_BYTES
@ PARSE_EXTRA_BYTES
Definition: parse_return.hpp:25