Coverage Report

Created: 2023-09-25 06:13

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