Coverage Report

Created: 2023-09-25 06:13

/src/msgpack-c/include/msgpack/v2/unpack.hpp
Line
Count
Source (jump to first uncovered line)
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
0
    detail::create_object_visitor& visitor() { return *this; }
52
    /// Unpack one msgpack::object.
53
    /**
54
     *
55
     * @param result The object that contains unpacked data.
56
     * @param referenced If the unpacked object contains reference of the buffer,
57
     *                   then set as true, otherwise false.
58
     *
59
     * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
60
     *         and additional data is required, then return false. If data format is invalid, throw
61
     *         msgpack::parse_error.
62
     *
63
     * See:
64
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
65
     */
66
    bool next(msgpack::object_handle& result, bool& referenced);
67
68
    /// Unpack one msgpack::object.
69
    /**
70
     *
71
     * @param result The object that contains unpacked data.
72
     *
73
     * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete
74
     *         and additional data is required, then return false. If data format is invalid, throw
75
     *         msgpack::parse_error.
76
     *
77
     * See:
78
     * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer
79
     */
80
    bool next(msgpack::object_handle& result);
81
    msgpack::zone* release_zone();
82
    void reset_zone();
83
    bool flush_zone();
84
private:
85
0
    static bool default_reference_func(msgpack::type::object_type /*type*/, std::size_t /*len*/, void*) {
86
0
        return true;
87
0
    }
88
    msgpack::unique_ptr<msgpack::zone> m_z;
89
    zone_push_finalizer m_finalizer;
90
};
91
92
0
inline bool unpacker::next(msgpack::object_handle& result, bool& referenced) {
93
0
    bool ret = parser_t::next();
94
0
    if (ret) {
95
0
        referenced = detail::create_object_visitor::referenced();
96
0
        result.zone().reset( release_zone() );
97
0
        result.set(data());
98
0
        reset();
99
0
    }
100
0
    else {
101
0
        result.zone().reset();
102
0
        result.set(msgpack::object());
103
0
    }
104
0
    return ret;
105
0
}
106
107
0
inline bool unpacker::next(msgpack::object_handle& result) {
108
0
    bool referenced;
109
0
    return next(result, referenced);
110
0
}
111
112
inline msgpack::zone* unpacker::release_zone()
113
0
{
114
0
    if(!flush_zone()) {
115
0
        return MSGPACK_NULLPTR;
116
0
    }
117
0
118
0
    msgpack::zone* r =  new msgpack::zone;
119
0
    msgpack::zone* old = m_z.release();
120
0
    m_z.reset(r);
121
0
    set_zone(*m_z);
122
0
    m_finalizer.set_zone(*m_z);
123
0
124
0
    return old;
125
0
}
126
127
inline void unpacker::reset_zone()
128
0
{
129
0
    m_z->clear();
130
0
}
131
132
inline bool unpacker::flush_zone()
133
0
{
134
0
    if(referenced()) {
135
0
        try {
136
0
            m_z->push_finalizer(&detail::decr_count, get_raw_buffer());
137
0
        } catch (...) {
138
0
            return false;
139
0
        }
140
0
        set_referenced(false);
141
0
142
0
        detail::incr_count(get_raw_buffer());
143
0
    }
144
0
145
0
    return true;
146
0
}
147
148
inline msgpack::object_handle unpack(
149
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
150
    unpack_reference_func f, void* user_data,
151
    unpack_limit const& limit
152
)
153
0
{
154
0
    msgpack::object obj;
155
0
    msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
156
0
    referenced = false;
157
0
    std::size_t noff = off;
158
0
    parse_return ret = detail::unpack_imp(
159
0
        data, len, noff, *z, obj, referenced, f, user_data, limit);
160
0
161
0
    switch(ret) {
162
0
    case PARSE_SUCCESS:
163
0
        off = noff;
164
0
        return msgpack::object_handle(obj, msgpack::move(z));
165
0
    case PARSE_EXTRA_BYTES:
166
0
        off = noff;
167
0
        return msgpack::object_handle(obj, msgpack::move(z));
168
0
    default:
169
0
        break;
170
0
    }
171
0
    return msgpack::object_handle();
172
0
}
173
174
inline msgpack::object_handle unpack(
175
    const char* data, std::size_t len, std::size_t& off,
176
    unpack_reference_func f, void* user_data,
177
    unpack_limit const& limit)
178
0
{
179
0
    bool referenced;
180
0
    return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit);
181
0
}
182
183
inline msgpack::object_handle unpack(
184
    const char* data, std::size_t len, bool& referenced,
185
    unpack_reference_func f, void* user_data,
186
    unpack_limit const& limit)
187
0
{
188
0
    std::size_t off = 0;
189
0
    return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit);
190
0
}
191
192
inline msgpack::object_handle unpack(
193
    const char* data, std::size_t len,
194
    unpack_reference_func f, void* user_data,
195
    unpack_limit const& limit)
