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/v2/unpack.hpp
Line
Count
Source
1
//
2
// MessagePack for C++ deserializing routine
3
//
4
// Copyright (C) 2016 KONDO Takatoshi
5
//
6
//    Distributed under the Boost Software License, Version 1.0.
7
//    (See accompanying file LICENSE_1_0.txt or copy at
8
//    http://www.boost.org/LICENSE_1_0.txt)
9
//
10
#ifndef MSGPACK_V2_UNPACK_HPP
11
#define MSGPACK_V2_UNPACK_HPP
12
13
#if MSGPACK_DEFAULT_API_VERSION >= 2
14
15
#include "msgpack/unpack_decl.hpp"
16
#include "msgpack/parse.hpp"
17
#include "msgpack/create_object_visitor.hpp"
18
19
namespace msgpack {
20
21
/// @cond
22
MSGPACK_API_VERSION_NAMESPACE(v2) {
23
/// @endcond
24
25
26
struct zone_push_finalizer {
27
0
    zone_push_finalizer(msgpack::zone& z):m_z(&z) {}
28
0
    void set_zone(msgpack::zone& z) { m_z = &z; }
29
0
    void operator()(char* buffer) {
30
0
        m_z->push_finalizer(&detail::decr_count, buffer);
31
0
    }
32
    msgpack::zone* m_z;
33
};
34
35
class unpacker : public parser<unpacker, zone_push_finalizer>,
36
                 public detail::create_object_visitor {
37
    typedef parser<unpacker, zone_push_finalizer> parser_t;
38
public:
39
    unpacker(unpack_reference_func f = &unpacker::default_reference_func,
40
             void* user_data = MSGPACK_NULLPTR,
41
             std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE,
42
             unpack_limit const& limit = unpack_limit())
43
        :parser_t(m_finalizer, initial_buffer_size),
44
         detail::create_object_visitor(f, user_data, limit),
45
         m_z(new msgpack::zone),
46
0
         m_finalizer(*m_z) {
47
0
        set_zone(*m_z);
48
0
        set_referenced(false);
49
0
    }
50
51
#if !defined(MSGPACK_USE_CPP03)
52
    unpacker(unpacker&& other)
53
        :parser_t(std::move(other)),
54
         detail::create_object_visitor(std::move(other)),
55
         m_z(std::move(other.m_z)),
56
0
         m_finalizer(std::move(other.m_finalizer)) {
57
0
        // The parser base copied a hook pointer that still refers to the
58
0
        // moved-from object's m_finalizer; re-point it to our own. The zone
59
0
        // itself is heap-allocated and only ownership moved, so the zone
60
0
        // pointers held by the visitor and by m_finalizer stay valid.
61
0
        parser_t::set_referenced_buffer_hook(m_finalizer);
62
0
    }
63
0
    unpacker& operator=(unpacker&& other) {
64
0
        if (this != &other) {
65
0
            this->~unpacker();
66
0
            new (this) unpacker(std::move(other));
67
0
        }
68
0
        return *this;
69
0
    }
70
#endif // !defined(MSGPACK_USE_CPP03)
71
72
0
    detail::create_object_visitor& visitor() { return *this; }
73
    /// Unpack one msgpack::object.
74
    /**
75
     *
76
     * @param result The object that contains unpacked data.
77
     * @param referenced If the unpacked object contains reference of the buffer,
78
     *                   then set as true, otherwise false.
79
     *
80
     * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
81
     *         and additional data is required, then return false. If data format is invalid, throw
82
     *         msgpack::parse_error.
83
     *
84
     * See:
85
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
86
     */
87
    bool next(msgpack::object_handle& result, bool& referenced);
88
89
    /// Unpack one msgpack::object.
90
    /**
91
     *
92
     * @param result The object that contains unpacked data.
93
     *
94
     * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
95
     *         and additional data is required, then return false. If data format is invalid, throw
96
     *         msgpack::parse_error.
97
     *
98
     * See:
99
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
100
     */
101
    bool next(msgpack::object_handle& result);
102
    msgpack::zone* release_zone();
103
    void reset_zone();
104
    bool flush_zone();
105
private:
106
0
    static bool default_reference_func(msgpack::type::object_type /*type*/, std::size_t /*len*/, void*) {
107
0
        return true;
108
0
    }
109
    msgpack::unique_ptr<msgpack::zone> m_z;
110
    zone_push_finalizer m_finalizer;
111
};
112
113
0
inline bool unpacker::next(msgpack::object_handle& result, bool& referenced) {
114
0
    bool ret = parser_t::next();
115
0
    if (ret) {
116
0
        referenced = detail::create_object_visitor::referenced();
117
0
        result.zone().reset( release_zone() );
118
0
        result.set(data());
119
0
        reset();
120
0
    }
121
0
    else {
122
0
        result.zone().reset();
123
0
        result.set(msgpack::object());
124
0
    }
125
0
    return ret;
126
0
}
127
128
0
inline bool unpacker::next(msgpack::object_handle& result) {
129
0
    bool referenced;
130
0
    return next(result, referenced);
131
0
}
132
133
inline msgpack::zone* unpacker::release_zone()
134
0
{
135
0
    if(!flush_zone()) {
136
0
        return MSGPACK_NULLPTR;
137
0
    }
138
0
139
0
    msgpack::zone* r =  new msgpack::zone;
140
0
    msgpack::zone* old = m_z.release();
141
0
    m_z.reset(r);
142
0
    set_zone(*m_z);
143
0
    m_finalizer.set_zone(*m_z);
144
0
145
0
    return old;
146
0
}
147
148
inline void unpacker::reset_zone()
149
0
{
150
0
    m_z->clear();
151
0
}
152
153
inline bool unpacker::flush_zone()
154
0
{
155
0
    if(referenced()) {
156
0
        try {
157
0
            m_z->push_finalizer(&detail::decr_count, get_raw_buffer());
158
0
        } catch (...) {
159
0
            return false;
160
0
        }
161
0
        set_referenced(false);
162
0
163
0
        detail::incr_count(get_raw_buffer());
164
0
    }
165
0
166
0
    return true;
167
0
}
168
169
inline msgpack::object_handle unpack(
170
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
171
    unpack_reference_func f, void* user_data,
172
    unpack_limit const& limit
173
)
174
0
{
175
0
    msgpack::object obj;
176
0
    msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
177
0
    referenced = false;
178
0
    std::size_t noff = off;
179
0
    parse_return ret = detail::unpack_imp(
180
0
        data, len, noff, *z, obj, referenced, f, user_data, limit);
181
0
182
0
    switch(ret) {
183
0
    case PARSE_SUCCESS:
184
0
        off = noff;
185
0
        return msgpack::object_handle(obj, msgpack::move(z));
186
0
    case PARSE_EXTRA_BYTES:
187
0
        off = noff;
188
0
        return msgpack::object_handle(obj, msgpack::move(z));
189
0
    default:
190
0
        break;
191
0
    }
192
0
    return msgpack::object_handle();
193
0
}
194
195
inline msgpack::object_handle unpack(
196
    const char* data, std::size_t len, std::size_t& off,
197
    unpack_reference_func f, void* user_data,
198
    unpack_limit const& limit)
199
0
{
200
0
    bool referenced;
201
0
    return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit);
202
0
}
203
204
inline msgpack::object_handle unpack(
205
    const char* data, std::size_t len, bool& referenced,
206
    unpack_reference_func f, void* user_data,
207
    unpack_limit const& limit)
208
0
{
209
0
    std::size_t off = 0;
210
0
    return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit);
211
0
}
212
213
inline msgpack::object_handle unpack(
214
    const char* data, std::size_t len,
215
    unpack_reference_func f, void* user_data,
216
    unpack_limit const& limit)
