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