Coverage Report

Created: 2026-09-11 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/msgpack-c/include/msgpack/v1/unpack.hpp
Line
Count
Source
1
//
2
// MessagePack for C++ deserializing routine
3
//
4
// Copyright (C) 2008-2016 FURUHASHI Sadayuki and 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_V1_UNPACK_HPP
11
#define MSGPACK_V1_UNPACK_HPP
12
13
#include "msgpack/versioning.hpp"
14
#include "msgpack/unpack_decl.hpp"
15
#include "msgpack/object.hpp"
16
#include "msgpack/zone.hpp"
17
#include "msgpack/unpack_exception.hpp"
18
#include "msgpack/unpack_define.hpp"
19
#include "msgpack/cpp_config.hpp"
20
#include "msgpack/sysdep.hpp"
21
#include "msgpack/assert.hpp"
22
23
#include <memory>
24
#include <limits>
25
26
27
#if !defined(MSGPACK_USE_CPP03)
28
#include <atomic>
29
#endif
30
31
#if defined(_MSC_VER)
32
// avoiding confliction std::max, std::min, and macro in windows.h
33
#ifndef NOMINMAX
34
#define NOMINMAX
35
#endif
36
#endif // defined(_MSC_VER)
37
38
namespace msgpack {
39
40
/// @cond
41
MSGPACK_API_VERSION_NAMESPACE(v1) {
42
/// @endcond
43
44
namespace detail {
45
46
class unpack_user {
47
public:
48
    unpack_user(unpack_reference_func f = MSGPACK_NULLPTR,
49
                void* user_data = MSGPACK_NULLPTR,
50
                unpack_limit const& limit = unpack_limit())
51
0
        :m_func(f), m_user_data(user_data), m_limit(limit) {}
52
0
    msgpack::zone const& zone() const { return *m_zone; }
53
0
    msgpack::zone& zone() { return *m_zone; }
54
0
    void set_zone(msgpack::zone& zone) { m_zone = &zone; }
55
0
    bool referenced() const { return m_referenced; }
56
0
    void set_referenced(bool referenced) { m_referenced = referenced; }
57
0
    unpack_reference_func reference_func() const { return m_func; }
58
0
    void* user_data() const { return m_user_data; }
59
0
    unpack_limit const& limit() const { return m_limit; }
60
0
    unpack_limit& limit() { return m_limit; }
61
62
private:
63
    msgpack::zone* m_zone;
64
    bool m_referenced;
65
    unpack_reference_func m_func;
66
    void* m_user_data;
67
    unpack_limit m_limit;
68
};
69
70
inline void unpack_uint8(uint8_t d, msgpack::object& o)
71
0
{ o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
72
73
inline void unpack_uint16(uint16_t d, msgpack::object& o)
74
0
{ o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
75
76
inline void unpack_uint32(uint32_t d, msgpack::object& o)
77
0
{ o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
78
79
inline void unpack_uint64(uint64_t d, msgpack::object& o)
80
0
{ o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = d; }
81
82
inline void unpack_int8(int8_t d, msgpack::object& o)
83
0
{ if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = static_cast<uint64_t>(d); }
84
0
        else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
85
86
inline void unpack_int16(int16_t d, msgpack::object& o)
87
0
{ if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = static_cast<uint64_t>(d); }
88
0
        else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
89
90
inline void unpack_int32(int32_t d, msgpack::object& o)
91
0
{ if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = static_cast<uint64_t>(d); }
92
0
        else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
93
94
inline void unpack_int64(int64_t d, msgpack::object& o)
95
0
{ if(d >= 0) { o.type = msgpack::type::POSITIVE_INTEGER; o.via.u64 = static_cast<uint64_t>(d); }
96
0
        else { o.type = msgpack::type::NEGATIVE_INTEGER; o.via.i64 = d; } }
97
98
inline void unpack_float(float d, msgpack::object& o)
99
0
{ o.type = msgpack::type::FLOAT32; o.via.f64 = d; }
100
101
inline void unpack_double(double d, msgpack::object& o)
102
0
{ o.type = msgpack::type::FLOAT64; o.via.f64 = d; }
103
104
inline void unpack_nil(msgpack::object& o)
105
0
{ o.type = msgpack::type::NIL; }
106
107
inline void unpack_true(msgpack::object& o)
108
0
{ o.type = msgpack::type::BOOLEAN; o.via.boolean = true; }
109
110
inline void unpack_false(msgpack::object& o)
111
0
{ o.type = msgpack::type::BOOLEAN; o.via.boolean = false; }
112
113
struct unpack_array {
114
0
    void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
115
0
        if (n > u.limit().array()) throw msgpack::array_size_overflow("array size overflow");
116
0
        o.type = msgpack::type::ARRAY;
117
0
        o.via.array.size = 0;
118
0
119
0
#if SIZE_MAX == UINT_MAX
120
0
        if (n > SIZE_MAX/sizeof(msgpack::object))
121
0
            throw msgpack::array_size_overflow("array size overflow");
122
0
#endif // SIZE_MAX == UINT_MAX
123
0
124
0
        size_t size = n*sizeof(msgpack::object);
125
0
        o.via.array.ptr = static_cast<msgpack::object*>(u.zone().allocate_align(size, MSGPACK_ZONE_ALIGNOF(msgpack::object)));
126
0
    }
127
};
128
129
inline void unpack_array_item(msgpack::object& c, msgpack::object const& o)
130
0
{
131
0
#if defined(__GNUC__) && !defined(__clang__)
132
0
    std::memcpy(&c.via.array.ptr[c.via.array.size++], &o, sizeof(msgpack::object));
133
0
134
0
#else  /* __GNUC__ && !__clang__ */
135
0
    c.via.array.ptr[c.via.array.size++] = o;
136
0
#endif /* __GNUC__ && !__clang__ */
137
0
}
138
139
struct unpack_map {
140
0
    void operator()(unpack_user& u, uint32_t n, msgpack::object& o) const {
141
0
        if (n > u.limit().map()) throw msgpack::map_size_overflow("map size overflow");
142
0
        o.type = msgpack::type::MAP;
143
0
        o.via.map.size = 0;
144
0
145
0
#if SIZE_MAX == UINT_MAX
146
0
        if (n > SIZE_MAX/sizeof(msgpack::object_kv))
147
0
            throw msgpack::map_size_overflow("map size overflow");
148
0
#endif // SIZE_MAX == UINT_MAX
149
0
150
0
        size_t size = n*sizeof(msgpack::object_kv);
151
0
        o.via.map.ptr = static_cast<msgpack::object_kv*>(u.zone().allocate_align(size, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv)));
152
0
    }
153
};
154
155
inline void unpack_map_item(msgpack::object& c, msgpack::object const& k, msgpack::object const& v)
156
0
{
157
0
#if defined(__GNUC__) && !defined(__clang__)
158
0
    std::memcpy(&c.via.map.ptr[c.via.map.size].key, &k, sizeof(msgpack::object));
159
0
    std::memcpy(&c.via.map.ptr[c.via.map.size].val, &v, sizeof(msgpack::object));
160
0
#else  /* __GNUC__ && !__clang__ */
161
0
    c.via.map.ptr[c.via.map.size].key = k;
162
0
    c.via.map.ptr[c.via.map.size].val = v;
163
0
#endif /* __GNUC__ && !__clang__ */
164
0
    ++c.via.map.size;
165
0
}
166
167
inline void unpack_str(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
168
0
{
169
0
    o.type = msgpack::type::STR;
170
0
    if (l > u.limit().str()) throw msgpack::str_size_overflow("str size overflow");
171
0
    if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
172
0
        o.via.str.ptr = p;
173
0
        u.set_referenced(true);
174
0
    }
175
0
    else if (l > 0) {
176
0
        char* tmp = static_cast<char*>(u.zone().allocate_align(l, MSGPACK_ZONE_ALIGNOF(char)));
177
0
        std::memcpy(tmp, p, l);
178
0
        o.via.str.ptr = tmp;
179
0
    }
180
0
    else {
181
0
        o.via.str.ptr = MSGPACK_NULLPTR;
182
0
    }
183
0
    o.via.str.size = l;
184
0
}
185
186
inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, msgpack::object& o)
187
0
{
188
0
    o.type = msgpack::type::BIN;
189
0
    if (l > u.limit().bin()) throw msgpack::bin_size_overflow("bin size overflow");
190
0
    if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
191
0
        o.via.bin.ptr = p;
192
0
        u.set_referenced(true);
193
0
    }
194
0
    else if (l > 0) {
195
0
        char* tmp = static_cast<char*>(u.zone().allocate_align(l, MSGPACK_ZONE_ALIGNOF(char)));
196
0
        std::memcpy(tmp, p, l);
197
0
        o.via.bin.ptr = tmp;
198
0
    }
199
0
    else {
200
0
        o.via.bin.ptr = MSGPACK_NULLPTR;
201
0
    }
202
0
    o.via.bin.size = l;
203
0
}
204
205
inline void unpack_ext(unpack_user& u, const char* p, std::size_t l, msgpack::object& o)
206
0
{
207
0
    o.type = msgpack::type::EXT;
208
0
    if (l > u.limit().ext()) throw msgpack::ext_size_overflow("ext size overflow");
209
0
    if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
210
0
        o.via.ext.ptr = p;
211
0
        u.set_referenced(true);
212
0
    }
213
0
    else {
214
0
        char* tmp = static_cast<char*>(u.zone().allocate_align(l, MSGPACK_ZONE_ALIGNOF(char)));
215
0
        std::memcpy(tmp, p, l);
216
0
        o.via.ext.ptr = tmp;
217
0
    }
218
0
    o.via.ext.size = static_cast<uint32_t>(l - 1);
219
0
}
220
221
222
class unpack_stack {
223
public:
224
0
    msgpack::object const& obj() const { return m_obj; }
225
0
    msgpack::object& obj() { return m_obj; }
226
0
    void set_obj(msgpack::object const& obj) { m_obj = obj; }
227
0
    std::size_t count() const { return m_count; }
228
0
    void set_count(std::size_t count) { m_count = count; }
229
0
    std::size_t decr_count() { return --m_count; }
230
0
    uint32_t container_type() const { return m_container_type; }
231
0
    void set_container_type(uint32_t container_type) { m_container_type = container_type; }
232
0
    msgpack::object const& map_key() const { return m_map_key; }
233
0
    void set_map_key(msgpack::object const& map_key) { m_map_key = map_key; }
234
private:
235
    msgpack::object m_obj;
236
    std::size_t m_count;
237
    uint32_t m_container_type;
238
    msgpack::object m_map_key;
239
};
240
241
inline void init_count(void* buffer)
242
0
{
243
0
#if defined(MSGPACK_USE_CPP03)
244
0
    *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer) = 1;
245
0
#else  // defined(MSGPACK_USE_CPP03)
246
0
    new (buffer) std::atomic<unsigned int>(1);
247
0
#endif // defined(MSGPACK_USE_CPP03)
248
0
}
249
250
inline void decr_count(void* buffer)
251
0
{
252
0
#if defined(MSGPACK_USE_CPP03)
253
0
    if(_msgpack_sync_decr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer)) == 0) {
254
0
        free(buffer);
255
0
    }
