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