Coverage Report

Created: 2024-12-31 06:13

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