196
0
{
197
0
    bool referenced;
198
0
    std::size_t off = 0;
199
0
    return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit);
200
0
}
201
202
inline void unpack(
203
    msgpack::object_handle& result,
204
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
205
    unpack_reference_func f, void* user_data,
206
    unpack_limit const& limit)
207
0
{
208
0
    msgpack::object obj;
209
0
    msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
210
0
    referenced = false;
211
0
    std::size_t noff = off;
212
0
    parse_return ret = detail::unpack_imp(
213
0
        data, len, noff, *z, obj, referenced, f, user_data, limit);
214
0
215
0
    switch(ret) {
216
0
    case PARSE_SUCCESS:
217
0
        off = noff;
218
0
        result.set(obj);
219
0
        result.zone() = msgpack::move(z);
220
0
        return;
221
0
    case PARSE_EXTRA_BYTES:
222
0
        off = noff;
223
0
        result.set(obj);
224
0
        result.zone() = msgpack::move(z);
225
0
        return;
226
0
    default:
227
0
        return;
228
0
    }
229
0
}
230
231
inline void unpack(
232
    msgpack::object_handle& result,
233
    const char* data, std::size_t len, std::size_t& off,
234
    unpack_reference_func f, void* user_data,
235
            unpack_limit const& limit)
236
0
{
237
0
    bool referenced;
238
0
    msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit);
239
0
}
240
241
inline void unpack(
242
    msgpack::object_handle& result,
243
    const char* data, std::size_t len, bool& referenced,
244
    unpack_reference_func f, void* user_data,
245
    unpack_limit const& limit)
246
0
{
247
0
    std::size_t off = 0;
248
0
    msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit);
249
0
}
250
251
inline void unpack(
252
    msgpack::object_handle& result,
253
    const char* data, std::size_t len,
254
    unpack_reference_func f, void* user_data,
255
    unpack_limit const& limit)
256
0
{
257
0
    bool referenced;
258
0
    std::size_t off = 0;
259
0
    msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit);
260
0
}
261
262
263
inline msgpack::object unpack(
264
    msgpack::zone& z,
265
    const char* data, std::size_t len, std::size_t& off, bool& referenced,
266
    unpack_reference_func f, void* user_data,
267
    unpack_limit const& limit)
268
0
{
269
0
    msgpack::object obj;
270
0
    std::size_t noff = off;
271
0
    referenced = false;
272
0
    parse_return ret = detail::unpack_imp(
273
0
        data, len, noff, z, obj, referenced, f, user_data, limit);
274
0
275
0
    switch(ret) {
276
0
    case PARSE_SUCCESS:
277
0
        off = noff;
278
0
        return obj;
279
0
    case PARSE_EXTRA_BYTES:
280
0
        off = noff;
281
0
        return obj;
282
0
    default:
283
0
        break;
284
0
    }
285
0
    return obj;
286
0
}
287
288
inline msgpack::object unpack(
289
    msgpack::zone& z,
290
    const char* data, std::size_t len, std::size_t& off,
291
    unpack_reference_func f, void* user_data,
292
    unpack_limit const& limit)
293
0
{
294
0
    bool referenced;
295
0
    return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit);
296
0
}
297
298
inline msgpack::object unpack(
299
    msgpack::zone& z,
300
    const char* data, std::size_t len, bool& referenced,
301
    unpack_reference_func f, void* user_data,
302
    unpack_limit const& limit)
303
0
{
304
0
    std::size_t off = 0;
305
0
    return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit);
306
0
}
307
308
inline msgpack::object unpack(
309
    msgpack::zone& z,
310
    const char* data, std::size_t len,
311
    unpack_reference_func f, void* user_data,
312
    unpack_limit const& limit)
313
0
{
314
0
    bool referenced;
315
0
    std::size_t off = 0;
316
0
    return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit);
317
0
}
318
319
namespace detail {
320
321
inline parse_return
322
unpack_imp(const char* data, std::size_t len, std::size_t& off,
323
           msgpack::zone& result_zone, msgpack::object& result, bool& referenced,
324
           unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR,
325
           unpack_limit const& limit = unpack_limit())
326
2.25k
{
327
2.25k
    create_object_visitor v(f, user_data, limit);
328
2.25k
    v.set_zone(result_zone);
329
2.25k
    referenced = false;
330
2.25k
    v.set_referenced(referenced);
331
2.25k
    parse_return ret = parse_imp(data, len, off, v);
332
2.25k
    referenced = v.referenced();
333
2.25k
    result = v.data();
334
2.25k
    return ret;
335
2.25k
}
336
337
} // namespace detail
338
339
340
/// @cond
341
}  // MSGPACK_API_VERSION_NAMESPACE(v2)
342
/// @endcond
343
344
}  // namespace msgpack
345
346
#endif // MSGPACK_DEFAULT_API_VERSION >= 2
347
348
#endif // MSGPACK_V2_UNPACK_HPP