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