1 //
2 // MessagePack for C++ deserializing routine
3 //
4 // Copyright (C) 2018 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_V3_PARSE_HPP
11 #define MSGPACK_V3_PARSE_HPP
12 
13 #if MSGPACK_DEFAULT_API_VERSION >= 2
14 
15 #include <cstddef>
16 
17 #include "msgpack/parse_return.hpp"
18 
19 namespace msgpack {
20 
21 /// @cond
MSGPACK_API_VERSION_NAMESPACE(v3)22 MSGPACK_API_VERSION_NAMESPACE(v3) {
23 /// @endcond
24 
25 namespace detail {
26 
27 template <typename VisitorHolder>
28 class context {
29 public:
30     context()
31         :m_trail(0), m_cs(MSGPACK_CS_HEADER)
32     {
33     }
34 
35     void init()
36     {
37         m_cs = MSGPACK_CS_HEADER;
38         m_trail = 0;
39         m_stack.clear();
40         holder().visitor().init();
41     }
42 
43     parse_return execute(const char* data, std::size_t len, std::size_t& off);
44 
45 private:
46     template <typename T>
47     static uint32_t next_cs(T p)
48     {
49         return static_cast<uint32_t>(*p) & 0x1f;
50     }
51 
52     VisitorHolder& holder() {
53         return static_cast<VisitorHolder&>(*this);
54     }
55 
56     template <typename T, typename StartVisitor, typename EndVisitor>
57     parse_return start_aggregate(
58         StartVisitor const& sv,
59         EndVisitor const& ev,
60         const char* load_pos,
61         std::size_t& off) {
62         typename value<T>::type size;
63         load<T>(size, load_pos);
64         if (size == 0) {
65             if (!sv(size)) {
66                 off = m_current - m_start;
67                 return PARSE_STOP_VISITOR;
68             }
69             if (!ev()) {
70                 off = m_current - m_start;
71                 return PARSE_STOP_VISITOR;
72             }
73             parse_return ret = m_stack.consume(holder(), m_current);
74             ++m_current;
75             if (ret != PARSE_CONTINUE) {
76                 off = m_current - m_start;
77                 return ret;
78             }
79         }
80         else {
81             if (!sv(size)) {
82                 off = m_current - m_start;
83                 return PARSE_STOP_VISITOR;
84             }
85             parse_return ret = m_stack.push(holder(), sv.type(), static_cast<uint32_t>(size));
86             ++m_current;
87             if (ret != PARSE_CONTINUE) {
88                 off = m_current - m_start;
89                 return ret;
90             }
91         }
92         m_cs = MSGPACK_CS_HEADER;
93         return PARSE_CONTINUE;
94     }
95 
96     parse_return after_visit_proc(bool visit_result, std::size_t& off) {
97         if (!visit_result) {
98             off = m_current - m_start;
99             return PARSE_STOP_VISITOR;
100         }
101         parse_return ret = m_stack.consume(holder(), m_current);
102         ++m_current;
103         if (ret != PARSE_CONTINUE) {
104             off = m_current - m_start;
105         }
106         m_cs = MSGPACK_CS_HEADER;
107         return ret;
108     }
109 
110     struct array_sv {
111         array_sv(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
112         bool operator()(uint32_t size) const {
113             return m_visitor_holder.visitor().start_array(size);
114         }
115         msgpack_container_type type() const { return MSGPACK_CT_ARRAY_ITEM; }
116     private:
117         VisitorHolder& m_visitor_holder;
118     };
119     struct array_ev {
120         array_ev(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
121         bool operator()() const {
122             return m_visitor_holder.visitor().end_array();
123         }
124     private:
125         VisitorHolder& m_visitor_holder;
126     };
127     struct map_sv {
128         map_sv(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
129         bool operator()(uint32_t size) const {
130             return m_visitor_holder.visitor().start_map(size);
131         }
132         msgpack_container_type type() const { return MSGPACK_CT_MAP_KEY; }
133     private:
134         VisitorHolder& m_visitor_holder;
135     };
136     struct map_ev {
137         map_ev(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
138         bool operator()() const {
139             return m_visitor_holder.visitor().end_map();
140         }
141     private:
142         VisitorHolder& m_visitor_holder;
143     };
144 
145     struct unpack_stack {
146         struct stack_elem {
147             stack_elem(msgpack_container_type type, uint32_t rest):m_type(type), m_rest(rest) {}
148             msgpack_container_type m_type;
149             uint32_t m_rest;
150         };
151         unpack_stack() {
152             m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
153         }
154         parse_return push(VisitorHolder& visitor_holder, msgpack_container_type type, uint32_t rest) {
155             m_stack.push_back(stack_elem(type, rest));
156             switch (type) {
157             case MSGPACK_CT_ARRAY_ITEM:
158                 return visitor_holder.visitor().start_array_item() ? PARSE_CONTINUE : PARSE_STOP_VISITOR;
159             case MSGPACK_CT_MAP_KEY:
160                 return visitor_holder.visitor().start_map_key() ? PARSE_CONTINUE : PARSE_STOP_VISITOR;
161             case MSGPACK_CT_MAP_VALUE:
162                 assert(0);
163                 return PARSE_STOP_VISITOR;
164             }
165             assert(0);
166             return PARSE_STOP_VISITOR;
167         }
168         parse_return consume(VisitorHolder& visitor_holder, char const*& current) {
169             while (!m_stack.empty()) {
170                 stack_elem& e = m_stack.back();
171                 switch (e.m_type) {
172                 case MSGPACK_CT_ARRAY_ITEM:
173                     if (!visitor_holder.visitor().end_array_item()) {
174                         --current;
175                         return PARSE_STOP_VISITOR;
176                     }
177                     if (--e.m_rest == 0)  {
178                         m_stack.pop_back();
179                         if (!visitor_holder.visitor().end_array()) {
180                             --current;
181                             return PARSE_STOP_VISITOR;
182                         }
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()) {
191                         --current;
192                         return PARSE_STOP_VISITOR;
193                     }
194                     if (!visitor_holder.visitor().start_map_value()) return PARSE_STOP_VISITOR;
195                     e.m_type = MSGPACK_CT_MAP_VALUE;
196                     return PARSE_CONTINUE;
197                 case MSGPACK_CT_MAP_VALUE:
198                     if (!visitor_holder.visitor().end_map_value()) {
199                         --current;
200                         return PARSE_STOP_VISITOR;
201                     }
202                     if (--e.m_rest == 0) {
203                         m_stack.pop_back();
204                         if (!visitor_holder.visitor().end_map()) {
205                             --current;
206                             return PARSE_STOP_VISITOR;
207                         }
208                     }
209                     else {
210                         e.m_type = MSGPACK_CT_MAP_KEY;
211                         if (!visitor_holder.visitor().start_map_key()) return PARSE_STOP_VISITOR;
212                         return PARSE_CONTINUE;
213                     }
214                     break;
215                 }
216             }
217             return PARSE_SUCCESS;
218         }
219         bool empty() const { return m_stack.empty(); }
220         void clear() { m_stack.clear(); }
221     private:
222         std::vector<stack_elem> m_stack;
223     };
224 
225     char const* m_start;
226     char const* m_current;
227 
228     std::size_t m_trail;
229     uint32_t m_cs;
230     uint32_t m_num_elements;
231     unpack_stack m_stack;
232 };
233 
234 template <std::size_t N>
235 inline void check_ext_size(std::size_t /*size*/) {
236 }
237 
238 template <>
239 inline void check_ext_size<4>(std::size_t size) {
240     if (size == 0xffffffff) throw msgpack::ext_size_overflow("ext size overflow");
241 }
242 
243 template <typename VisitorHolder>
244 inline parse_return context<VisitorHolder>::execute(const char* data, std::size_t len, std::size_t& off)
245 {
246     assert(len >= off);
247 
248     m_start = data;
249     m_current = data + off;
250     const char* const pe = data + len;
251     const char* n = MSGPACK_NULLPTR;
252 
253     msgpack::object obj;
254 
255     if(m_current == pe) {
256         off = m_current - m_start;
257         return PARSE_CONTINUE;
258     }
259     bool fixed_trail_again = false;
260     do {
261         if (m_cs == MSGPACK_CS_HEADER) {
262             fixed_trail_again = false;
263             int selector = *reinterpret_cast<const unsigned char*>(m_current);
264             if (0x00 <= selector && selector <= 0x7f) { // Positive Fixnum
265                 uint8_t tmp = *reinterpret_cast<const uint8_t*>(m_current);
266                 bool visret = holder().visitor().visit_positive_integer(tmp);
267                 parse_return upr = after_visit_proc(visret, off);
268                 if (upr != PARSE_CONTINUE) return upr;
269             } else if(0xe0 <= selector && selector <= 0xff) { // Negative Fixnum
270                 int8_t tmp = *reinterpret_cast<const int8_t*>(m_current);
271                 bool visret = holder().visitor().visit_negative_integer(tmp);
272                 parse_return upr = after_visit_proc(visret, off);
273                 if (upr != PARSE_CONTINUE) return upr;
274             } else if (0xc4 <= selector && selector <= 0xdf) {
275                 const uint32_t trail[] = {
276                     1, // bin     8  0xc4
277                     2, // bin    16  0xc5
278                     4, // bin    32  0xc6
279                     1, // ext     8  0xc7
280                     2, // ext    16  0xc8
281                     4, // ext    32  0xc9
282                     4, // float  32  0xca
283                     8, // float  64  0xcb
284                     1, // uint    8  0xcc
285                     2, // uint   16  0xcd
286                     4, // uint   32  0xce
287                     8, // uint   64  0xcf
288                     1, // int     8  0xd0
289                     2, // int    16  0xd1
290                     4, // int    32  0xd2
291                     8, // int    64  0xd3
292                     2, // fixext  1  0xd4
293                     3, // fixext  2  0xd5
294                     5, // fixext  4  0xd6
295                     9, // fixext  8  0xd7
296                     17,// fixext 16  0xd8
297                     1, // str     8  0xd9
298                     2, // str    16  0xda
299                     4, // str    32  0xdb
300                     2, // array  16  0xdc
301                     4, // array  32  0xdd
302                     2, // map    16  0xde
303                     4, // map    32  0xdf
304                 };
305                 m_trail = trail[selector - 0xc4];
306                 m_cs = next_cs(m_current);
307                 fixed_trail_again = true;
308             } else if(0xa0 <= selector && selector <= 0xbf) { // FixStr
309                 m_trail = static_cast<uint32_t>(*m_current) & 0x1f;
310                 if(m_trail == 0) {
311                     bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
312                     parse_return upr = after_visit_proc(visret, off);
313                     if (upr != PARSE_CONTINUE) return upr;
314                 }
315                 else {
316                     m_cs = MSGPACK_ACS_STR_VALUE;
317                     fixed_trail_again = true;
318                 }
319             } else if(0x90 <= selector && selector <= 0x9f) { // FixArray
320                 parse_return ret = start_aggregate<fix_tag>(array_sv(holder()), array_ev(holder()), m_current, off);
321                 if (ret != PARSE_CONTINUE) return ret;
322             } else if(0x80 <= selector && selector <= 0x8f) { // FixMap
323                 parse_return ret = start_aggregate<fix_tag>(map_sv(holder()), map_ev(holder()), m_current, off);
324                 if (ret != PARSE_CONTINUE) return ret;
325             } else if(selector == 0xc2) { // false
326                 bool visret = holder().visitor().visit_boolean(false);
327                 parse_return upr = after_visit_proc(visret, off);
328                 if (upr != PARSE_CONTINUE) return upr;
329             } else if(selector == 0xc3) { // true
330                 bool visret = holder().visitor().visit_boolean(true);
331                 parse_return upr = after_visit_proc(visret, off);
332                 if (upr != PARSE_CONTINUE) return upr;
333             } else if(selector == 0xc0) { // nil
334                 bool visret = holder().visitor().visit_nil();
335                 parse_return upr = after_visit_proc(visret, off);
336                 if (upr != PARSE_CONTINUE) return upr;
337             } else {
338                 off = m_current - m_start;
339                 holder().visitor().parse_error(off - 1, off);
340                 return PARSE_PARSE_ERROR;
341             }
342             // end MSGPACK_CS_HEADER
343         }
344         if (m_cs != MSGPACK_CS_HEADER || fixed_trail_again) {
345             if (fixed_trail_again) {
346                 ++m_current;
347                 fixed_trail_again = false;
348             }
349             if(static_cast<std::size_t>(pe - m_current) < m_trail) {
350                 off = m_current - m_start;
351                 return PARSE_CONTINUE;
352             }
353             n = m_current;
354             m_current += m_trail - 1;
355             switch(m_cs) {
356                 //case MSGPACK_CS_
357                 //case MSGPACK_CS_
358             case MSGPACK_CS_FLOAT: {
359                 union { uint32_t i; float f; } mem;
360                 load<uint32_t>(mem.i, n);
361                 bool visret = holder().visitor().visit_float32(mem.f);
362                 parse_return upr = after_visit_proc(visret, off);
363                 if (upr != PARSE_CONTINUE) return upr;
364             } break;
365             case MSGPACK_CS_DOUBLE: {
366                 union { uint64_t i; double f; } mem;
367                 load<uint64_t>(mem.i, n);
368 #if defined(TARGET_OS_IPHONE)
369                 // ok
370 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
371                 // https://github.com/msgpack/msgpack-perl/pull/1
372                 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
373 #endif
374                 bool visret = holder().visitor().visit_float64(mem.f);
375                 parse_return upr = after_visit_proc(visret, off);
376                 if (upr != PARSE_CONTINUE) return upr;
377             } break;
378             case MSGPACK_CS_UINT_8: {
379                 uint8_t tmp;
380                 load<uint8_t>(tmp, n);
381                 bool visret = holder().visitor().visit_positive_integer(tmp);
382                 parse_return upr = after_visit_proc(visret, off);
383                 if (upr != PARSE_CONTINUE) return upr;
384             } break;
385             case MSGPACK_CS_UINT_16: {
386                 uint16_t tmp;
387                 load<uint16_t>(tmp, n);
388                 bool visret = holder().visitor().visit_positive_integer(tmp);
389                 parse_return upr = after_visit_proc(visret, off);
390                 if (upr != PARSE_CONTINUE) return upr;
391             } break;
392             case MSGPACK_CS_UINT_32: {
393                 uint32_t tmp;
394                 load<uint32_t>(tmp, n);
395                 bool visret = holder().visitor().visit_positive_integer(tmp);
396                 parse_return upr = after_visit_proc(visret, off);
397                 if (upr != PARSE_CONTINUE) return upr;
398             } break;
399             case MSGPACK_CS_UINT_64: {
400                 uint64_t tmp;
401                 load<uint64_t>(tmp, n);
402                 bool visret = holder().visitor().visit_positive_integer(tmp);
403                 parse_return upr = after_visit_proc(visret, off);
404                 if (upr != PARSE_CONTINUE) return upr;
405             } break;
406             case MSGPACK_CS_INT_8: {
407                 int8_t tmp;
408                 load<int8_t>(tmp, n);
409                 bool visret = holder().visitor().visit_negative_integer(tmp);
410                 parse_return upr = after_visit_proc(visret, off);
411                 if (upr != PARSE_CONTINUE) return upr;
412             } break;
413             case MSGPACK_CS_INT_16: {
414                 int16_t tmp;
415                 load<int16_t>(tmp, n);
416                 bool visret = holder().visitor().visit_negative_integer(tmp);
417                 parse_return upr = after_visit_proc(visret, off);
418                 if (upr != PARSE_CONTINUE) return upr;
419             } break;
420             case MSGPACK_CS_INT_32: {
421                 int32_t tmp;
422                 load<int32_t>(tmp, n);
423                 bool visret = holder().visitor().visit_negative_integer(tmp);
424                 parse_return upr = after_visit_proc(visret, off);
425                 if (upr != PARSE_CONTINUE) return upr;
426             } break;
427             case MSGPACK_CS_INT_64: {
428                 int64_t tmp;
429                 load<int64_t>(tmp, n);
430                 bool visret = holder().visitor().visit_negative_integer(tmp);
431                 parse_return upr = after_visit_proc(visret, off);
432                 if (upr != PARSE_CONTINUE) return upr;
433             } break;
434             case MSGPACK_CS_FIXEXT_1: {
435                 bool visret = holder().visitor().visit_ext(n, 1+1);
436                 parse_return upr = after_visit_proc(visret, off);
437                 if (upr != PARSE_CONTINUE) return upr;
438             } break;
439             case MSGPACK_CS_FIXEXT_2: {
440                 bool visret = holder().visitor().visit_ext(n, 2+1);
441                 parse_return upr = after_visit_proc(visret, off);
442                 if (upr != PARSE_CONTINUE) return upr;
443             } break;
444             case MSGPACK_CS_FIXEXT_4: {
445                 bool visret = holder().visitor().visit_ext(n, 4+1);
446                 parse_return upr = after_visit_proc(visret, off);
447                 if (upr != PARSE_CONTINUE) return upr;
448             } break;
449             case MSGPACK_CS_FIXEXT_8: {
450                 bool visret = holder().visitor().visit_ext(n, 8+1);
451                 parse_return upr = after_visit_proc(visret, off);
452                 if (upr != PARSE_CONTINUE) return upr;
453             } break;
454             case MSGPACK_CS_FIXEXT_16: {
455                 bool visret = holder().visitor().visit_ext(n, 16+1);
456                 parse_return upr = after_visit_proc(visret, off);
457                 if (upr != PARSE_CONTINUE) return upr;
458             } break;
459             case MSGPACK_CS_STR_8: {
460                 uint8_t tmp;
461                 load<uint8_t>(tmp, n);
462                 m_trail = tmp;
463                 if(m_trail == 0) {
464                     bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
465                     parse_return upr = after_visit_proc(visret, off);
466                     if (upr != PARSE_CONTINUE) return upr;
467                 }
468                 else {
469                     m_cs = MSGPACK_ACS_STR_VALUE;
470                     fixed_trail_again = true;
471                 }
472             } break;
473             case MSGPACK_CS_BIN_8: {
474                 uint8_t tmp;
475                 load<uint8_t>(tmp, n);
476                 m_trail = tmp;
477                 if(m_trail == 0) {
478                     bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
479                     parse_return upr = after_visit_proc(visret, off);
480                     if (upr != PARSE_CONTINUE) return upr;
481                 }
482                 else {
483                     m_cs = MSGPACK_ACS_BIN_VALUE;
484                     fixed_trail_again = true;
485                 }
486             } break;
487             case MSGPACK_CS_EXT_8: {
488                 uint8_t tmp;
489                 load<uint8_t>(tmp, n);
490                 m_trail = tmp + 1;
491                 if(m_trail == 0) {
492                     bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
493                     parse_return upr = after_visit_proc(visret, off);
494                     if (upr != PARSE_CONTINUE) return upr;
495                 }
496                 else {
497                     m_cs = MSGPACK_ACS_EXT_VALUE;
498                     fixed_trail_again = true;
499                 }
500             } break;
501             case MSGPACK_CS_STR_16: {
502                 uint16_t tmp;
503                 load<uint16_t>(tmp, n);
504                 m_trail = tmp;
505                 if(m_trail == 0) {
506                     bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
507                     parse_return upr = after_visit_proc(visret, off);
508                     if (upr != PARSE_CONTINUE) return upr;
509                 }
510                 else {
511                     m_cs = MSGPACK_ACS_STR_VALUE;
512                     fixed_trail_again = true;
513                 }
514             } break;
515             case MSGPACK_CS_BIN_16: {
516                 uint16_t tmp;
517                 load<uint16_t>(tmp, n);
518                 m_trail = tmp;
519                 if(m_trail == 0) {
520                     bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
521                     parse_return upr = after_visit_proc(visret, off);
522                     if (upr != PARSE_CONTINUE) return upr;
523                 }
524                 else {
525                     m_cs = MSGPACK_ACS_BIN_VALUE;
526                     fixed_trail_again = true;
527                 }
528             } break;
529             case MSGPACK_CS_EXT_16: {
530                 uint16_t tmp;
531                 load<uint16_t>(tmp, n);
532                 m_trail = tmp + 1;
533                 if(m_trail == 0) {
534                     bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
535                     parse_return upr = after_visit_proc(visret, off);
536                     if (upr != PARSE_CONTINUE) return upr;
537                 }
538                 else {
539                     m_cs = MSGPACK_ACS_EXT_VALUE;
540                     fixed_trail_again = true;
541                 }
542             } break;
543             case MSGPACK_CS_STR_32: {
544                 uint32_t tmp;
545                 load<uint32_t>(tmp, n);
546                 m_trail = tmp;
547                 if(m_trail == 0) {
548                     bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
549                     parse_return upr = after_visit_proc(visret, off);
550                     if (upr != PARSE_CONTINUE) return upr;
551                 }
552                 else {
553                     m_cs = MSGPACK_ACS_STR_VALUE;
554                     fixed_trail_again = true;
555                 }
556             } break;
557             case MSGPACK_CS_BIN_32: {
558                 uint32_t tmp;
559                 load<uint32_t>(tmp, n);
560                 m_trail = tmp;
561                 if(m_trail == 0) {
562                     bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
563                     parse_return upr = after_visit_proc(visret, off);
564                     if (upr != PARSE_CONTINUE) return upr;
565                 }
566                 else {
567                     m_cs = MSGPACK_ACS_BIN_VALUE;
568                     fixed_trail_again = true;
569                 }
570             } break;
571             case MSGPACK_CS_EXT_32: {
572                 uint32_t tmp;
573                 load<uint32_t>(tmp, n);
574                 check_ext_size<sizeof(std::size_t)>(tmp);
575                 m_trail = tmp;
576                 ++m_trail;
577                 if(m_trail == 0) {
578                     bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
579                     parse_return upr = after_visit_proc(visret, off);
580                     if (upr != PARSE_CONTINUE) return upr;
581                 }
582                 else {
583                     m_cs = MSGPACK_ACS_EXT_VALUE;
584                     fixed_trail_again = true;
585                 }
586             } break;
587             case MSGPACK_ACS_STR_VALUE: {
588                 bool visret = holder().visitor().visit_str(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_ACS_BIN_VALUE: {
593                 bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
594                 parse_return upr = after_visit_proc(visret, off);
595                 if (upr != PARSE_CONTINUE) return upr;
596             } break;
597             case MSGPACK_ACS_EXT_VALUE: {
598                 bool visret = holder().visitor().visit_ext(n, static_cast<uint32_t>(m_trail));
599                 parse_return upr = after_visit_proc(visret, off);
600                 if (upr != PARSE_CONTINUE) return upr;
601             } break;
602             case MSGPACK_CS_ARRAY_16: {
603                 parse_return ret = start_aggregate<uint16_t>(array_sv(holder()), array_ev(holder()), n, off);
604                 if (ret != PARSE_CONTINUE) return ret;
605 
606             } break;
607             case MSGPACK_CS_ARRAY_32: {
608                 parse_return ret = start_aggregate<uint32_t>(array_sv(holder()), array_ev(holder()), n, off);
609                 if (ret != PARSE_CONTINUE) return ret;
610             } break;
611             case MSGPACK_CS_MAP_16: {
612                 parse_return ret = start_aggregate<uint16_t>(map_sv(holder()), map_ev(holder()), n, off);
613                 if (ret != PARSE_CONTINUE) return ret;
614             } break;
615             case MSGPACK_CS_MAP_32: {
616                 parse_return ret = start_aggregate<uint32_t>(map_sv(holder()), map_ev(holder()), n, off);
617                 if (ret != PARSE_CONTINUE) return ret;
618             } break;
619             default:
620                 off = m_current - m_start;
621                 holder().visitor().parse_error(n - m_start - 1, n - m_start);
622                 return PARSE_PARSE_ERROR;
623             }
624         }
625     } while(m_current != pe);
626 
627     off = m_current - m_start;
628     return PARSE_CONTINUE;
629 }
630 
631 template <typename Visitor>
632 struct parse_helper : detail::context<parse_helper<Visitor> > {
633     parse_helper(Visitor& v):m_visitor(v) {}
634     parse_return execute(const char* data, std::size_t len, std::size_t& off) {
635         return detail::context<parse_helper<Visitor> >::execute(data, len, off);
636     }
637     Visitor& visitor() const { return m_visitor; }
638     Visitor& m_visitor;
639 };
640 
641 template <typename Visitor>
642 inline parse_return
643 parse_imp(const char* data, size_t len, size_t& off, Visitor& v) {
644     std::size_t noff = off;
645     if(len <= noff) {
646         // FIXME
647         v.insufficient_bytes(noff, noff);
648         return PARSE_CONTINUE;
649     }
650     detail::parse_helper<Visitor> h(v);
651     parse_return ret = h.execute(data, len, noff);
652     off = noff;
653     switch (ret) {
654     case PARSE_CONTINUE:
655         v.insufficient_bytes(noff - 1, noff);
656         return ret;
657     case PARSE_SUCCESS:
658         if(noff < len) {
659             return PARSE_EXTRA_BYTES;
660         }
661         return ret;
662     default:
663         return ret;
664     }
665 }
666 
667 } // detail
668 
669 /// @cond
670 }  // MSGPACK_API_VERSION_NAMESPACE(v3)
671 /// @endcond
672 
673 }  // namespace msgpack
674 
675 #endif // MSGPACK_DEFAULT_API_VERSION >= 2
676 
677 #endif // MSGPACK_V3_PARSE_HPP
678