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