217
0
{
218
0
    bool referenced;
219
0
    std::size_t off = 0;
220
0
    return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit);
221
0
}
222
223
inline void unpack(
224
    msgpack::object_handle& result,
225
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
226
    unpack_reference_func f, void* user_data,
227
    unpack_limit const& limit)
228
0
{
229
0
    msgpack::object obj;
230
0
    msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
231
0
    referenced = false;
232
0
    std::size_t noff = off;
233
0
    parse_return ret = detail::unpack_imp(
234
0
        data, len, noff, *z, obj, referenced, f, user_data, limit);
235
0
236
0
    switch(ret) {
237
0
    case PARSE_SUCCESS:
238
0
        off = noff;
239
0
        result.set(obj);
240
0
        result.zone() = msgpack::move(z);
241
0
        return;
242
0
    case PARSE_EXTRA_BYTES:
243
0
        off = noff;
244
0
        result.set(obj);
245
0
        result.zone() = msgpack::move(z);
246
0
        return;
247
0
    default:
248
0
        return;
249
0
    }
250
0
}
251
252
inline void unpack(
253
    msgpack::object_handle& result,
254
    const char* data, std::size_t len, std::size_t& off,
255
    unpack_reference_func f, void* user_data,
256
            unpack_limit const& limit)
257
0
{
258
0
    bool referenced;
259
0
    msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit);
