Coverage Report

Created: 2023-09-25 06:13

/src/msgpack-c/include/msgpack/v2/create_object_visitor.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// MessagePack for C++ deserializing routine
3
//
4
// Copyright (C) 2017 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_CREATE_OBJECT_VISITOR_HPP
11
#define MSGPACK_V2_CREATE_OBJECT_VISITOR_HPP
12
13
#include "msgpack/unpack_decl.hpp"
14
#include "msgpack/unpack_exception.hpp"
15
#include "msgpack/v2/create_object_visitor_decl.hpp"
16
#include "msgpack/v2/null_visitor.hpp"
17
#include "msgpack/assert.hpp"
18
19
namespace msgpack {
20
21
/// @cond
22
MSGPACK_API_VERSION_NAMESPACE(v2) {
23
/// @endcond
24
25
namespace detail {
26
27
class create_object_visitor : public msgpack::v2::null_visitor {
28
public:
29
    create_object_visitor(unpack_reference_func f, void* user_data, unpack_limit const& limit)
30
2.25k
        :m_func(f), m_user_data(user_data), m_limit(limit) {
31
2.25k
        m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
32
2.25k
        m_stack.push_back(&m_obj);
33
2.25k
    }
34
35
#if !defined(MSGPACK_USE_CPP03)
36
    create_object_visitor(create_object_visitor&& other)
37
        :m_func(other.m_func),
38
         m_user_data(other.m_user_data),
39
         m_limit(std::move(other.m_limit)),
40
         m_stack(std::move(other.m_stack)),
41
         m_zone(other.m_zone),
42
0
         m_referenced(other.m_referenced) {
43
0
        other.m_zone = MSGPACK_NULLPTR;
44
0
        m_stack[0] = &m_obj;
45
0
    }
46
0
    create_object_visitor& operator=(create_object_visitor&& other) {
47
0
        this->~create_object_visitor();
48
0
        new (this) create_object_visitor(std::move(other));
49
0
        return *this;
50
0
    }
51
#endif // !defined(MSGPACK_USE_CPP03)
52
53
0
    void init() {
54
0
        m_stack.resize(1);
55
0
        m_obj = msgpack::object();
56
0
        m_stack[0] = &m_obj;
57
0
    }
58
    msgpack::object const& data() const
59
1.19k
    {
60
1.19k
        return m_obj;
61
1.19k
    }
62
0
    msgpack::zone const& zone() const { return *m_zone; }
63
72.8k
    msgpack::zone& zone() { return *m_zone; }
64
2.25k
    void set_zone(msgpack::zone& zone) { m_zone = &zone; }
65
1.19k
    bool referenced() const { return m_referenced; }
66
2.25k
    void set_referenced(bool referenced) { m_referenced = referenced; }
67
    // visit functions
68
4.70k
    bool visit_nil() {
69
4.70k
        msgpack::object* obj = m_stack.back();
70
4.70k
        obj->type = msgpack::type::NIL;
71
4.70k
        return true;
72
4.70k
    }
73
10.0k
    bool visit_boolean(bool v) {
74
10.0k
        msgpack::object* obj = m_stack.back();
75
10.0k
        obj->type = msgpack::type::BOOLEAN;
76
10.0k
        obj->via.boolean = v;
77
10.0k
        return true;
78
10.0k
    }
79
815k
    bool visit_positive_integer(uint64_t v) {
80
815k
        msgpack::object* obj = m_stack.back();
81
815k
        obj->type = msgpack::type::POSITIVE_INTEGER;
82
815k
        obj->via.u64 = v;
83
815k
        return true;
84
815k
    }
85
200k
    bool visit_negative_integer(int64_t v) {
86
200k
        msgpack::object* obj = m_stack.back();
87
200k
        if(v >= 0) {
88
2.62k
            obj->type = msgpack::type::POSITIVE_INTEGER;
89
2.62k
            obj->via.u64 = static_cast<uint64_t>(v);
90
2.62k
        }
91
198k
        else {
92
198k
            obj->type = msgpack::type::NEGATIVE_INTEGER;
93
198k
            obj->via.i64 = v;
94
198k
        }
95
200k
        return true;
96
200k
    }
97
488k
    bool visit_float32(float v) {
98
488k
        msgpack::object* obj = m_stack.back();
99
488k
        obj->type = msgpack::type::FLOAT32;
100
488k
        obj->via.f64 = v;
101
488k
        return true;
102
488k
    }
103
29.1k
    bool visit_float64(double v) {
104
29.1k
        msgpack::object* obj = m_stack.back();
105
29.1k
        obj->type = msgpack::type::FLOAT64;
106
29.1k
        obj->via.f64 = v;
107
29.1k
        return true;
108
29.1k
    }
109
30.7k
    bool visit_str(const char* v, uint32_t size) {
110
30.7k
        MSGPACK_ASSERT(v || size == 0);
111
30.7k
        if (size > m_limit.str()) throw msgpack::str_size_overflow("str size overflow");
112
30.7k
        msgpack::object* obj = m_stack.back();
113
30.7k
        obj->type = msgpack::type::STR;
114
30.7k
        if (m_func && m_func(obj->type, size, m_user_data)) {
115
0
            obj->via.str.ptr = v;
116
0
            obj->via.str.size = size;
117
0
            set_referenced(true);
118
0
        }
119
30.7k
        else {
120
30.7k
            if (v) {
121
30.0k
                char* tmp = static_cast<char*>(zone().allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
122
30.0k
                std::memcpy(tmp, v, size);
123
30.0k
                obj->via.str.ptr = tmp;
124
30.0k
                obj->via.str.size = size;
125
30.0k
            }
126
706
            else {
127
706
                obj->via.str.ptr = MSGPACK_NULLPTR;
128
706
                obj->via.str.size = 0;
129
706
            }
130
30.7k
        }
131
30.7k
        return true;
132
30.7k
    }
133
6.46k
    bool visit_bin(const char* v, uint32_t size) {
134
6.46k
        MSGPACK_ASSERT(v || size == 0);
135
6.46k
        if (size > m_limit.bin()) throw msgpack::bin_size_overflow("bin size overflow");
136
6.46k
        msgpack::object* obj = m_stack.back();
137
6.46k
        obj->type = msgpack::type::BIN;
138
6.46k
        if (m_func && m_func(obj->type, size, m_user_data)) {
139
0
            obj->via.bin.ptr = v;
140
0
            obj->via.bin.size = size;
141
0
            set_referenced(true);
142
0
        }
143
6.46k
        else {
144
6.46k
            if (v) {
145
6.46k
                char* tmp = static_cast<char*>(zone().allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
146
6.46k
                std::memcpy(tmp, v, size);
147
6.46k
                obj->via.bin.ptr = tmp;
148
6.46k
                obj->via.bin.size = size;
149
6.46k
            }
150
0
            else {
151
0
                obj->via.bin.ptr = MSGPACK_NULLPTR;
152
0
                obj->via.bin.size = 0;
153
0
            }
154
6.46k
        }
155
6.46k
        return true;
156
6.46k
    }
157
36.3k
    bool visit_ext(const char* v, uint32_t size) {
158
36.3k
        MSGPACK_ASSERT(v || size == 0);
159
36.3k
        if (size > m_limit.ext()) throw msgpack::ext_size_overflow("ext size overflow");
160
36.3k
        msgpack::object* obj = m_stack.back();
161
36.3k
        obj->type = msgpack::type::EXT;
162
36.3k
        if (m_func && m_func(obj->type, size, m_user_data)) {
163
0
            obj->via.ext.ptr = v;
164
0
            obj->via.ext.size = static_cast<uint32_t>(size - 1);
165
0
            set_referenced(true);
166
0
        }
167
36.3k
        else {
168
36.3k
            if (v) {
169
36.3k
                char* tmp = static_cast<char*>(zone().allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
170
36.3k
                std::memcpy(tmp, v, size);
171
36.3k
                obj->via.ext.ptr = tmp;
172
36.3k
                obj->via.ext.size = static_cast<uint32_t>(size - 1);
173
36.3k
            }
174
0
            else {
175
0
                obj->via.ext.ptr = MSGPACK_NULLPTR;
176
0
                obj->via.ext.size = 0;
177
0
            }
178
36.3k
        }
179
36.3k
        return true;
180
36.3k
    }
181
177k
    bool start_array(uint32_t num_elements) {
182
177k
        if (num_elements > m_limit.array()) throw msgpack::array_size_overflow("array size overflow");
183
177k
        if (m_stack.size() > m_limit.depth()) throw msgpack::depth_size_overflow("depth size overflow");
184
177k
        msgpack::object* obj = m_stack.back();
185
177k
        obj->type = msgpack::type::ARRAY;
186
177k
        obj->via.array.size = num_elements;
187
177k
        if (num_elements == 0) {
188
31.8k
            obj->via.array.ptr = MSGPACK_NULLPTR;
189
31.8k
        }
190
145k
        else {
191
192
#if SIZE_MAX == UINT_MAX
193
            if (num_elements > SIZE_MAX/sizeof(msgpack::object))
194
                throw msgpack::array_size_overflow("array size overflow");
195
#endif // SIZE_MAX == UINT_MAX
196
197
145k
            size_t size = num_elements*sizeof(msgpack::object);
198
145k
            obj->via.array.ptr =
199
145k
                static_cast<msgpack::object*>(m_zone->allocate_align(size, MSGPACK_ZONE_ALIGNOF(msgpack::object)));
200
145k
        }
201
177k
        m_stack.push_back(obj->via.array.ptr);
202
177k
        return true;
203
177k
    }
204
752k
    bool start_array_item() {
205
752k
        return true;
206
752k
    }
207
743k
    bool end_array_item() {
208
743k
        ++m_stack.back();
209
743k
        return true;
210
743k
    }
211
168k
    bool end_array() {
212
168k
        m_stack.pop_back();
213
168k
        return true;
214
168k
    }
215
246k
    bool start_map(uint32_t num_kv_pairs) {
216
246k
        if (num_kv_pairs > m_limit.map()) throw msgpack::map_size_overflow("map size overflow");
217
246k
        if (m_stack.size() > m_limit.depth()) throw msgpack::depth_size_overflow("depth size overflow");
218
246k
        msgpack::object* obj = m_stack.back();
219
246k
        obj->type = msgpack::type::MAP;
220
246k
        obj->via.map.size = num_kv_pairs;
221
246k
        if (num_kv_pairs == 0) {
222
32.2k
            obj->via.map.ptr = MSGPACK_NULLPTR;
223
32.2k
        }
224
214k
        else {
225
226
#if SIZE_MAX == UINT_MAX
227
            if (num_kv_pairs > SIZE_MAX/sizeof(msgpack::object_kv))
228
                throw msgpack::map_size_overflow("map size overflow");
229
#endif // SIZE_MAX == UINT_MAX
230
214k
            size_t size = num_kv_pairs*sizeof(msgpack::object_kv);
231
214k
            obj->via.map.ptr =
232
214k
                static_cast<msgpack::object_kv*>(m_zone->allocate_align(size, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv)));
233
214k
        }
234
246k
        m_stack.push_back(reinterpret_cast<msgpack::object*>(obj->via.map.ptr));
235
246k
        return true;
236
246k
    }
237
649k
    bool start_map_key() {
238
649k
        return true;
239
649k
    }
240
643k
    bool end_map_key() {
241
643k
        ++m_stack.back();
242
643k
        return true;
243
643k
    }
244
643k
    bool start_map_value() {
245
643k
        return true;
246
643k
    }
247
642k
    bool end_map_value() {
248
642k
        ++m_stack.back();
249
642k
        return true;
250
642k
    }
251
239k
    bool end_map() {
252
239k
        m_stack.pop_back();
253
239k
        return true;
254
239k
    }
255
1
    void parse_error(size_t /*parsed_offset*/, size_t /*error_offset*/) {
256
1
        throw msgpack::parse_error("parse error");
257
1
    }
258
942
    void insufficient_bytes(size_t /*parsed_offset*/, size_t /*error_offset*/) {
259
942
        throw msgpack::insufficient_bytes("insufficient bytes");
260
942
    }
261
private:
262
public:
263
    unpack_reference_func m_func;
264
    void* m_user_data;
265
    unpack_limit m_limit;
266
    msgpack::object m_obj;
267
    std::vector<msgpack::object*> m_stack;
268
    msgpack::zone* m_zone;
269
    bool m_referenced;
270
};
271
272
} // detail
273
274
/// @cond
275
}  // MSGPACK_API_VERSION_NAMESPACE(v2)
276
/// @endcond
277
278
}  // namespace msgpack
279
280
#endif // MSGPACK_V2_CREATE_OBJECT_VISITOR_HPP