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