260
0
}
261
262
inline void unpack(
263
    msgpack::object_handle& result,
264
    const char* data, std::size_t len, bool& referenced,
265
    unpack_reference_func f, void* user_data,
266
    unpack_limit const& limit)
267
0
{
268
0
    std::size_t off = 0;
269
0
    msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit);
270
0
}
271
272
inline void unpack(
273
    msgpack::object_handle& result,
274
    const char* data, std::size_t len,
275
    unpack_reference_func f, void* user_data,
276
    unpack_limit const& limit)
277
0
{
278
0
    bool referenced;
279
0
    std::size_t off = 0;
280
0
    msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit);
281
0
}
282
283
284
inline msgpack::object unpack(
285
    msgpack::zone& z,
286
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
287
    unpack_reference_func f, void* user_data,
288
    unpack_limit const& limit)
289
0
{
290
0
    msgpack::object obj;
291
0
    std::size_t noff = off;
292
0
    referenced = false;
293
0
    parse_return ret = detail::unpack_imp(
294
0
        data, len, noff, z, obj, referenced, f, user_data, limit);
295
0
296
0
    switch(ret) {
297
0
    case PARSE_SUCCESS:
298
0
        off = noff;
299
0
        return obj;
300
0
    case PARSE_EXTRA_BYTES:
301
0
        off = noff;
302
0
        return obj;
303
0
    default:
304
0
        break;
305
0
    }
306
0
    return obj;
307
0
}
308
309
inline msgpack::object unpack(
310
    msgpack::zone& z,
311
    const char* data, std::size_t len, std::size_t& off,
312
    unpack_reference_func f, void* user_data,
313
    unpack_limit const& limit)
314
0
{
315
0
    bool referenced;
316
0
    return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit);
317
0
}
318
319
inline msgpack::object unpack(
320
    msgpack::zone& z,
321
    const char* data, std::size_t len, bool& referenced,
322
    unpack_reference_func f, void* user_data,
323
    unpack_limit const& limit)
324
0
{
325
0
    std::size_t off = 0;
326
0
    return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit);
327
0
}
328
329
inline msgpack::object unpack(
330
    msgpack::zone& z,
331
    const char* data, std::size_t len,
332
    unpack_reference_func f, void* user_data,
333
    unpack_limit const& limit)
334
0
{
335
0
    bool referenced;
336
0
    std::size_t off = 0;
337
0
    return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit);
338
0
}
339
340
namespace detail {
341
342
inline parse_return
343
unpack_imp(const char* data, std::size_t len, std::size_t& off,
344
           msgpack::zone& result_zone, msgpack::object& result, bool& referenced,
345
           unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR,
346
           unpack_limit const& limit = unpack_limit())
347
2.09k
{
348
2.09k
    create_object_visitor v(f, user_data, limit);
349
2.09k
    v.set_zone(result_zone);
350
2.09k
    referenced = false;
351
2.09k
    v.set_referenced(referenced);
352
2.09k
    parse_return ret = parse_imp(data, len, off, v);
353
2.09k
    referenced = v.referenced();
354
2.09k
    result = v.data();
355
2.09k
    return ret;
356
2.09k
}
357
358
} // namespace detail
359
360
361
/// @cond
362
}  // MSGPACK_API_VERSION_NAMESPACE(v2)
363
/// @endcond
364
365
}  // namespace msgpack
366
367
#endif // MSGPACK_DEFAULT_API_VERSION >= 2
368
369
#endif // MSGPACK_V2_UNPACK_HPP