/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 |