MessagePack for C++
Loading...
Searching...
No Matches
parse.hpp
Go to the documentation of this file.
1//
2// MessagePack for C++ deserializing routine
3//
4// Copyright (C) 2016-2017 KONDO Takatoshi
5//
6// Distributed under the Boost Software License, Version 1.0.
7// (See accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9//
10#ifndef MSGPACK_V2_PARSE_HPP
11#define MSGPACK_V2_PARSE_HPP
12
13#if MSGPACK_DEFAULT_API_VERSION >= 2
14
15#include <cstddef>
16#include <limits>
17#include <new>
18
23#include "msgpack/assert.hpp"
24
25namespace msgpack {
26
30
31namespace detail {
32
33using v1::detail::fix_tag;
34using v1::detail::value;
35using v1::detail::load;
36
37template <typename VisitorHolder>
38class context {
39public:
40 context()
41 :m_trail(0), m_cs(MSGPACK_CS_HEADER)
42 {
43 }
44
45 void init()
46 {
47 m_cs = MSGPACK_CS_HEADER;
48 m_trail = 0;
49 m_stack.clear();
50 holder().visitor().init();
51 }
52
53 parse_return execute(const char* data, std::size_t len, std::size_t& off);
54
55private:
56 template <typename T>
57 static uint32_t next_cs(T p)
58 {
59 return static_cast<uint32_t>(*p) & 0x1f;
60 }
61
62 VisitorHolder& holder() {
63 return static_cast<VisitorHolder&>(*this);
64 }
65
66 template <typename T, typename StartVisitor, typename EndVisitor>
67 parse_return start_aggregate(
68 StartVisitor const& sv,
69 EndVisitor const& ev,
70 const char* load_pos,
71 std::size_t& off) {
72 typename value<T>::type size;
73 load<T>(size, load_pos);
74 ++m_current;
75 if (size == 0) {
76 if (!sv(size)) {
77 off = static_cast<std::size_t>(m_current - m_start);
78 return PARSE_STOP_VISITOR;
79 }
80 if (!ev()) {
81 off = static_cast<std::size_t>(m_current - m_start);
82 return PARSE_STOP_VISITOR;
83 }
84 parse_return ret = m_stack.consume(holder());
85 if (ret != PARSE_CONTINUE) {
86 off = static_cast<std::size_t>(m_current - m_start);
87 return ret;
88 }
89 }
90 else {
91 if (!sv(size)) {
92 off = static_cast<std::size_t>(m_current - m_start);
93 return PARSE_STOP_VISITOR;
94 }
95 parse_return ret = m_stack.push(holder(), sv.type(), static_cast<uint32_t>(size));
96 if (ret != PARSE_CONTINUE) {
97 off = static_cast<std::size_t>(m_current - m_start);
98 return ret;
99 }
100 }
101 m_cs = MSGPACK_CS_HEADER;
102 return PARSE_CONTINUE;
103 }
104
105 parse_return after_visit_proc(bool visit_result, std::size_t& off) {
106 ++m_current;
107 if (!visit_result) {
108 off = static_cast<std::size_t>(m_current - m_start);
109 return PARSE_STOP_VISITOR;
110 }
111 parse_return ret = m_stack.consume(holder());
112 if (ret != PARSE_CONTINUE) {
113 off = static_cast<std::size_t>(m_current - m_start);
114 }
115 m_cs = MSGPACK_CS_HEADER;
116 return ret;
117 }
118
119 struct array_sv {
120 array_sv(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
121 bool operator()(uint32_t size) const {
122 return m_visitor_holder.visitor().start_array(size);
123 }
124 msgpack_container_type type() const { return MSGPACK_CT_ARRAY_ITEM; }
125 private:
126 VisitorHolder& m_visitor_holder;
127 };
128 struct array_ev {
129 array_ev(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
130 bool operator()() const {
131 return m_visitor_holder.visitor().end_array();
132 }
133 private:
134 VisitorHolder& m_visitor_holder;
135 };
136 struct map_sv {
137 map_sv(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
138 bool operator()(uint32_t size) const {
139 return m_visitor_holder.visitor().start_map(size);
140 }
141 msgpack_container_type type() const { return MSGPACK_CT_MAP_KEY; }
142 private:
143 VisitorHolder& m_visitor_holder;
144 };
145 struct map_ev {
146 map_ev(VisitorHolder& visitor_holder):m_visitor_holder(visitor_holder) {}
147 bool operator()() const {
148 return m_visitor_holder.visitor().end_map();
149 }
150 private:
151 VisitorHolder& m_visitor_holder;
152 };
153
154 struct unpack_stack {
155 struct stack_elem {
156 stack_elem(msgpack_container_type type, uint32_t rest):m_type(type), m_rest(rest) {}
158 uint32_t m_rest;
159 };
160 unpack_stack() {
161 m_stack.reserve(MSGPACK_EMBED_STACK_SIZE);
162 }
163 parse_return push(VisitorHolder& visitor_holder, msgpack_container_type type, uint32_t rest) {
164 m_stack.push_back(stack_elem(type, rest));
165 switch (type) {
167 return visitor_holder.visitor().start_array_item() ? PARSE_CONTINUE : PARSE_STOP_VISITOR;
169 return visitor_holder.visitor().start_map_key() ? PARSE_CONTINUE : PARSE_STOP_VISITOR;
172 return PARSE_STOP_VISITOR;
173 }
175 return PARSE_STOP_VISITOR;
176 }
177 parse_return consume(VisitorHolder& visitor_holder) {
178 while (!m_stack.empty()) {
179 stack_elem& e = m_stack.back();
180 switch (e.m_type) {
182 if (!visitor_holder.visitor().end_array_item()) return PARSE_STOP_VISITOR;
183 if (--e.m_rest == 0) {
184 m_stack.pop_back();
185 if (!visitor_holder.visitor().end_array()) return PARSE_STOP_VISITOR;
186 }
187 else {
188 if (!visitor_holder.visitor().start_array_item()) return PARSE_STOP_VISITOR;
189 return PARSE_CONTINUE;
190 }
191 break;
193 if (!visitor_holder.visitor().end_map_key()) return PARSE_STOP_VISITOR;
194 if (!visitor_holder.visitor().start_map_value()) return PARSE_STOP_VISITOR;
195 e.m_type = MSGPACK_CT_MAP_VALUE;
196 return PARSE_CONTINUE;
198 if (!visitor_holder.visitor().end_map_value()) return PARSE_STOP_VISITOR;
199 if (--e.m_rest == 0) {
200 m_stack.pop_back();
201 if (!visitor_holder.visitor().end_map()) return PARSE_STOP_VISITOR;
202 }
203 else {
204 e.m_type = MSGPACK_CT_MAP_KEY;
205 if (!visitor_holder.visitor().start_map_key()) return PARSE_STOP_VISITOR;
206 return PARSE_CONTINUE;
207 }
208 break;
209 }
210 }
211 return PARSE_SUCCESS;
212 }
213 bool empty() const { return m_stack.empty(); }
214 void clear() { m_stack.clear(); }
215 private:
216 std::vector<stack_elem> m_stack;
217 };
218
219 char const* m_start;
220 char const* m_current;
221
222 std::size_t m_trail;
223 uint32_t m_cs;
224 uint32_t m_num_elements;
225 unpack_stack m_stack;
226};
227
228template <std::size_t N>
229inline void check_ext_size(std::size_t /*size*/) {
230}
231
232template <>
233inline void check_ext_size<4>(std::size_t size) {
234 if (size == 0xffffffff) throw msgpack::ext_size_overflow("ext size overflow");
235}
236
237template <typename VisitorHolder>
238inline parse_return context<VisitorHolder>::execute(const char* data, std::size_t len, std::size_t& off)
239{
240 MSGPACK_ASSERT(len >= off);
241
242 m_start = data;
243 m_current = data + off;
244 const char* const pe = data + len;
245 const char* n = MSGPACK_NULLPTR;
246
247 if(m_current == pe) {
248 off = static_cast<std::size_t>(m_current - m_start);
249 return PARSE_CONTINUE;
250 }
251 bool fixed_trail_again = false;
252 do {
253 if (m_cs == MSGPACK_CS_HEADER) {
254 fixed_trail_again = false;
255 int selector = *reinterpret_cast<const unsigned char*>(m_current);
256 if (0x00 <= selector && selector <= 0x7f) { // Positive Fixnum
257 uint8_t tmp = *reinterpret_cast<const uint8_t*>(m_current);
258 bool visret = holder().visitor().visit_positive_integer(tmp);
259 parse_return upr = after_visit_proc(visret, off);
260 if (upr != PARSE_CONTINUE) return upr;
261 } else if(0xe0 <= selector && selector <= 0xff) { // Negative Fixnum
262 int8_t tmp = *reinterpret_cast<const int8_t*>(m_current);
263 bool visret = holder().visitor().visit_negative_integer(tmp);
264 parse_return upr = after_visit_proc(visret, off);
265 if (upr != PARSE_CONTINUE) return upr;
266 } else if (0xc4 <= selector && selector <= 0xdf) {
267 const uint32_t trail[] = {
268 1, // bin 8 0xc4
269 2, // bin 16 0xc5
270 4, // bin 32 0xc6
271 1, // ext 8 0xc7
272 2, // ext 16 0xc8
273 4, // ext 32 0xc9
274 4, // float 32 0xca
275 8, // float 64 0xcb
276 1, // uint 8 0xcc
277 2, // uint 16 0xcd
278 4, // uint 32 0xce
279 8, // uint 64 0xcf
280 1, // int 8 0xd0
281 2, // int 16 0xd1
282 4, // int 32 0xd2
283 8, // int 64 0xd3
284 2, // fixext 1 0xd4
285 3, // fixext 2 0xd5
286 5, // fixext 4 0xd6
287 9, // fixext 8 0xd7
288 17,// fixext 16 0xd8
289 1, // str 8 0xd9
290 2, // str 16 0xda
291 4, // str 32 0xdb
292 2, // array 16 0xdc
293 4, // array 32 0xdd
294 2, // map 16 0xde
295 4, // map 32 0xdf
296 };
297 m_trail = trail[selector - 0xc4];
298 m_cs = next_cs(m_current);
299 fixed_trail_again = true;
300 } else if(0xa0 <= selector && selector <= 0xbf) { // FixStr
301 m_trail = static_cast<uint32_t>(*m_current) & 0x1f;
302 if(m_trail == 0) {
303 bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
304 parse_return upr = after_visit_proc(visret, off);
305 if (upr != PARSE_CONTINUE) return upr;
306 }
307 else {
309 fixed_trail_again = true;
310 }
311 } else if(0x90 <= selector && selector <= 0x9f) { // FixArray
312 parse_return ret = start_aggregate<fix_tag>(array_sv(holder()), array_ev(holder()), m_current, off);
313 if (ret != PARSE_CONTINUE) return ret;
314 } else if(0x80 <= selector && selector <= 0x8f) { // FixMap
315 parse_return ret = start_aggregate<fix_tag>(map_sv(holder()), map_ev(holder()), m_current, off);
316 if (ret != PARSE_CONTINUE) return ret;
317 } else if(selector == 0xc2) { // false
318 bool visret = holder().visitor().visit_boolean(false);
319 parse_return upr = after_visit_proc(visret, off);
320 if (upr != PARSE_CONTINUE) return upr;
321 } else if(selector == 0xc3) { // true
322 bool visret = holder().visitor().visit_boolean(true);
323 parse_return upr = after_visit_proc(visret, off);
324 if (upr != PARSE_CONTINUE) return upr;
325 } else if(selector == 0xc0) { // nil
326 bool visret = holder().visitor().visit_nil();
327 parse_return upr = after_visit_proc(visret, off);
328 if (upr != PARSE_CONTINUE) return upr;
329 } else {
330 off = static_cast<std::size_t>(m_current - m_start);
331 holder().visitor().parse_error(off - 1, off);
332 return PARSE_PARSE_ERROR;
333 }
334 // end MSGPACK_CS_HEADER
335 }
336 if (m_cs != MSGPACK_CS_HEADER || fixed_trail_again) {
337 if (fixed_trail_again) {
338 ++m_current;
339 fixed_trail_again = false;
340 }
341 if(static_cast<std::size_t>(pe - m_current) < m_trail) {
342 off = static_cast<std::size_t>(m_current - m_start);
343 return PARSE_CONTINUE;
344 }
345 n = m_current;
346 m_current += m_trail - 1;
347 switch(m_cs) {
348 //case MSGPACK_CS_
349 //case MSGPACK_CS_
350 case MSGPACK_CS_FLOAT: {
351 union { uint32_t i; float f; } mem;
352 load<uint32_t>(mem.i, n);
353 bool visret = holder().visitor().visit_float32(mem.f);
354 parse_return upr = after_visit_proc(visret, off);
355 if (upr != PARSE_CONTINUE) return upr;
356 } break;
357 case MSGPACK_CS_DOUBLE: {
358 union { uint64_t i; double f; } mem;
359 load<uint64_t>(mem.i, n);
360#if defined(TARGET_OS_IPHONE)
361 // ok
362#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
363 // https://github.com/msgpack/msgpack-perl/pull/1
364 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
365#endif
366 bool visret = holder().visitor().visit_float64(mem.f);
367 parse_return upr = after_visit_proc(visret, off);
368 if (upr != PARSE_CONTINUE) return upr;
369 } break;
370 case MSGPACK_CS_UINT_8: {
371 uint8_t tmp;
372 load<uint8_t>(tmp, n);
373 bool visret = holder().visitor().visit_positive_integer(tmp);
374 parse_return upr = after_visit_proc(visret, off);
375 if (upr != PARSE_CONTINUE) return upr;
376 } break;
377 case MSGPACK_CS_UINT_16: {
378 uint16_t tmp;
379 load<uint16_t>(tmp, n);
380 bool visret = holder().visitor().visit_positive_integer(tmp);
381 parse_return upr = after_visit_proc(visret, off);
382 if (upr != PARSE_CONTINUE) return upr;
383 } break;
384 case MSGPACK_CS_UINT_32: {
385 uint32_t tmp;
386 load<uint32_t>(tmp, n);
387 bool visret = holder().visitor().visit_positive_integer(tmp);
388 parse_return upr = after_visit_proc(visret, off);
389 if (upr != PARSE_CONTINUE) return upr;
390 } break;
391 case MSGPACK_CS_UINT_64: {
392 uint64_t tmp;
393 load<uint64_t>(tmp, n);
394 bool visret = holder().visitor().visit_positive_integer(tmp);
395 parse_return upr = after_visit_proc(visret, off);
396 if (upr != PARSE_CONTINUE) return upr;
397 } break;
398 case MSGPACK_CS_INT_8: {
399 int8_t tmp;
400 load<int8_t>(tmp, n);
401 bool visret = holder().visitor().visit_negative_integer(tmp);
402 parse_return upr = after_visit_proc(visret, off);
403 if (upr != PARSE_CONTINUE) return upr;
404 } break;
405 case MSGPACK_CS_INT_16: {
406 int16_t tmp;
407 load<int16_t>(tmp, n);
408 bool visret = holder().visitor().visit_negative_integer(tmp);
409 parse_return upr = after_visit_proc(visret, off);
410 if (upr != PARSE_CONTINUE) return upr;
411 } break;
412 case MSGPACK_CS_INT_32: {
413 int32_t tmp;
414 load<int32_t>(tmp, n);
415 bool visret = holder().visitor().visit_negative_integer(tmp);
416 parse_return upr = after_visit_proc(visret, off);
417 if (upr != PARSE_CONTINUE) return upr;
418 } break;
419 case MSGPACK_CS_INT_64: {
420 int64_t tmp;
421 load<int64_t>(tmp, n);
422 bool visret = holder().visitor().visit_negative_integer(tmp);
423 parse_return upr = after_visit_proc(visret, off);
424 if (upr != PARSE_CONTINUE) return upr;
425 } break;
426 case MSGPACK_CS_FIXEXT_1: {
427 bool visret = holder().visitor().visit_ext(n, 1+1);
428 parse_return upr = after_visit_proc(visret, off);
429 if (upr != PARSE_CONTINUE) return upr;
430 } break;
431 case MSGPACK_CS_FIXEXT_2: {
432 bool visret = holder().visitor().visit_ext(n, 2+1);
433 parse_return upr = after_visit_proc(visret, off);
434 if (upr != PARSE_CONTINUE) return upr;
435 } break;
436 case MSGPACK_CS_FIXEXT_4: {
437 bool visret = holder().visitor().visit_ext(n, 4+1);
438 parse_return upr = after_visit_proc(visret, off);
439 if (upr != PARSE_CONTINUE) return upr;
440 } break;
441 case MSGPACK_CS_FIXEXT_8: {
442 bool visret = holder().visitor().visit_ext(n, 8+1);
443 parse_return upr = after_visit_proc(visret, off);
444 if (upr != PARSE_CONTINUE) return upr;
445 } break;
447 bool visret = holder().visitor().visit_ext(n, 16+1);
448 parse_return upr = after_visit_proc(visret, off);
449 if (upr != PARSE_CONTINUE) return upr;
450 } break;
451 case MSGPACK_CS_STR_8: {
452 uint8_t tmp;
453 load<uint8_t>(tmp, n);
454 m_trail = tmp;
455 if(m_trail == 0) {
456 bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
457 parse_return upr = after_visit_proc(visret, off);
458 if (upr != PARSE_CONTINUE) return upr;
459 }
460 else {
462 fixed_trail_again = true;
463 }
464 } break;
465 case MSGPACK_CS_BIN_8: {
466 uint8_t tmp;
467 load<uint8_t>(tmp, n);
468 m_trail = tmp;
469 if(m_trail == 0) {
470 bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
471 parse_return upr = after_visit_proc(visret, off);
472 if (upr != PARSE_CONTINUE) return upr;
473 }
474 else {
476 fixed_trail_again = true;
477 }
478 } break;
479 case MSGPACK_CS_EXT_8: {
480 uint8_t tmp;
481 load<uint8_t>(tmp, n);
482 m_trail = tmp + 1;
483 if(m_trail == 0) {
484 bool visret = holder().visitor().visit_ext(n, m_trail);
485 parse_return upr = after_visit_proc(visret, off);
486 if (upr != PARSE_CONTINUE) return upr;
487 }
488 else {
490 fixed_trail_again = true;
491 }
492 } break;
493 case MSGPACK_CS_STR_16: {
494 uint16_t tmp;
495 load<uint16_t>(tmp, n);
496 m_trail = tmp;
497 if(m_trail == 0) {
498 bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
499 parse_return upr = after_visit_proc(visret, off);
500 if (upr != PARSE_CONTINUE) return upr;
501 }
502 else {
504 fixed_trail_again = true;
505 }
506 } break;
507 case MSGPACK_CS_BIN_16: {
508 uint16_t tmp;
509 load<uint16_t>(tmp, n);
510 m_trail = tmp;
511 if(m_trail == 0) {
512 bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
513 parse_return upr = after_visit_proc(visret, off);
514 if (upr != PARSE_CONTINUE) return upr;
515 }
516 else {
518 fixed_trail_again = true;
519 }
520 } break;
521 case MSGPACK_CS_EXT_16: {
522 uint16_t tmp;
523 load<uint16_t>(tmp, n);
524 m_trail = tmp + 1;
525 if(m_trail == 0) {
526 bool visret = holder().visitor().visit_ext(n, m_trail);
527 parse_return upr = after_visit_proc(visret, off);
528 if (upr != PARSE_CONTINUE) return upr;
529 }
530 else {
532 fixed_trail_again = true;
533 }
534 } break;
535 case MSGPACK_CS_STR_32: {
536 uint32_t tmp;
537 load<uint32_t>(tmp, n);
538 m_trail = tmp;
539 if(m_trail == 0) {
540 bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
541 parse_return upr = after_visit_proc(visret, off);
542 if (upr != PARSE_CONTINUE) return upr;
543 }
544 else {
546 fixed_trail_again = true;
547 }
548 } break;
549 case MSGPACK_CS_BIN_32: {
550 uint32_t tmp;
551 load<uint32_t>(tmp, n);
552 m_trail = tmp;
553 if(m_trail == 0) {
554 bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
555 parse_return upr = after_visit_proc(visret, off);
556 if (upr != PARSE_CONTINUE) return upr;
557 }
558 else {
560 fixed_trail_again = true;
561 }
562 } break;
563 case MSGPACK_CS_EXT_32: {
564 uint32_t tmp;
565 load<uint32_t>(tmp, n);
566 check_ext_size<sizeof(std::size_t)>(tmp);
567 m_trail = tmp;
568 ++m_trail;
569 if(m_trail == 0) {
570 bool visret = holder().visitor().visit_ext(n, m_trail);
571 parse_return upr = after_visit_proc(visret, off);
572 if (upr != PARSE_CONTINUE) return upr;
573 }
574 else {
576 fixed_trail_again = true;
577 }
578 } break;
580 bool visret = holder().visitor().visit_str(n, static_cast<uint32_t>(m_trail));
581 parse_return upr = after_visit_proc(visret, off);
582 if (upr != PARSE_CONTINUE) return upr;
583 } break;
585 bool visret = holder().visitor().visit_bin(n, static_cast<uint32_t>(m_trail));
586 parse_return upr = after_visit_proc(visret, off);
587 if (upr != PARSE_CONTINUE) return upr;
588 } break;
590 bool visret = holder().visitor().visit_ext(n, m_trail);
591 parse_return upr = after_visit_proc(visret, off);
592 if (upr != PARSE_CONTINUE) return upr;
593 } break;
594 case MSGPACK_CS_ARRAY_16: {
595 parse_return ret = start_aggregate<uint16_t>(array_sv(holder()), array_ev(holder()), n, off);
596 if (ret != PARSE_CONTINUE) return ret;
597
598 } break;
599 case MSGPACK_CS_ARRAY_32: {
600 parse_return ret = start_aggregate<uint32_t>(array_sv(holder()), array_ev(holder()), n, off);
601 if (ret != PARSE_CONTINUE) return ret;
602 } break;
603 case MSGPACK_CS_MAP_16: {
604 parse_return ret = start_aggregate<uint16_t>(map_sv(holder()), map_ev(holder()), n, off);
605 if (ret != PARSE_CONTINUE) return ret;
606 } break;
607 case MSGPACK_CS_MAP_32: {
608 parse_return ret = start_aggregate<uint32_t>(map_sv(holder()), map_ev(holder()), n, off);
609 if (ret != PARSE_CONTINUE) return ret;
610 } break;
611 default:
612 off = static_cast<std::size_t>(m_current - m_start);
613 holder().visitor().parse_error(static_cast<std::size_t>(n - m_start - 1), static_cast<std::size_t>(n - m_start));
614 return PARSE_PARSE_ERROR;
615 }
616 }
617 } while(m_current != pe);
618
619 off = static_cast<std::size_t>(m_current - m_start);
620 return PARSE_CONTINUE;
621}
622
623} // detail
624
625
627
628template <typename VisitorHolder, typename ReferencedBufferHook>
629class parser : public detail::context<VisitorHolder> {
630 typedef parser<VisitorHolder, ReferencedBufferHook> this_type;
631 typedef detail::context<VisitorHolder> context_type;
632public:
634
642 parser(ReferencedBufferHook& hook,
643 std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
644
645#if !defined(MSGPACK_USE_CPP03)
646 parser(this_type&& other);
647 this_type& operator=(this_type&& other);
648#endif // !defined(MSGPACK_USE_CPP03)
649
650 ~parser();
651
652public:
654
661 void reserve_buffer(std::size_t size = MSGPACK_UNPACKER_RESERVE_SIZE);
662
664
669 char* buffer();
670
672
678 std::size_t buffer_capacity() const;
679
681
690 void buffer_consumed(std::size_t size);
691
693
703 bool next();
704
706
709 std::size_t message_size() const;
710
711public:
713
719 std::size_t parsed_size() const;
720
722
728 char* nonparsed_buffer();
729
731
737 std::size_t nonparsed_size() const;
738
740
747 void skip_nonparsed_buffer(std::size_t size);
748
750
754 void remove_nonparsed_buffer();
755
756 void reset();
757
758protected:
759 char* get_raw_buffer() {
760 return m_buffer;
761 }
762private:
763 void expand_buffer(std::size_t size);
764 parse_return execute_imp();
765
766protected:
767 // Re-point the buffer-hook, e.g. after a move of the owning object so that
768 // the hook refers to the moved-to object's member rather than the
769 // moved-from (soon to be destroyed) object's member.
770 void set_referenced_buffer_hook(ReferencedBufferHook& hook) {
771 m_referenced_buffer_hook = &hook;
772 }
773
774private:
775 char* m_buffer;
776 std::size_t m_used;
777 std::size_t m_free;
778 std::size_t m_off;
779 std::size_t m_parsed;
780 std::size_t m_initial_buffer_size;
781 ReferencedBufferHook* m_referenced_buffer_hook;
782
783#if defined(MSGPACK_USE_CPP03)
784private:
785 parser(const this_type&);
786 this_type& operator=(const this_type&);
787#else // defined(MSGPACK_USE_CPP03)
788public:
789 parser(const this_type&) = delete;
790 this_type& operator=(const this_type&) = delete;
791#endif // defined(MSGPACK_USE_CPP03)
792};
793
794template <typename VisitorHolder, typename ReferencedBufferHook>
796 ReferencedBufferHook& hook,
797 std::size_t initial_buffer_size)
798 :m_referenced_buffer_hook(&hook)
799{
800 if(initial_buffer_size < COUNTER_SIZE) {
801 initial_buffer_size = COUNTER_SIZE;
802 }
803
804 char* buffer = static_cast<char*>(::malloc(initial_buffer_size));
805 if(!buffer) {
806 throw std::bad_alloc();
807 }
808
809 m_buffer = buffer;
810 m_used = COUNTER_SIZE;
811 m_free = initial_buffer_size - m_used;
812 m_off = COUNTER_SIZE;
813 m_parsed = 0;
814 m_initial_buffer_size = initial_buffer_size;
815
816 detail::init_count(m_buffer);
817}
818
819#if !defined(MSGPACK_USE_CPP03)
820// Move constructor and move assignment operator
821
822template <typename VisitorHolder, typename ReferencedBufferHook>
823inline parser<VisitorHolder, ReferencedBufferHook>::parser(this_type&& other)
824 :context_type(std::move(other)),
825 m_buffer(other.m_buffer),
826 m_used(other.m_used),
827 m_free(other.m_free),
828 m_off(other.m_off),
829 m_parsed(other.m_parsed),
830 m_initial_buffer_size(other.m_initial_buffer_size),
831 m_referenced_buffer_hook(other.m_referenced_buffer_hook) {
832 other.m_buffer = MSGPACK_NULLPTR;
833 other.m_used = 0;
834 other.m_free = 0;
835 other.m_off = 0;
836 other.m_parsed = 0;
837}
838
839template <typename VisitorHolder, typename ReferencedBufferHook>
840inline parser<VisitorHolder, ReferencedBufferHook>& parser<VisitorHolder, ReferencedBufferHook>::operator=(this_type&& other) {
841 if (this != &other) {
842 this->~parser();
843 new (this) this_type(std::move(other));
844 }
845 return *this;
846}
847
848#endif // !defined(MSGPACK_USE_CPP03)
849
850
851template <typename VisitorHolder, typename ReferencedBufferHook>
852inline parser<VisitorHolder, ReferencedBufferHook>::~parser()
853{
854 // These checks are required for move operations.
855 if (m_buffer) detail::decr_count(m_buffer);
856}
857
858
859template <typename VisitorHolder, typename ReferencedBufferHook>
860inline void parser<VisitorHolder, ReferencedBufferHook>::reserve_buffer(std::size_t size)
861{
862 if(m_free >= size) return;
863 expand_buffer(size);
864}
865
866template <typename VisitorHolder, typename ReferencedBufferHook>
867inline void parser<VisitorHolder, ReferencedBufferHook>::expand_buffer(std::size_t size)
868{
869 if(m_used == m_off && detail::get_count(m_buffer) == 1
870 && !static_cast<VisitorHolder&>(*this).visitor().referenced()) {
871 // rewind buffer
872 m_free += m_used - COUNTER_SIZE;
873 m_used = COUNTER_SIZE;
874 m_off = COUNTER_SIZE;
875
876 if(m_free >= size) return;
877 }
878
879 if(m_off == COUNTER_SIZE) {
880 if(size > std::numeric_limits<std::size_t>::max() - m_used) {
881 throw std::bad_alloc();
882 }
883 std::size_t next_size = (m_used + m_free) * 2; // include COUNTER_SIZE
884 while(next_size < size + m_used) {
885 std::size_t tmp_next_size = next_size * 2;
886 if (tmp_next_size <= next_size) {
887 next_size = size + m_used;
888 break;
889 }
890 next_size = tmp_next_size;
891 }
892
893 char* tmp = static_cast<char*>(::realloc(m_buffer, next_size));
894 if(!tmp) {
895 throw std::bad_alloc();
896 }
897
898 m_buffer = tmp;
899 m_free = next_size - m_used;
900
901 } else {
902 std::size_t next_size = m_initial_buffer_size; // include COUNTER_SIZE
903 std::size_t not_parsed = m_used - m_off;
904 if(size > std::numeric_limits<std::size_t>::max() - not_parsed - COUNTER_SIZE) {
905 throw std::bad_alloc();
906 }
907 while(next_size < size + not_parsed + COUNTER_SIZE) {
908 std::size_t tmp_next_size = next_size * 2;
909 if (tmp_next_size <= next_size) {
910 next_size = size + not_parsed + COUNTER_SIZE;
911 break;
912 }
913 next_size = tmp_next_size;
914 }
915
916 char* tmp = static_cast<char*>(::malloc(next_size));
917 if(!tmp) {
918 throw std::bad_alloc();
919 }
920
921 detail::init_count(tmp);
922
923 std::memcpy(tmp+COUNTER_SIZE, m_buffer + m_off, not_parsed);
924
925 if(static_cast<VisitorHolder&>(*this).referenced()) {
926 try {
927 (*m_referenced_buffer_hook)(m_buffer);
928 }
929 catch (...) {
930 ::free(tmp);
931 throw;
932 }
933 static_cast<VisitorHolder&>(*this).set_referenced(false);
934 } else {
935 detail::decr_count(m_buffer);
936 }
937
938 m_buffer = tmp;
939 m_used = not_parsed + COUNTER_SIZE;
940 m_free = next_size - m_used;
941 m_off = COUNTER_SIZE;
942 }
943}
944
945template <typename VisitorHolder, typename ReferencedBufferHook>
946inline char* parser<VisitorHolder, ReferencedBufferHook>::buffer()
947{
948 return m_buffer + m_used;
949}
950
951template <typename VisitorHolder, typename ReferencedBufferHook>
952inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::buffer_capacity() const
953{
954 return m_free;
955}
956
957template <typename VisitorHolder, typename ReferencedBufferHook>
958inline void parser<VisitorHolder, ReferencedBufferHook>::buffer_consumed(std::size_t size)
959{
960 m_used += size;
961 m_free -= size;
962}
963
964template <typename VisitorHolder, typename ReferencedBufferHook>
965 inline bool parser<VisitorHolder, ReferencedBufferHook>::next()
966{
967 parse_return ret = execute_imp();
968 return ret == PARSE_SUCCESS;
969}
970
971template <typename VisitorHolder, typename ReferencedBufferHook>
972inline parse_return parser<VisitorHolder, ReferencedBufferHook>::execute_imp()
973{
974 std::size_t off = m_off;
975 parse_return ret = context_type::execute(m_buffer, m_used, m_off);
976 if(m_off > off) {
977 m_parsed += m_off - off;
978 }
979 return ret;
980}
981
982template <typename VisitorHolder, typename ReferencedBufferHook>
983inline void parser<VisitorHolder, ReferencedBufferHook>::reset()
984{
985 context_type::init();
986 // don't reset referenced flag
987 m_parsed = 0;
988}
989
990template <typename VisitorHolder, typename ReferencedBufferHook>
991inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::message_size() const
992{
993 return m_parsed - m_off + m_used;
994}
995
996template <typename VisitorHolder, typename ReferencedBufferHook>
997inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::parsed_size() const
998{
999 return m_parsed;
1000}
1001
1002template <typename VisitorHolder, typename ReferencedBufferHook>
1003inline char* parser<VisitorHolder, ReferencedBufferHook>::nonparsed_buffer()
1004{
1005 return m_buffer + m_off;
1006}
1007
1008template <typename VisitorHolder, typename ReferencedBufferHook>
1009inline std::size_t parser<VisitorHolder, ReferencedBufferHook>::nonparsed_size() const
1010{
1011 return m_used - m_off;
1012}
1013
1014template <typename VisitorHolder, typename ReferencedBufferHook>
1015inline void parser<VisitorHolder, ReferencedBufferHook>::skip_nonparsed_buffer(std::size_t size)
1016{
1017 m_off += size;
1018}
1019
1020template <typename VisitorHolder, typename ReferencedBufferHook>
1021inline void parser<VisitorHolder, ReferencedBufferHook>::remove_nonparsed_buffer()
1022{
1023 m_used = m_off;
1024}
1025
1026template <typename Visitor>
1027inline bool parse(const char* data, size_t len, size_t& off, Visitor& v) {
1028 parse_return ret = msgpack::detail::parse_imp(data, len, off, v);
1029 return ret == PARSE_SUCCESS || ret == PARSE_EXTRA_BYTES;
1030}
1031
1032template <typename Visitor>
1033inline bool parse(const char* data, size_t len, Visitor& v) {
1034 std::size_t off = 0;
1035 return msgpack::parse(data, len, off, v);
1036}
1037
1038namespace detail {
1039
1040template <typename Visitor>
1041struct parse_helper : detail::context<parse_helper<Visitor> > {
1042 parse_helper(Visitor& v):m_visitor(v) {}
1043 parse_return execute(const char* data, std::size_t len, std::size_t& off) {
1044 return detail::context<parse_helper<Visitor> >::execute(data, len, off);
1045 }
1046 Visitor& visitor() const { return m_visitor; }
1047 Visitor& m_visitor;
1048};
1049
1050template <typename Visitor>
1051inline parse_return
1052parse_imp(const char* data, size_t len, size_t& off, Visitor& v) {
1053 std::size_t noff = off;
1054
1055 if(len <= noff) {
1056 // FIXME
1057 v.insufficient_bytes(noff, noff);
1058 return PARSE_CONTINUE;
1059 }
1060 detail::parse_helper<Visitor> h(v);
1061 parse_return ret = h.execute(data, len, noff);
1062 switch (ret) {
1063 case PARSE_CONTINUE:
1064 off = noff;
1065 v.insufficient_bytes(noff - 1, noff);
1066 return ret;
1067 case PARSE_SUCCESS:
1068 off = noff;
1069 if(noff < len) {
1070 return PARSE_EXTRA_BYTES;
1071 }
1072 return ret;
1073 default:
1074 return ret;
1075 }
1076}
1077
1078} // detail
1079
1080
1082} // MSGPACK_API_VERSION_NAMESPACE(v2)
1084
1085} // namespace msgpack
1086
1087#endif // MSGPACK_DEFAULT_API_VERSION >= 2
1088
1089#endif // MSGPACK_V2_PARSE_HPP
#define MSGPACK_ASSERT
Definition assert.hpp:22
Definition unpack.hpp:318
int execute(const char *data, std::size_t len, std::size_t &off)
Definition unpack.hpp:467
msgpack::object const & data() const
Definition unpack.hpp:335
context(unpack_reference_func f, void *user_data, unpack_limit const &limit)
Definition unpack.hpp:320
void init()
Definition unpack.hpp:327
Parsing class for a stream deserialization.
Definition parse_decl.hpp:32
Definition check_container_size.hpp:31
parse_return parse_imp(const char *data, size_t len, size_t &off, Visitor &v)
msgpack::enable_if< sizeof(T)==sizeof(fix_tag)>::type load(uint32_t &dst, const char *n)
Definition unpack.hpp:294
std::size_t size(T const &t)
Definition size_equal_only.hpp:24
Definition adaptor_base.hpp:15
parse_return
Definition parse_return.hpp:23
@ PARSE_CONTINUE
Definition parse_return.hpp:26
@ PARSE_EXTRA_BYTES
Definition parse_return.hpp:25
@ PARSE_STOP_VISITOR
Definition parse_return.hpp:28
@ PARSE_SUCCESS
Definition parse_return.hpp:24
@ PARSE_PARSE_ERROR
Definition parse_return.hpp:27
bool parse(const char *data, size_t len, size_t &off, Visitor &v)
Unpack msgpack formatted data via a visitor.
T type
Definition unpack.hpp:286
msgpack_container_type
Definition unpack_define.hpp:68
@ MSGPACK_CT_ARRAY_ITEM
Definition unpack_define.hpp:69
@ MSGPACK_CT_MAP_VALUE
Definition unpack_define.hpp:71
@ MSGPACK_CT_MAP_KEY
Definition unpack_define.hpp:70
#define MSGPACK_EMBED_STACK_SIZE
Definition unpack_define.hpp:16
@ MSGPACK_CS_EXT_32
Definition unpack_define.hpp:33
@ MSGPACK_CS_EXT_16
Definition unpack_define.hpp:32
@ MSGPACK_CS_STR_8
Definition unpack_define.hpp:52
@ MSGPACK_CS_STR_32
Definition unpack_define.hpp:54
@ MSGPACK_CS_DOUBLE
Definition unpack_define.hpp:36
@ MSGPACK_CS_FIXEXT_4
Definition unpack_define.hpp:48
@ MSGPACK_CS_UINT_32
Definition unpack_define.hpp:39
@ MSGPACK_CS_MAP_16
Definition unpack_define.hpp:57
@ MSGPACK_CS_BIN_32
Definition unpack_define.hpp:29
@ MSGPACK_CS_BIN_16
Definition unpack_define.hpp:28
@ MSGPACK_CS_UINT_64
Definition unpack_define.hpp:40
@ MSGPACK_CS_FLOAT
Definition unpack_define.hpp:35
@ MSGPACK_CS_ARRAY_32
Definition unpack_define.hpp:56
@ MSGPACK_CS_FIXEXT_1
Definition unpack_define.hpp:46
@ MSGPACK_CS_INT_8
Definition unpack_define.hpp:41
@ MSGPACK_CS_INT_32
Definition unpack_define.hpp:43
@ MSGPACK_ACS_BIN_VALUE
Definition unpack_define.hpp:63
@ MSGPACK_CS_ARRAY_16
Definition unpack_define.hpp:55
@ MSGPACK_CS_FIXEXT_16
Definition unpack_define.hpp:50
@ MSGPACK_CS_STR_16
Definition unpack_define.hpp:53
@ MSGPACK_ACS_STR_VALUE
Definition unpack_define.hpp:62
@ MSGPACK_CS_BIN_8
Definition unpack_define.hpp:27
@ MSGPACK_CS_INT_64
Definition unpack_define.hpp:44
@ MSGPACK_CS_FIXEXT_2
Definition unpack_define.hpp:47
@ MSGPACK_CS_HEADER
Definition unpack_define.hpp:21
@ MSGPACK_CS_FIXEXT_8
Definition unpack_define.hpp:49
@ MSGPACK_CS_MAP_32
Definition unpack_define.hpp:58
@ MSGPACK_ACS_EXT_VALUE
Definition unpack_define.hpp:64
@ MSGPACK_CS_EXT_8
Definition unpack_define.hpp:31
@ MSGPACK_CS_INT_16
Definition unpack_define.hpp:42
@ MSGPACK_CS_UINT_16
Definition unpack_define.hpp:38
@ MSGPACK_CS_UINT_8
Definition unpack_define.hpp:37
#define MSGPACK_NULLPTR
Definition cpp_config_decl.hpp:85
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE
Definition unpack_decl.hpp:43
#define MSGPACK_UNPACKER_RESERVE_SIZE
Definition unpack_decl.hpp:47
const size_t COUNTER_SIZE
Definition unpack_decl.hpp:40
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition versioning.hpp:66