256
0
#else  // defined(MSGPACK_USE_CPP03)
257
0
    if (--*reinterpret_cast<std::atomic<unsigned int>*>(buffer) == 0) {
258
0
        free(buffer);
259
0
    }
260
0
#endif // defined(MSGPACK_USE_CPP03)
261
0
}
262
263
inline void incr_count(void* buffer)
264
0
{
265
0
#if defined(MSGPACK_USE_CPP03)
266
0
    _msgpack_sync_incr_and_fetch(reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer));
267
0
#else  // defined(MSGPACK_USE_CPP03)
268
0
    ++*reinterpret_cast<std::atomic<unsigned int>*>(buffer);
269
0
#endif // defined(MSGPACK_USE_CPP03)
270
0
}
271
272
#if defined(MSGPACK_USE_CPP03)
273
inline _msgpack_atomic_counter_t get_count(void* buffer)
274
{
275
    return *reinterpret_cast<volatile _msgpack_atomic_counter_t*>(buffer);
276
}
277
#else  // defined(MSGPACK_USE_CPP03)
278
inline std::atomic<unsigned int> const& get_count(void* buffer)
279
0
{
280
0
    return *reinterpret_cast<std::atomic<unsigned int>*>(buffer);
281
0
}
282
#endif // defined(MSGPACK_USE_CPP03)
283
284
template <typename T>
285
struct value {
286
    typedef T type;
287
};
288
template <>
289
struct value<fix_tag> {
290
    typedef uint32_t type;
291
};
292
293
template <typename T>
294
655k
inline typename msgpack::enable_if<sizeof(T) == sizeof(fix_tag)>::type load(uint32_t& dst, const char* n) {
295
655k
    dst = static_cast<uint32_t>(*reinterpret_cast<const uint8_t*>(n)) & 0x0f;
296
655k
}
297
298
template <typename T>
299
120k
inline typename msgpack::enable_if<sizeof(T) == 1>::type load(T& dst, const char* n) {
300
120k
    dst = static_cast<T>(*reinterpret_cast<const uint8_t*>(n));
301
120k
}
std::__1::enable_if<(sizeof (unsigned char))==(1), void>::type msgpack::v1::detail::load<unsigned char>(unsigned char&, char const*)
Line
Count
Source
299
36.0k
inline typename msgpack::enable_if<sizeof(T) == 1>::type load(T& dst, const char* n) {
300
36.0k
    dst = static_cast<T>(*reinterpret_cast<const uint8_t*>(n));
301
36.0k
}
std::__1::enable_if<(sizeof (signed char))==(1), void>::type msgpack::v1::detail::load<signed char>(signed char&, char const*)
Line
Count
Source
299
84.6k
inline typename msgpack::enable_if<sizeof(T) == 1>::type load(T& dst, const char* n) {
300
84.6k
    dst = static_cast<T>(*reinterpret_cast<const uint8_t*>(n));
301
84.6k
}
302
303
template <typename T>
304
83.2k
inline typename msgpack::enable_if<sizeof(T) == 2>::type load(T& dst, const char* n) {
305
83.2k
    _msgpack_load16(T, n, &dst);
306
83.2k
}
std::__1::enable_if<(sizeof (unsigned short))==(2), void>::type msgpack::v1::detail::load<unsigned short>(unsigned short&, char const*)
Line
Count
Source
304
53.8k
inline typename msgpack::enable_if<sizeof(T) == 2>::type load(T& dst, const char* n) {
305
    _msgpack_load16(T, n, &dst);
306
53.8k
}
std::__1::enable_if<(sizeof (short))==(2), void>::type msgpack::v1::detail::load<short>(short&, char const*)
Line
Count
Source
304
29.4k
inline typename msgpack::enable_if<sizeof(T) == 2>::type load(T& dst, const char* n) {
305
    _msgpack_load16(T, n, &dst);
306
29.4k
}
307
308
template <typename T>
309
626k
inline typename msgpack::enable_if<sizeof(T) == 4>::type load(T& dst, const char* n) {
310
626k
    _msgpack_load32(T, n, &dst);
311
626k
}
std::__1::enable_if<(sizeof (unsigned int))==(4), void>::type msgpack::v1::detail::load<unsigned int>(unsigned int&, char const*)
Line
Count
Source
309
589k
inline typename msgpack::enable_if<sizeof(T) == 4>::type load(T& dst, const char* n) {
310
    _msgpack_load32(T, n, &dst);
311
589k
}
std::__1::enable_if<(sizeof (int))==(4), void>::type msgpack::v1::detail::load<int>(int&, char const*)
Line
Count
Source
309
36.3k
inline typename msgpack::enable_if<sizeof(T) == 4>::type load(T& dst, const char* n) {
310
    _msgpack_load32(T, n, &dst);
311
36.3k
}
312
313
template <typename T>
314
48.4k
inline typename msgpack::enable_if<sizeof(T) == 8>::type load(T& dst, const char* n) {
315
48.4k
    _msgpack_load64(T, n, &dst);
316
48.4k
}
std::__1::enable_if<(sizeof (unsigned long))==(8), void>::type msgpack::v1::detail::load<unsigned long>(unsigned long&, char const*)
Line
Count
Source
314
21.7k
inline typename msgpack::enable_if<sizeof(T) == 8>::type load(T& dst, const char* n) {
315
    _msgpack_load64(T, n, &dst);
316
21.7k
}
std::__1::enable_if<(sizeof (long))==(8), void>::type msgpack::v1::detail::load<long>(long&, char const*)
Line
Count
Source
314
26.7k
inline typename msgpack::enable_if<sizeof(T) == 8>::type load(T& dst, const char* n) {
315
    _msgpack_load64(T, n, &dst);
316
26.7k
}
317
318
class context {
319
public:
320
    context(unpack_reference_func f, void* user_data, unpack_limit const& limit)
321
        :m_trail(0), m_user(f, user_data, limit), m_cs(MSGPACK_CS_HEADER)
322
0
    {
323
0
        m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
324
0
        m_stack.push_back(unpack_stack());
325
0
    }
326
327
    void init()
328
0
    {
329
0
        m_cs = MSGPACK_CS_HEADER;
330
0
        m_trail = 0;
331
0
        m_stack.resize(1);
332
0
        m_stack[0].set_obj(msgpack::object());
333
0
    }
334
335
    msgpack::object const& data() const
336
0
    {
337
0
        return m_stack[0].obj();
338
0
    }
339
340
    unpack_user& user()
341
0
    {
342
0
        return m_user;
343
0
    }
344
345
    unpack_user const& user() const
346
0
    {
347
0
        return m_user;
348
0
    }
349
350
    int execute(const char* data, std::size_t len, std::size_t& off);
351
352
private:
353
    template <typename T>
354
    static uint32_t next_cs(T p)
355
0
    {
356
0
        return static_cast<uint32_t>(*p) & 0x1f;
357
0
    }
358
359
    template <typename T, typename Func>
360
    int push_aggregate(
361
        Func const& f,
362
        uint32_t container_type,
363
        msgpack::object& obj,
364
        const char* load_pos,
365
0
        std::size_t& off) {
366
0
        typename value<T>::type tmp;
367
0
        load<T>(tmp, load_pos);
368
0
        f(m_user, tmp, m_stack.back().obj());
369
0
        if(tmp == 0) {
370
0
            obj = m_stack.back().obj();
371
0
            int ret = push_proc(obj, off);
372
0
            if (ret != 0) return ret;
373
0
        }
374
0
        else {
375
0
            m_stack.back().set_container_type(container_type);
376
0
            m_stack.back().set_count(tmp);
377
0
            if (m_stack.size() <= m_user.limit().depth()) {
378
0
                m_stack.push_back(unpack_stack());
379
0
            }
380
0
            else {
381
0
                throw msgpack::depth_size_overflow("depth size overflow");
382
0
            }
383
0
            m_cs = MSGPACK_CS_HEADER;
384
0
            ++m_current;
385
0
        }
386
0
        return 0;
387
0
    }
Unexecuted instantiation: int msgpack::v1::detail::context::push_aggregate<msgpack::v1::detail::fix_tag, msgpack::v1::detail::unpack_array>(msgpack::v1::detail::unpack_array const&, unsigned int, msgpack::v2::object&, char const*, unsigned long&)
Unexecuted instantiation: int msgpack::v1::detail::context::push_aggregate<msgpack::v1::detail::fix_tag, msgpack::v1::detail::unpack_map>(msgpack::v1::detail::unpack_map const&, unsigned int, msgpack::v2::object&, char const*, unsigned long&)
Unexecuted instantiation: int msgpack::v1::detail::context::push_aggregate<unsigned short, msgpack::v1::detail::unpack_array>(msgpack::v1::detail::unpack_array const&, unsigned int, msgpack::v2::object&, char const*, unsigned long&)
Unexecuted instantiation: int msgpack::v1::detail::context::push_aggregate<unsigned int, msgpack::v1::detail::unpack_array>(msgpack::v1::detail::unpack_array const&, unsigned int, msgpack::v2::object&, char const*, unsigned long&)
Unexecuted instantiation: int msgpack::v1::detail::context::push_aggregate<unsigned short, msgpack::v1::detail::unpack_map>(msgpack::v1::detail::unpack_map const&, unsigned int, msgpack::v2::object&, char const*, unsigned long&)
Unexecuted instantiation: int msgpack::v1::detail::context::push_aggregate<unsigned int, msgpack::v1::detail::unpack_map>(msgpack::v1::detail::unpack_map const&, unsigned int, msgpack::v2::object&, char const*, unsigned long&)
388
389
0
    int push_item(msgpack::object& obj) {
390
0
        bool finish = false;
391
0
        while (!finish) {
392
0
            if(m_stack.size() == 1) {
393
0
                return 1;
394
0
            }
395
0
            unpack_stack& sp = *(m_stack.end() - 2);
396
0
            switch(sp.container_type()) {
397
0
            case MSGPACK_CT_ARRAY_ITEM:
398
0
                unpack_array_item(sp.obj(), obj);
399
0
                if(sp.decr_count() == 0) {
400
0
                    obj = sp.obj();
401
0
                    m_stack.pop_back();
402
0
                }
403
0
                else {
404
0
                    finish = true;
405
0
                }
406
0
                break;
407
0
            case MSGPACK_CT_MAP_KEY:
408
0
                sp.set_map_key(obj);
409
0
                sp.set_container_type(MSGPACK_CT_MAP_VALUE);
410
0
                finish = true;
411
0
                break;
412
0
            case MSGPACK_CT_MAP_VALUE:
413
0
                unpack_map_item(sp.obj(), sp.map_key(), obj);
414
0
                if(sp.decr_count() == 0) {
415
0
                    obj = sp.obj();
416
0
                    m_stack.pop_back();
417
0
                }
418
0
                else {
419
0
                    sp.set_container_type(MSGPACK_CT_MAP_KEY);
420
0
                    finish = true;
421
0
                }
422
0
                break;
423
0
            default:
424
0
                return -1;
425
0
            }
426
0
        }
427
0
        return 0;
428
0
    }
429
430
0
    int push_proc(msgpack::object& obj, std::size_t& off) {
431
0
        int ret = push_item(obj);
432
0
        if (ret > 0) {
433
0
            m_stack[0].set_obj(obj);
434
0
            ++m_current;
435
0
            /*printf("-- finish --\n"); */
436
0
            off = static_cast<std::size_t>(m_current - m_start);
437
0
        }
438
0
        else if (ret < 0) {
439
0
            off = static_cast<std::size_t>(m_current - m_start);
440
0
        }
441
0
        else {
442
0
            m_cs = MSGPACK_CS_HEADER;
443
0
            ++m_current;
444
0
        }
445
0
        return ret;
446
0
    }
447
448
    template <std::size_t N>
449
0
    static void check_ext_size(std::size_t /*size*/) {
450
0
    }
451
452
private:
453
    char const* m_start;
454
    char const* m_current;
455
456
    std::size_t m_trail;
457
    unpack_user m_user;
458
    uint32_t m_cs;
459
    std::vector<unpack_stack> m_stack;
460
};
461
462
template <>
463
0
inline void context::check_ext_size<4>(std::size_t size) {
464
0
    if (size == 0xffffffff) throw msgpack::ext_size_overflow("ext size overflow");
465
0
}
466
467
inline int context::execute(const char* data, std::size_t len, std::size_t& off)
468
0
{
469
0
    MSGPACK_ASSERT(len >= off);
470
0
471
0
    m_start = data;
472
0
    m_current = data + off;
473
0
    const char* const pe = data + len;
474
0
    const char* n = MSGPACK_NULLPTR;
475
0
476
0
    msgpack::object obj;
477
0
478
0
    if(m_current == pe) {
479
0
        off = static_cast<std::size_t>(m_current - m_start);
480
0
        return 0;
481
0
    }
482
0
    bool fixed_trail_again = false;
483
0
    do {
484
0
        if (m_cs == MSGPACK_CS_HEADER) {
485
0
            fixed_trail_again = false;
486
0
            int selector = *reinterpret_cast<const unsigned char*>(m_current);
487
0
            if (0x00 <= selector && selector <= 0x7f) { // Positive Fixnum
488
0
                unpack_uint8(*reinterpret_cast<const uint8_t*>(m_current), obj);
489
0
                int ret = push_proc(obj, off);
490
0
                if (ret != 0) return ret;
491
0
            } else if(0xe0 <= selector && selector <= 0xff) { // Negative Fixnum
492
0
                unpack_int8(*reinterpret_cast<const int8_t*>(m_current), obj);
493
0
                int ret = push_proc(obj, off);
494
0
                if (ret != 0) return ret;
495
0
            } else if (0xc4 <= selector && selector <= 0xdf) {
496
0
                const uint32_t trail[] = {
497
0
                    1, // bin     8  0xc4
498
0
                    2, // bin    16  0xc5
499
0
                    4, // bin    32  0xc6
500
0
                    1, // ext     8  0xc7
501
0
                    2, // ext    16  0xc8
502
0
                    4, // ext    32  0xc9
503
0
                    4, // float  32  0xca
504
0
                    8, // float  64  0xcb
505
0
                    1, // uint    8  0xcc
506
0
                    2, // uint   16  0xcd
507
0
                    4, // uint   32  0xce
508
0
                    8, // uint   64  0xcf
509
0
                    1, // int     8  0xd0
510
0
                    2, // int    16  0xd1
511
0
                    4, // int    32  0xd2
512
0
                    8, // int    64  0xd3
513
0
                    2, // fixext  1  0xd4
514
0
                    3, // fixext  2  0xd5
515
0
                    5, // fixext  4  0xd6
516
0
                    9, // fixext  8  0xd7
517
0
                    17,// fixext 16  0xd8
518
0
                    1, // str     8  0xd9
519
0
                    2, // str    16  0xda
520
0
                    4, // str    32  0xdb
521
0
                    2, // array  16  0xdc
522
0
                    4, // array  32  0xdd
523
0
                    2, // map    16  0xde
524
0
                    4, // map    32  0xdf
525
0
                };
526
0
                m_trail = trail[selector - 0xc4];
527
0
                m_cs = next_cs(m_current);
528
0
                fixed_trail_again = true;
529
0
            } else if(0xa0 <= selector && selector <= 0xbf) { // FixStr
530
0
                m_trail = static_cast<uint32_t>(*m_current) & 0x1f;
531
0
                if(m_trail == 0) {
532
0
                    unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
533
0
                    int ret = push_proc(obj, off);
534
0
                    if (ret != 0) return ret;
535
0
                }
536
0
                else {
537
0
                    m_cs = MSGPACK_ACS_STR_VALUE;
538
0
                    fixed_trail_again = true;
539
0
                }
540
0
541
0
            } else if(0x90 <= selector && selector <= 0x9f) { // FixArray
542
0
                int ret = push_aggregate<fix_tag>(
543
0
                    unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, m_current, off);
544
0
                if (ret != 0) return ret;
545
0
            } else if(0x80 <= selector && selector <= 0x8f) { // FixMap
546
0
                int ret = push_aggregate<fix_tag>(
547
0
                    unpack_map(), MSGPACK_CT_MAP_KEY, obj, m_current, off);
548
0
                if (ret != 0) return ret;
549
0
            } else if(selector == 0xc2) { // false
550
0
                unpack_false(obj);
551
0
                int ret = push_proc(obj, off);
552
0
                if (ret != 0) return ret;
553
0
            } else if(selector == 0xc3) { // true
554
0
                unpack_true(obj);
555
0
                int ret = push_proc(obj, off);
556
0
                if (ret != 0) return ret;
557
0
            } else if(selector == 0xc0) { // nil
558
0
                unpack_nil(obj);
559
0
                int ret = push_proc(obj, off);
560
0
                if (ret != 0) return ret;
561
0
            } else {
562
0
                off = static_cast<std::size_t>(m_current - m_start);
563
0
                return -1;
564
0
            }
565
0
            // end MSGPACK_CS_HEADER
566
0
        }
567
0
        if (m_cs != MSGPACK_CS_HEADER || fixed_trail_again) {
568
0
            if (fixed_trail_again) {
569
0
                ++m_current;
570
0
                fixed_trail_again = false;
571
0
            }
572
0
            if(static_cast<std::size_t>(pe - m_current) < m_trail) {
573
0
                off = static_cast<std::size_t>(m_current - m_start);
574
0
                return 0;
575
0
            }
576
0
            n = m_current;
577
0
            m_current += m_trail - 1;
578
0
            switch(m_cs) {
579
0
                //case MSGPACK_CS_
580
0
                //case MSGPACK_CS_
581
0
            case MSGPACK_CS_FLOAT: {
582
0
                union { uint32_t i; float f; } mem;
583
0
                load<uint32_t>(mem.i, n);
584
0
                unpack_float(mem.f, obj);
585
0
                int ret = push_proc(obj, off);
586
0
                if (ret != 0) return ret;
587
0
            } break;
588
0
            case MSGPACK_CS_DOUBLE: {
589
0
                union { uint64_t i; double f; } mem;
590
0
                load<uint64_t>(mem.i, n);
591
0
#if defined(TARGET_OS_IPHONE)
592
0
                // ok
593
0
#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
594
0
                // https://github.com/msgpack/msgpack-perl/pull/1
595
0
                mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
596
0
#endif
597
0
                unpack_double(mem.f, obj);
598
0
                int ret = push_proc(obj, off);
599
0
                if (ret != 0) return ret;
600
0
            } break;
601
0
            case MSGPACK_CS_UINT_8: {
602
0
                uint8_t tmp;
603
0
                load<uint8_t>(tmp, n);
604
0
                unpack_uint8(tmp, obj);
605
0
                int ret = push_proc(obj, off);
606
0
                if (ret != 0) return ret;
607
0
            } break;
608
0
            case MSGPACK_CS_UINT_16: {
609
0
                uint16_t tmp;
610
0
                load<uint16_t>(tmp, n);
611
0
                unpack_uint16(tmp, obj);
612
0
                int ret = push_proc(obj, off);
613
0
                if (ret != 0) return ret;
614
0
            } break;
615
0
            case MSGPACK_CS_UINT_32: {
616
0
                uint32_t tmp;
617
0
                load<uint32_t>(tmp, n);
618
0
                unpack_uint32(tmp, obj);
619
0
                int ret = push_proc(obj, off);
620
0
                if (ret != 0) return ret;
621
0
            } break;
622
0
            case MSGPACK_CS_UINT_64: {
623
0
                uint64_t tmp;
624
0
                load<uint64_t>(tmp, n);
625
0
                unpack_uint64(tmp, obj);
626
0
                int ret = push_proc(obj, off);
627
0
                if (ret != 0) return ret;
628
0
            } break;
629
0
            case MSGPACK_CS_INT_8: {
630
0
                int8_t tmp;
631
0
                load<int8_t>(tmp, n);
632
0
                unpack_int8(tmp, obj);
633
0
                int ret = push_proc(obj, off);
634
0
                if (ret != 0) return ret;
635
0
            } break;
636
0
            case MSGPACK_CS_INT_16: {
637
0
                int16_t tmp;
638
0
                load<int16_t>(tmp, n);
639
0
                unpack_int16(tmp, obj);
640
0
                int ret = push_proc(obj, off);
641
0
                if (ret != 0) return ret;
642
0
            } break;
643
0
            case MSGPACK_CS_INT_32: {
644
0
                int32_t tmp;
645
0
                load<int32_t>(tmp, n);
646
0
                unpack_int32(tmp, obj);
647
0
                int ret = push_proc(obj, off);
648
0
                if (ret != 0) return ret;
649
0
            } break;
650
0
            case MSGPACK_CS_INT_64: {
651
0
                int64_t tmp;
652
0
                load<int64_t>(tmp, n);
653
0
                unpack_int64(tmp, obj);
654
0
                int ret = push_proc(obj, off);
655
0
                if (ret != 0) return ret;
656
0
            } break;
657
0
            case MSGPACK_CS_FIXEXT_1: {
658
0
                unpack_ext(m_user, n, 1+1, obj);
659
0
                int ret = push_proc(obj, off);
660
0
                if (ret != 0) return ret;
661
0
            } break;
662
0
            case MSGPACK_CS_FIXEXT_2: {
663
0
                unpack_ext(m_user, n, 2+1, obj);
664
0
                int ret = push_proc(obj, off);
665
0
                if (ret != 0) return ret;
666
0
            } break;
667
0
            case MSGPACK_CS_FIXEXT_4: {
668
0
                unpack_ext(m_user, n, 4+1, obj);
669
0
                int ret = push_proc(obj, off);
670
0
                if (ret != 0) return ret;
671
0
            } break;
672
0
            case MSGPACK_CS_FIXEXT_8: {
673
0
                unpack_ext(m_user, n, 8+1, obj);
674
0
                int ret = push_proc(obj, off);
675
0
                if (ret != 0) return ret;
676
0
            } break;
677
0
            case MSGPACK_CS_FIXEXT_16: {
678
0
                unpack_ext(m_user, n, 16+1, obj);
679
0
                int ret = push_proc(obj, off);
680
0
                if (ret != 0) return ret;
681
0
            } break;
682
0
            case MSGPACK_CS_STR_8: {
683
0
                uint8_t tmp;
684
0
                load<uint8_t>(tmp, n);
685
0
                m_trail = tmp;
686
0
                if(m_trail == 0) {
687
0
                    unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
688
0
                    int ret = push_proc(obj, off);
689
0
                    if (ret != 0) return ret;
690
0
                }
691
0
                else {
692
0
                    m_cs = MSGPACK_ACS_STR_VALUE;
693
0
                    fixed_trail_again = true;
694
0
                }
695
0
            } break;
696
0
            case MSGPACK_CS_BIN_8: {
697
0
                uint8_t tmp;
698
0
                load<uint8_t>(tmp, n);
699
0
                m_trail = tmp;
700
0
                if(m_trail == 0) {
701
0
                    unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
702
0
                    int ret = push_proc(obj, off);
703
0
                    if (ret != 0) return ret;
704
0
                }
705
0
                else {
706
0
                    m_cs = MSGPACK_ACS_BIN_VALUE;
707
0
                    fixed_trail_again = true;
708
0
                }
709
0
            } break;
710
0
            case MSGPACK_CS_EXT_8: {
711
0
                uint8_t tmp;
712
0
                load<uint8_t>(tmp, n);
713
0
                m_trail = tmp + 1;
714
0
                if(m_trail == 0) {
715
0
                    unpack_ext(m_user, n, m_trail, obj);
716
0
                    int ret = push_proc(obj, off);
717
0
                    if (ret != 0) return ret;
718
0
                }
719
0
                else {
720
0
                    m_cs = MSGPACK_ACS_EXT_VALUE;
721
0
                    fixed_trail_again = true;
722
0
                }
723
0
            } break;
724
0
            case MSGPACK_CS_STR_16: {
725
0
                uint16_t tmp;
726
0
                load<uint16_t>(tmp, n);
727
0
                m_trail = tmp;
728
0
                if(m_trail == 0) {
729
0
                    unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
730
0
                    int ret = push_proc(obj, off);
731
0
                    if (ret != 0) return ret;
732
0
                }
733
0
                else {
734
0
                    m_cs = MSGPACK_ACS_STR_VALUE;
735
0
                    fixed_trail_again = true;
736
0
                }
737
0
            } break;
738
0
            case MSGPACK_CS_BIN_16: {
739
0
                uint16_t tmp;
740
0
                load<uint16_t>(tmp, n);
741
0
                m_trail = tmp;
742
0
                if(m_trail == 0) {
743
0
                    unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
744
0
                    int ret = push_proc(obj, off);
745
0
                    if (ret != 0) return ret;
746
0
                }
747
0
                else {
748
0
                    m_cs = MSGPACK_ACS_BIN_VALUE;
749
0
                    fixed_trail_again = true;
750
0
                }
751
0
            } break;
752
0
            case MSGPACK_CS_EXT_16: {
753
0
                uint16_t tmp;
754
0
                load<uint16_t>(tmp, n);
755
0
                m_trail = tmp + 1;
756
0
                if(m_trail == 0) {
757
0
                    unpack_ext(m_user, n, m_trail, obj);
758
0
                    int ret = push_proc(obj, off);
759
0
                    if (ret != 0) return ret;
760
0
                }
761
0
                else {
762
0
                    m_cs = MSGPACK_ACS_EXT_VALUE;
763
0
                    fixed_trail_again = true;
764
0
                }
765
0
            } break;
766
0
            case MSGPACK_CS_STR_32: {
767
0
                uint32_t tmp;
768
0
                load<uint32_t>(tmp, n);
769
0
                m_trail = tmp;
770
0
                if(m_trail == 0) {
771
0
                    unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
772
0
                    int ret = push_proc(obj, off);
773
0
                    if (ret != 0) return ret;
774
0
                }
775
0
                else {
776
0
                    m_cs = MSGPACK_ACS_STR_VALUE;
777
0
                    fixed_trail_again = true;
778
0
                }
779
0
            } break;
780
0
            case MSGPACK_CS_BIN_32: {
781
0
                uint32_t tmp;
782
0
                load<uint32_t>(tmp, n);
783
0
                m_trail = tmp;
784
0
                if(m_trail == 0) {
785
0
                    unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
786
0
                    int ret = push_proc(obj, off);
787
0
                    if (ret != 0) return ret;
788
0
                }
789
0
                else {
790
0
                    m_cs = MSGPACK_ACS_BIN_VALUE;
791
0
                    fixed_trail_again = true;
792
0
                }
793
0
            } break;
794
0
            case MSGPACK_CS_EXT_32: {
795
0
                uint32_t tmp;
796
0
                load<uint32_t>(tmp, n);
797
0
                check_ext_size<sizeof(std::size_t)>(tmp);
798
0
                m_trail = tmp;
799
0
                ++m_trail;
800
0
                if(m_trail == 0) {
801
0
                    unpack_ext(m_user, n, m_trail, obj);
802
0
                    int ret = push_proc(obj, off);
803
0
                    if (ret != 0) return ret;
804
0
                }
805
0
                else {
806
0
                    m_cs = MSGPACK_ACS_EXT_VALUE;
807
0
                    fixed_trail_again = true;
808
0
                }
809
0
            } break;
810
0
            case MSGPACK_ACS_STR_VALUE: {
811
0
                unpack_str(m_user, n, static_cast<uint32_t>(m_trail), obj);
812
0
                int ret = push_proc(obj, off);
813
0
                if (ret != 0) return ret;
814
0
            } break;
815
0
            case MSGPACK_ACS_BIN_VALUE: {
816
0
                unpack_bin(m_user, n, static_cast<uint32_t>(m_trail), obj);
817
0
                int ret = push_proc(obj, off);
818
0
                if (ret != 0) return ret;
819
0
            } break;
820
0
            case MSGPACK_ACS_EXT_VALUE: {
821
0
                unpack_ext(m_user, n, m_trail, obj);
822
0
                int ret = push_proc(obj, off);
823
0
                if (ret != 0) return ret;
824
0
            } break;
825
0
            case MSGPACK_CS_ARRAY_16: {
826
0
                int ret = push_aggregate<uint16_t>(
827
0
                    unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
828
0
                if (ret != 0) return ret;
829
0
            } break;
830
0
            case MSGPACK_CS_ARRAY_32: {
831
0
                /* FIXME security guard */
832
0
                int ret = push_aggregate<uint32_t>(
833
0
                    unpack_array(), MSGPACK_CT_ARRAY_ITEM, obj, n, off);
834
0
                if (ret != 0) return ret;
835
0
            } break;
836
0
            case MSGPACK_CS_MAP_16: {
837
0
                int ret = push_aggregate<uint16_t>(
838
0
                    unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
839
0
                if (ret != 0) return ret;
840
0
            } break;
841
0
            case MSGPACK_CS_MAP_32: {
842
0
                /* FIXME security guard */
843
0
                int ret = push_aggregate<uint32_t>(
844
0
                    unpack_map(), MSGPACK_CT_MAP_KEY, obj, n, off);
845
0
                if (ret != 0) return ret;
846
0
            } break;
847
0
            default:
848
0
                off = static_cast<std::size_t>(m_current - m_start);
849
0
                return -1;
850
0
            }
851
0
        }
852
0
    } while(m_current != pe);
853
0
854
0
    off = static_cast<std::size_t>(m_current - m_start);
855
0
    return 0;
856
0
}
857
858
} // detail
859
860
861
/// Unpacking class for a stream deserialization.
862
class unpacker {
863
public:
864
    /// Constructor
865
    /**
866
     * @param f A judging function that msgpack::object refer to the buffer.
867
     * @param user_data This parameter is passed to f.
868
     * @param initial_buffer_size The memory size to allocate when unpacker is constructed.
869
     * @param limit The size limit information of msgpack::object.
870
     *
871
     */
872
    unpacker(unpack_reference_func f = &unpacker::default_reference_func,
873
             void* user_data = MSGPACK_NULLPTR,
874
             std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE,
875
             unpack_limit const& limit = unpack_limit());
876
877
#if !defined(MSGPACK_USE_CPP03)
878
    unpacker(unpacker&& other);
879
    unpacker& operator=(unpacker&& other);
880
#endif // !defined(MSGPACK_USE_CPP03)
881
882
    ~unpacker();
883
884
public:
885
    /// Reserve a buffer memory.
886
    /**
887
     * @param size The size of allocating memory.
888
     *
889
     * After returning this function, buffer_capacity() returns at least 'size'.
890
     * See:
891
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
892
     */
893
    void reserve_buffer(std::size_t size = MSGPACK_UNPACKER_RESERVE_SIZE);
894
895
    /// Get buffer pointer.
896
    /**
897
     * You need to care about the memory is enable between buffer() and buffer() + buffer_capacity()
898
     * See:
899
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
900
     */
901
    char* buffer();
902
903
    /// Get buffer capacity.
904
    /**
905
     * @return The memory size that you can write.
906
     *
907
     * See:
908
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
909
     */
910
    std::size_t buffer_capacity() const;
911
912
    /// Notify a buffer consumed information to msgpack::unpacker.
913
    /**
914
     * @param size The size of memory that you consumed.
915
     *
916
     * After copying the data to the memory that is pointed by buffer(), you need to call the
917
     * function to notify how many bytes are consumed. Then you can call next() functions.
918
     *
919
     * See:
920
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
921
     */
922
    void buffer_consumed(std::size_t size);
923
924
    /// Unpack one msgpack::object. [obsolete]
925
    /**
926
     *
927
     * @param result The object that contains unpacked data.
928
     *
929
     * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
930
     *         and additional data is required, then return false. If data format is invalid, throw
931
     *         msgpack::parse_error.
932
     *
933
     * See:
934
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
935
     * This function is obsolete. Use the reference inteface version of next() function instead of
936
     * the pointer interface version.
937
     */
938
    MSGPACK_DEPRECATED("please use reference version instead")
939
    bool next(msgpack::object_handle* result);
940
941
    /// Unpack one msgpack::object.
942
    /**
943
     *
944
     * @param result The object that contains unpacked data.
945
     * @param referenced If the unpacked object contains reference of the buffer,
946
     *                   then set as true, otherwise false.
947
     *
948
     * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
949
     *         and additional data is required, then return false. If data format is invalid, throw
950
     *         msgpack::parse_error.
951
     *
952
     * See:
953
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
954
     */
955
    bool next(msgpack::object_handle& result, bool& referenced);
956
957
    /// Unpack one msgpack::object.
958
    /**
959
     *
960
     * @param result The object that contains unpacked data.
961
     *
962
     * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
963
     *         and additional data is required, then return false. If data format is invalid, throw
964
     *         msgpack::parse_error.
965
     *
966
     * See:
967
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
968
     */
969
    bool next(msgpack::object_handle& result);
970
971
    /// Get message size.
972
    /**
973
     * @return Returns parsed_size() + nonparsed_size()
974
     */
975
    std::size_t message_size() const;
976
977
    /*! for backward compatibility */
978
    bool execute();
979
980
    /*! for backward compatibility */
981
    msgpack::object const& data();
982
983
    /*! for backward compatibility */
984
    msgpack::zone* release_zone();
985
986
    /*! for backward compatibility */
987
    void reset_zone();
988
989
    /*! for backward compatibility */
990
    void reset();
991
992
public:
993
    /// Get parsed message size.
994
    /**
995
     * @return Parsed message size.
996
     *
997
     * This function is usable when non-MessagePack message follows after
998
     * MessagePack message.
999
     */
1000
    std::size_t parsed_size() const;
1001
1002
    /// Get the address that is not parsed in the buffer.
1003
    /**
1004
     * @return Address of the buffer that is not parsed
1005
     *
1006
     * This function is usable when non-MessagePack message follows after
1007
     * MessagePack message.
1008
     */
1009
    char* nonparsed_buffer();
1010
1011
    /// Get the size of the buffer that is not parsed.
1012
    /**
1013
     * @return Size of the buffer that is not parsed
1014
     *
1015
     * This function is usable when non-MessagePack message follows after
1016
     * MessagePack message.
1017
     */
1018
    std::size_t nonparsed_size() const;
1019
1020
    /// Skip the specified size of non-parsed buffer.
1021
    /**
1022
     * @param size to skip
1023
     *
1024
     * Note that the `size' argument must be smaller than nonparsed_size().
1025
     * This function is usable when non-MessagePack message follows after
1026
     * MessagePack message.
1027
     */
1028
    void skip_nonparsed_buffer(std::size_t size);
1029
1030
    /// Remove nonparsed buffer and reset the current position as a new start point.
1031
    /**
1032
     * This function is usable when non-MessagePack message follows after
1033
     * MessagePack message.
1034
     */
1035
    void remove_nonparsed_buffer();
1036
1037
private:
1038
    void expand_buffer(std::size_t size);
1039
    int execute_imp();
1040
    bool flush_zone();
1041
    static bool default_reference_func(msgpack::type::object_type type, std::size_t len, void*);
1042
1043
private:
1044
    char* m_buffer;
1045
    std::size_t m_used;
1046
    std::size_t m_free;
1047
    std::size_t m_off;
1048
    std::size_t m_parsed;
1049
    msgpack::unique_ptr<msgpack::zone> m_z;
1050
    std::size_t m_initial_buffer_size;
1051
    detail::context m_ctx;
1052
1053
#if defined(MSGPACK_USE_CPP03)
1054
private:
1055
    unpacker(const unpacker&);
1056
    unpacker& operator=(const unpacker&);
1057
#else  // defined(MSGPACK_USE_CPP03)
1058
    unpacker(const unpacker&) = delete;
1059
    unpacker& operator=(const unpacker&) = delete;
1060
#endif // defined(MSGPACK_USE_CPP03)
1061
};
1062
1063
inline unpacker::unpacker(unpack_reference_func f,
1064
                          void* user_data,
1065
                          std::size_t initial_buffer_size,
1066
                          unpack_limit const& limit)
1067
    :m_z(new msgpack::zone), m_ctx(f, user_data, limit)
1068
{
1069
    if(initial_buffer_size < COUNTER_SIZE) {
1070
        initial_buffer_size = COUNTER_SIZE;
1071
    }
1072
1073
    char* buffer = static_cast<char*>(::malloc(initial_buffer_size));
1074
    if(!buffer) {
1075
        throw std::bad_alloc();
1076
    }
1077
1078
    m_buffer = buffer;
1079
    m_used = COUNTER_SIZE;
1080
    m_free = initial_buffer_size - m_used;
1081
    m_off = COUNTER_SIZE;
1082
    m_parsed = 0;
1083
    m_initial_buffer_size = initial_buffer_size;
1084
1085
    detail::init_count(m_buffer);
1086
1087
    m_ctx.init();
1088
    m_ctx.user().set_zone(*m_z);
1089
    m_ctx.user().set_referenced(false);
1090
}
1091
1092
#if !defined(MSGPACK_USE_CPP03)
1093
// Move constructor and move assignment operator
1094
1095
inline unpacker::unpacker(unpacker&& other)
1096
    :m_buffer(other.m_buffer),
1097
     m_used(other.m_used),
1098
     m_free(other.m_free),
1099
     m_off(other.m_off),
1100
     m_parsed(other.m_parsed),
1101
     m_z(std::move(other.m_z)),
1102
     m_initial_buffer_size(other.m_initial_buffer_size),
1103
     m_ctx(other.m_ctx) {
1104
    other.m_buffer = MSGPACK_NULLPTR;
1105
}
1106
1107
0
inline unpacker& unpacker::operator=(unpacker&& other) {
1108
0
    if (this != &other) {
1109
0
        this->~unpacker();
1110
0
        new (this) unpacker(std::move(other));
1111
0
    }
1112
0
    return *this;
1113
0
}
1114
1115
#endif // !defined(MSGPACK_USE_CPP03)
1116
1117
1118
inline unpacker::~unpacker()
1119
{
1120
    // These checks are required for move operations.
1121
    if (m_buffer) detail::decr_count(m_buffer);
1122
}
1123
1124
1125
inline void unpacker::reserve_buffer(std::size_t size)
1126
0
{
1127
0
    if(m_free >= size) return;
1128
0
    expand_buffer(size);
1129
0
}
1130
1131
inline void unpacker::expand_buffer(std::size_t size)
1132
0
{
1133
0
    if(m_used == m_off && detail::get_count(m_buffer) == 1
1134
0
        && !m_ctx.user().referenced()) {
1135
0
        // rewind buffer
1136
0
        m_free += m_used - COUNTER_SIZE;
1137
0
        m_used = COUNTER_SIZE;
1138
0
        m_off  = COUNTER_SIZE;
1139
0
1140
0
        if(m_free >= size) return;
1141
0
    }
1142
0
1143
0
    if(m_off == COUNTER_SIZE) {
1144
0
        if(size > std::numeric_limits<std::size_t>::max() - m_used) {
1145
0
            throw std::bad_alloc();
1146
0
        }
1147
0
        std::size_t next_size = (m_used + m_free) * 2;    // include COUNTER_SIZE
1148
0
        while(next_size < size + m_used) {
1149
0
            std::size_t tmp_next_size = next_size * 2;
1150
0
            if (tmp_next_size <= next_size) {
1151
0
                next_size = size + m_used;
1152
0
                break;
1153
0
            }
1154
0
            next_size = tmp_next_size;
1155
0
        }
1156
0
1157
0
        char* tmp = static_cast<char*>(::realloc(m_buffer, next_size));
1158
0
        if(!tmp) {
1159
0
            throw std::bad_alloc();
1160
0
        }
1161
0
1162
0
        m_buffer = tmp;
1163
0
        m_free = next_size - m_used;
1164
0
1165
0
    } else {
1166
0
        std::size_t next_size = m_initial_buffer_size;  // include COUNTER_SIZE
1167
0
        std::size_t not_parsed = m_used - m_off;
1168
0
        if(size > std::numeric_limits<std::size_t>::max() - not_parsed - COUNTER_SIZE) {
1169
0
            throw std::bad_alloc();
1170
0
        }
1171
0
        while(next_size < size + not_parsed + COUNTER_SIZE) {
1172
0
            std::size_t tmp_next_size = next_size * 2;
1173
0
            if (tmp_next_size <= next_size) {
1174
0
                next_size = size + not_parsed + COUNTER_SIZE;
1175
0
                break;
1176
0
            }
1177
0
            next_size = tmp_next_size;
1178
0
        }
1179
0
1180
0
        char* tmp = static_cast<char*>(::malloc(next_size));
1181
0
        if(!tmp) {
1182
0
            throw std::bad_alloc();
1183
0
        }
1184
0
1185
0
        detail::init_count(tmp);
1186
0
1187
0
        std::memcpy(tmp+COUNTER_SIZE, m_buffer + m_off, not_parsed);
1188
0
1189
0
        if(m_ctx.user().referenced()) {
1190
0
            try {
1191
0
                m_z->push_finalizer(&detail::decr_count, m_buffer);
1192
0
            }
1193
0
            catch (...) {
1194
0
                ::free(tmp);
1195
0
                throw;
1196
0
            }
1197
0
            m_ctx.user().set_referenced(false);
1198
0
        } else {
1199
0
            detail::decr_count(m_buffer);
1200
0
        }
1201
0
1202
0
        m_buffer = tmp;
1203
0
        m_used  = not_parsed + COUNTER_SIZE;
1204
0
        m_free  = next_size - m_used;
1205
0
        m_off   = COUNTER_SIZE;
1206
0
    }
1207
0
}
1208
1209
inline char* unpacker::buffer()
1210
0
{
1211
0
    return m_buffer + m_used;
1212
0
}
1213
1214
inline std::size_t unpacker::buffer_capacity() const
1215
0
{
1216
0
    return m_free;
1217
0
}
1218
1219
inline void unpacker::buffer_consumed(std::size_t size)
1220
0
{
1221
0
    m_used += size;
1222
0
    m_free -= size;
1223
0
}
1224
1225
inline bool unpacker::next(msgpack::object_handle& result, bool& referenced)
1226
0
{
1227
0
    referenced = false;
1228
0
    int ret = execute_imp();
1229
0
    if(ret < 0) {
1230
0
        throw msgpack::parse_error("parse error");
1231
0
    }
1232
0
1233
0
    if(ret == 0) {
1234
0
        result.zone().reset();
1235
0
        result.set(msgpack::object());
1236
0
        return false;
1237
0
1238
0
    } else {
1239
0
        referenced = m_ctx.user().referenced();
1240
0
        result.zone().reset( release_zone() );
1241
0
        result.set(data());
1242
0
        reset();
1243
0
        return true;
1244
0
    }
1245
0
}
1246
1247
inline bool unpacker::next(msgpack::object_handle& result)
1248
0
{
1249
0
    bool referenced;
1250
0
    return next(result, referenced);
1251
0
}
1252
1253
inline bool unpacker::next(msgpack::object_handle* result)
1254
0
{
1255
0
    return next(*result);
1256
0
}
1257
1258
1259
inline bool unpacker::execute()
1260
0
{
1261
0
    int ret = execute_imp();
1262
0
    if(ret < 0) {
1263
0
        throw msgpack::parse_error("parse error");
1264
0
    } else if(ret == 0) {
1265
0
        return false;
1266
0
    } else {
1267
0
        return true;
1268
0
    }
1269
0
}
1270
1271
inline int unpacker::execute_imp()
1272
0
{
1273
0
    std::size_t off = m_off;
1274
0
    int ret = m_ctx.execute(m_buffer, m_used, m_off);
1275
0
    if(m_off > off) {
1276
0
        m_parsed += m_off - off;
1277
0
    }
1278
0
    return ret;
1279
0
}
1280
1281
inline msgpack::object const& unpacker::data()
1282
0
{
1283
0
    return m_ctx.data();
1284
0
}
1285
1286
inline msgpack::zone* unpacker::release_zone()
1287
0
{
1288
0
    if(!flush_zone()) {
1289
0
        return MSGPACK_NULLPTR;
1290
0
    }
1291
0
1292
0
    msgpack::zone* r =  new msgpack::zone;
1293
0
    msgpack::zone* old = m_z.release();
1294
0
    m_z.reset(r);
1295
0
    m_ctx.user().set_zone(*m_z);
1296
0
1297
0
    return old;
1298
0
}
1299
1300
inline void unpacker::reset_zone()
1301
0
{
1302
0
    m_z->clear();
1303
0
}
1304
1305
inline bool unpacker::flush_zone()
1306
0
{
1307
0
    if(m_ctx.user().referenced()) {
1308
0
        try {
1309
0
            m_z->push_finalizer(&detail::decr_count, m_buffer);
1310
0
        } catch (...) {
1311
0
            return false;
1312
0
        }
1313
0
        m_ctx.user().set_referenced(false);
1314
0
1315
0
        detail::incr_count(m_buffer);
1316
0
    }
1317
0
1318
0
    return true;
1319
0
}
1320
1321
inline void unpacker::reset()
1322
0
{
1323
0
    m_ctx.init();
1324
0
    // don't reset referenced flag
1325
0
    m_parsed = 0;
1326
0
}
1327
1328
inline std::size_t unpacker::message_size() const
1329
0
{
1330
0
    return m_parsed - m_off + m_used;
1331
0
}
1332
1333
inline std::size_t unpacker::parsed_size() const
1334
0
{
1335
0
    return m_parsed;
1336
0
}
1337
1338
inline char* unpacker::nonparsed_buffer()
1339
0
{
1340
0
    return m_buffer + m_off;
1341
0
}
1342
1343
inline std::size_t unpacker::nonparsed_size() const
1344
0
{
1345
0
    return m_used - m_off;
1346
0
}
1347
1348
inline void unpacker::skip_nonparsed_buffer(std::size_t size)
1349
0
{
1350
0
    m_off += size;
1351
0
}
1352
1353
inline void unpacker::remove_nonparsed_buffer()
1354
0
{
1355
0
    m_used = m_off;
1356
0
}
1357
1358
namespace detail {
1359
1360
inline parse_return
1361
unpack_imp(const char* data, std::size_t len, std::size_t& off,
1362
           msgpack::zone& result_zone, msgpack::object& result, bool& referenced,
1363
           unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR,
1364
           unpack_limit const& limit = unpack_limit())
1365
0
{
1366
0
    std::size_t noff = off;
1367
0
1368
0
    if(len <= noff) {
1369
0
        // FIXME
1370
0
        return PARSE_CONTINUE;
1371
0
    }
1372
0
1373
0
    detail::context ctx(f, user_data, limit);
1374
0
    ctx.init();
1375
0
1376
0
    ctx.user().set_zone(result_zone);
1377
0
    ctx.user().set_referenced(false);
1378
0
    referenced = false;
1379
0
1380
0
    int e = ctx.execute(data, len, noff);
1381
0
    if(e < 0) {
1382
0
        return PARSE_PARSE_ERROR;
1383
0
    }
1384
0
1385
0
    referenced = ctx.user().referenced();
1386
0
    off = noff;
1387
0
1388
0
    if(e == 0) {
1389
0
        return PARSE_CONTINUE;
1390
0
    }
1391
0
1392
0
    result = ctx.data();
1393
0
1394
0
    if(noff < len) {
1395
0
        return PARSE_EXTRA_BYTES;
1396
0
    }
1397
0
1398
0
    return PARSE_SUCCESS;
1399
0
}
1400
1401
} // detail
1402
1403
// reference version
1404
1405
inline msgpack::object_handle unpack(
1406
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
1407
    unpack_reference_func f, void* user_data,
1408
    unpack_limit const& limit
1409
)
1410
0
{
1411
0
    msgpack::object obj;
1412
0
    msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
1413
0
    referenced = false;
1414
0
    std::size_t noff = off;
1415
0
    parse_return ret = detail::unpack_imp(
1416
0
        data, len, noff, *z, obj, referenced, f, user_data, limit);
1417
0
1418
0
    switch(ret) {
1419
0
    case PARSE_SUCCESS:
1420
0
        off = noff;
1421
0
        return msgpack::object_handle(obj, msgpack::move(z));
1422
0
    case PARSE_EXTRA_BYTES:
1423
0
        off = noff;
1424
0
        return msgpack::object_handle(obj, msgpack::move(z));
1425
0
    case PARSE_CONTINUE:
1426
0
        throw msgpack::insufficient_bytes("insufficient bytes");
1427
0
    case PARSE_PARSE_ERROR:
1428
0
    default:
1429
0
        throw msgpack::parse_error("parse error");
1430
0
    }
1431
0
    return msgpack::object_handle();
1432
0
}
1433
1434
inline msgpack::object_handle unpack(
1435
    const char* data, std::size_t len, std::size_t& off,
1436
    unpack_reference_func f, void* user_data,
1437
    unpack_limit const& limit)
1438
0
{
1439
0
    bool referenced;
1440
0
    return unpack(data, len, off, referenced, f, user_data, limit);
1441
0
}
1442
1443
inline msgpack::object_handle unpack(
1444
    const char* data, std::size_t len, bool& referenced,
1445
    unpack_reference_func f, void* user_data,
1446
    unpack_limit const& limit)
1447
0
{
1448
0
    std::size_t off = 0;
1449
0
    return unpack(data, len, off, referenced, f, user_data, limit);
1450
0
}
1451
1452
inline msgpack::object_handle unpack(
1453
    const char* data, std::size_t len,
1454
    unpack_reference_func f, void* user_data,
1455
    unpack_limit const& limit)
1456
0
{
1457
0
    bool referenced;
1458
0
    std::size_t off = 0;
1459
0
    return unpack(data, len, off, referenced, f, user_data, limit);
1460
0
}
1461
1462
inline void unpack(
1463
    msgpack::object_handle& result,
1464
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
1465
    unpack_reference_func f, void* user_data,
1466
    unpack_limit const& limit)
1467
0
{
1468
0
    msgpack::object obj;
1469
0
    msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
1470
0
    referenced = false;
1471
0
    std::size_t noff = off;
1472
0
    parse_return ret = detail::unpack_imp(
1473
0
        data, len, noff, *z, obj, referenced, f, user_data, limit);
1474
0
1475
0
    switch(ret) {
1476
0
    case PARSE_SUCCESS:
1477
0
        off = noff;
1478
0
        result.set(obj);
1479
0
        result.zone() = msgpack::move(z);
1480
0
        return;
1481
0
    case PARSE_EXTRA_BYTES:
1482
0
        off = noff;
1483
0
        result.set(obj);
1484
0
        result.zone() = msgpack::move(z);
1485
0
        return;
1486
0
    case PARSE_CONTINUE:
1487
0
        throw msgpack::insufficient_bytes("insufficient bytes");
1488
0
    case PARSE_PARSE_ERROR:
1489
0
    default:
1490
0
        throw msgpack::parse_error("parse error");
1491
0
    }
1492
0
}
1493
1494
inline void unpack(
1495
    msgpack::object_handle& result,
1496
    const char* data, std::size_t len, std::size_t& off,
1497
    unpack_reference_func f, void* user_data,
1498
            unpack_limit const& limit)
1499
0
{
1500
0
    bool referenced;
1501
0
    unpack(result, data, len, off, referenced, f, user_data, limit);
1502
0
}
1503
1504
inline void unpack(
1505
    msgpack::object_handle& result,
1506
    const char* data, std::size_t len, bool& referenced,
1507
    unpack_reference_func f, void* user_data,
1508
    unpack_limit const& limit)
1509
0
{
1510
0
    std::size_t off = 0;
1511
0
    unpack(result, data, len, off, referenced, f, user_data, limit);
1512
0
}
1513
1514
inline void unpack(
1515
    msgpack::object_handle& result,
1516
    const char* data, std::size_t len,
1517
    unpack_reference_func f, void* user_data,
1518
    unpack_limit const& limit)
1519
0
{
1520
0
    bool referenced;
1521
0
    std::size_t off = 0;
1522
0
    unpack(result, data, len, off, referenced, f, user_data, limit);
1523
0
}
1524
1525
1526
inline msgpack::object unpack(
1527
    msgpack::zone& z,
1528
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
1529
    unpack_reference_func f, void* user_data,
1530
    unpack_limit const& limit)
1531
0
{
1532
0
    msgpack::object obj;
1533
0
    std::size_t noff = off;
1534
0
    referenced = false;
1535
0
    parse_return ret = detail::unpack_imp(
1536
0
        data, len, noff, z, obj, referenced, f, user_data, limit);
1537
0
1538
0
    switch(ret) {
1539
0
    case PARSE_SUCCESS:
1540
0
        off = noff;
1541
0
        return obj;
1542
0
    case PARSE_EXTRA_BYTES:
1543
0
        off = noff;
1544
0
        return obj;
1545
0
    case PARSE_CONTINUE:
1546
0
        throw msgpack::insufficient_bytes("insufficient bytes");
1547
0
    case PARSE_PARSE_ERROR:
1548
0
    default:
1549
0
        throw msgpack::parse_error("parse error");
1550
0
    }
1551
0
    return obj;
1552
0
}
1553
1554
inline msgpack::object unpack(
1555
    msgpack::zone& z,
1556
    const char* data, std::size_t len, std::size_t& off,
1557
    unpack_reference_func f, void* user_data,
1558
    unpack_limit const& limit)
1559
0
{
1560
0
    bool referenced;
1561
0
    return unpack(z, data, len, off, referenced, f, user_data, limit);
1562
0
}
1563
1564
inline msgpack::object unpack(
1565
    msgpack::zone& z,
1566
    const char* data, std::size_t len, bool& referenced,
1567
    unpack_reference_func f, void* user_data,
1568
    unpack_limit const& limit)
1569
0
{
1570
0
    std::size_t off = 0;
1571
0
    return unpack(z, data, len, off, referenced, f, user_data, limit);
1572
0
}
1573
1574
inline msgpack::object unpack(
1575
    msgpack::zone& z,
1576
    const char* data, std::size_t len,
1577
    unpack_reference_func f, void* user_data,
1578
    unpack_limit const& limit)
1579
0
{
1580
0
    bool referenced;
1581
0
    std::size_t off = 0;
1582
0
    return unpack(z, data, len, off, referenced, f, user_data, limit);
1583
0
}
1584
1585
// obsolete
1586
// pointer version
1587
MSGPACK_DEPRECATED("please use reference version instead")
1588
inline void unpack(
1589
    msgpack::object_handle* result,
1590
    const char* data, std::size_t len, std::size_t* off, bool* referenced,
1591
    unpack_reference_func f, void* user_data,
1592
    unpack_limit const& limit)
1593
0
{
1594
0
    if (off)
1595
0
        if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data, limit);
1596
0
        else unpack(*result, data, len, *off, f, user_data, limit);
1597
0
    else
1598
0
        if (referenced) unpack(*result, data, len, *referenced, f, user_data, limit);
1599
0
        else unpack(*result, data, len, f, user_data, limit);
1600
0
}
1601
1602
inline bool unpacker::default_reference_func(msgpack::type::object_type /*type*/, std::size_t /*len*/, void*)
1603
0
{
1604
0
    return true;
1605
0
}
1606
1607
/// @cond
1608
}  // MSGPACK_API_VERSION_NAMESPACE(v1)
1609
/// @endcond
1610
1611
}  // namespace msgpack
1612
1613
1614
#endif // MSGPACK_V1_UNPACK_HPP