10 #ifndef MSGPACK_V2_X3_PARSE_HPP
11 #define MSGPACK_V2_X3_PARSE_HPP
13 #if defined(MSGPACK_USE_X3_PARSE)
15 #include <boost/version.hpp>
17 #if BOOST_VERSION >= 106100
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wunused-parameter"
25 #pragma GCC diagnostic ignored "-Wconversion"
28 #include <boost/config/warning_disable.hpp>
29 #include <boost/spirit/home/x3.hpp>
30 #include <boost/spirit/home/x3/binary.hpp>
40 namespace x3 = boost::spirit::x3;
45 const auto byte_range = [](
const std::uint8_t from,
const std::uint8_t to) {
46 const auto check = [from, to](
auto& ctx)
48 const std::uint8_t value = x3::_attr(ctx);
49 x3::_val(ctx) = value;
50 x3::_pass(ctx) = from <= value && value <= to;
52 return x3::byte_ [check];
56 const auto mp_positive_fixint = byte_range(0x00, 0x7f);
57 const auto mp_fixmap = byte_range(0x80, 0x8f);
58 const auto mp_fixarray = byte_range(0x90, 0x9f);
59 const auto mp_fixstr = byte_range(0xa0, 0xbf);
60 const auto mp_nil = x3::byte_(0xc0);
61 const auto mp_false = x3::byte_(0xc2);
62 const auto mp_true = x3::byte_(0xc3);
63 const auto mp_bin8 = x3::byte_(0xc4);
64 const auto mp_bin16 = x3::byte_(0xc5);
65 const auto mp_bin32 = x3::byte_(0xc6);
66 const auto mp_ext8 = x3::byte_(0xc7);
67 const auto mp_ext16 = x3::byte_(0xc8);
68 const auto mp_ext32 = x3::byte_(0xc9);
69 const auto mp_float32 = x3::byte_(0xca);
70 const auto mp_float64 = x3::byte_(0xcb);
71 const auto mp_uint8 = x3::byte_(0xcc);
72 const auto mp_uint16 = x3::byte_(0xcd);
73 const auto mp_uint32 = x3::byte_(0xce);
74 const auto mp_uint64 = x3::byte_(0xcf);
75 const auto mp_int8 = x3::byte_(0xd0);
76 const auto mp_int16 = x3::byte_(0xd1);
77 const auto mp_int32 = x3::byte_(0xd2);
78 const auto mp_int64 = x3::byte_(0xd3);
79 const auto mp_fixext1 = x3::byte_(0xd4);
80 const auto mp_fixext2 = x3::byte_(0xd5);
81 const auto mp_fixext4 = x3::byte_(0xd6);
82 const auto mp_fixext8 = x3::byte_(0xd7);
83 const auto mp_fixext16 = x3::byte_(0xd8);
84 const auto mp_str8 = x3::byte_(0xd9);
85 const auto mp_str16 = x3::byte_(0xda);
86 const auto mp_str32 = x3::byte_(0xdb);
87 const auto mp_array16 = x3::byte_(0xdc);
88 const auto mp_array32 = x3::byte_(0xdd);
89 const auto mp_map16 = x3::byte_(0xde);
90 const auto mp_map32 = x3::byte_(0xdf);
91 const auto mp_negative_fixint = byte_range(0xe0, 0xff);
93 const auto mp_d_uint8 = x3::byte_;
94 const auto mp_d_uint16 = x3::big_word;
95 const auto mp_d_uint32 = x3::big_dword;
96 const auto mp_d_uint64 = x3::big_qword;
98 const auto mp_d_int8 = x3::byte_;
99 const auto mp_d_int16 = x3::big_word;
100 const auto mp_d_int32 = x3::big_dword;
101 const auto mp_d_int64 = x3::big_qword;
103 x3::rule<class mp_object>
const mp_object(
"mp_object");
104 x3::rule<class array_items>
const array_item(
"array_item");
105 x3::rule<class map_items>
const map_item(
"map_item");
106 x3::rule<class kv>
const kv(
"kv");
108 struct tag_app_specific {};
115 index_size(std::size_t
size, type_t type = type_t::other):
size(
size), type(type) {}
116 std::size_t index = 0;
121 template <
typename Visitor>
122 struct app_specific {
123 template <
typename Vis>
124 app_specific(Vis&& vis):vis(vis) {}
125 std::vector<index_size> index_sizes;
129 template <
typename Visitor>
130 app_specific<Visitor> make_app_specific(Visitor&& vis) {
131 return app_specific<Visitor>(std::forward<Visitor>(vis));
134 const auto more = [](
auto &ctx) {
135 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
136 _pass(ctx) = app_specific.index_sizes.back().index++ < app_specific.index_sizes.back().size;
139 const auto done = [](
auto &ctx) {
140 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
141 if (app_specific.index_sizes.back().index == app_specific.index_sizes.back().size + 1) {
143 switch (app_specific.index_sizes.back().type) {
144 case index_size::type_t::array:
145 app_specific.vis.end_array();
147 case index_size::type_t::map:
148 app_specific.vis.end_map();
150 case index_size::type_t::other:
153 app_specific.index_sizes.pop_back();
160 const auto mp_object_def =
165 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
166 app_specific.vis.visit_nil();
175 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
176 app_specific.vis.visit_boolean(
true);
185 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
186 app_specific.vis.visit_boolean(
false);
195 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
196 app_specific.vis.visit_positive_integer(_attr(ctx));
205 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
206 std::int8_t val =
static_cast<std::int8_t
>(_attr(ctx));
207 app_specific.vis.visit_negative_integer(val);
213 mp_uint8 >> mp_d_uint8 [
216 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
217 app_specific.vis.visit_negative_integer(_attr(ctx));
223 mp_uint16 >> mp_d_uint16 [
226 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
227 app_specific.vis.visit_positive_integer(_attr(ctx));
233 mp_uint32 >> mp_d_uint32 [
236 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
237 app_specific.vis.visit_positive_integer(_attr(ctx));
243 mp_uint64 >> mp_d_uint64 [
246 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
247 app_specific.vis.visit_positive_integer(_attr(ctx));
253 mp_int8 >> mp_d_int8 [
256 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
257 std::int8_t val =
static_cast<std::int8_t
>(_attr(ctx));
258 app_specific.vis.visit_negative_integer(val);
264 mp_int16 >> mp_d_int16 [
267 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
268 std::int16_t val =
static_cast<std::int16_t
>(_attr(ctx));
269 app_specific.vis.visit_negative_integer(val);
275 mp_int32 >> mp_d_int32 [
278 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
279 std::int32_t val =
static_cast<std::int32_t
>(_attr(ctx));
280 app_specific.vis.visit_negative_integer(val);
286 mp_int64 >> mp_d_int64 [
289 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
290 std::int64_t val =
static_cast<std::int64_t
>(_attr(ctx));
291 app_specific.vis.visit_negative_integer(val);
297 mp_float32 >> mp_d_uint32 [
300 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
301 union { uint32_t i;
float f; } mem = { _attr(ctx) };
302 app_specific.vis.visit_float32(mem.f);
308 mp_float64 >> mp_d_uint64 [
311 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
312 union { uint64_t i;
double f; } mem = { _attr(ctx) };
313 #if defined(TARGET_OS_IPHONE)
315 #elif defined(__arm__) && !(__ARM_EABI__)
317 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
319 app_specific.vis.visit_float64(mem.f);
328 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
329 std::size_t
size = _attr(ctx) & 0b00011111;
330 app_specific.index_sizes.emplace_back(
size);
336 *(x3::eps [more] >> x3::char_)
341 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
342 auto const& str = _attr(ctx);
343 auto size =
static_cast<uint32_t
>(std::distance(str.begin(), str.end()));
344 app_specific.vis.visit_str(
size ? &str.front() :
nullptr,
size);
350 mp_str8 >> mp_d_uint8 [
353 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
354 app_specific.index_sizes.emplace_back(_attr(ctx));
360 *(x3::eps [more] >> x3::char_)
365 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
366 auto const& str = _attr(ctx);
367 auto size =
static_cast<uint32_t
>(std::distance(str.begin(), str.end()));
368 app_specific.vis.visit_str(
size ? &str.front() :
nullptr,
size);
374 mp_str16 >> mp_d_uint16 [
377 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
378 app_specific.index_sizes.emplace_back(_attr(ctx));
384 *(x3::eps [more] >> x3::char_)
389 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
390 auto const& str = _attr(ctx);
391 auto size =
static_cast<uint32_t
>(std::distance(str.begin(), str.end()));
392 app_specific.vis.visit_str(
size ? &str.front() :
nullptr,
size);
398 mp_str32 >> mp_d_uint32 [
401 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
402 app_specific.index_sizes.emplace_back(_attr(ctx));
408 *(x3::eps [more] >> x3::char_)
413 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
414 auto const& str = _attr(ctx);
415 auto size =
static_cast<uint32_t
>(std::distance(str.begin(), str.end()));
416 app_specific.vis.visit_str(
size ? &str.front() :
nullptr,
size);
422 mp_bin8 >> mp_d_uint8 [
425 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
426 app_specific.index_sizes.emplace_back(_attr(ctx));
432 *(x3::eps [more] >> x3::char_)
437 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
438 auto const& bin = _attr(ctx);
439 auto size =
static_cast<uint32_t
>(std::distance(bin.begin(), bin.end()));
440 app_specific.vis.visit_bin(
size ? &bin.front() :
nullptr,
size);
446 mp_bin16 >> mp_d_uint16 [
449 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
450 app_specific.index_sizes.emplace_back(_attr(ctx));
456 *(x3::eps [more] >> x3::char_)
461 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
462 auto const& bin = _attr(ctx);
463 auto size =
static_cast<uint32_t
>(std::distance(bin.begin(), bin.end()));
464 app_specific.vis.visit_bin(
size ? &bin.front() :
nullptr,
size);
470 mp_bin32 >> mp_d_uint32 [
473 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
474 app_specific.index_sizes.emplace_back(_attr(ctx));
480 *(x3::eps [more] >> x3::char_)
485 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
486 auto const& bin = _attr(ctx);
487 auto size =
static_cast<uint32_t
>(std::distance(bin.begin(), bin.end()));
488 app_specific.vis.visit_bin(
size ? &bin.front() :
nullptr,
size);
497 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
498 uint32_t
size = _attr(ctx) & 0b00001111;
499 app_specific.index_sizes.emplace_back(
size, index_size::type_t::array);
500 app_specific.vis.start_array(
size);
504 >> *(x3::eps [more] >> array_item)
508 mp_array16 >> mp_d_uint16 [
511 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
512 uint32_t
size = _attr(ctx);
513 app_specific.index_sizes.emplace_back(
size, index_size::type_t::array);
514 app_specific.vis.start_array(
size);
518 >> *(x3::eps [more] >> array_item)
522 mp_array32 >> mp_d_uint32 [
525 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
526 uint32_t
size = _attr(ctx);
527 app_specific.index_sizes.emplace_back(
size, index_size::type_t::array);
528 app_specific.vis.start_array(
size);
532 >> *(x3::eps [more] >> array_item)
539 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
540 uint32_t
size = _attr(ctx) & 0b00001111;
541 app_specific.index_sizes.emplace_back(
size, index_size::type_t::map);
542 app_specific.vis.start_map(
size);
546 >> *(x3::eps [more] >> map_item)
550 mp_map16 >> mp_d_uint16 [
553 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
554 uint32_t
size = _attr(ctx);
555 app_specific.index_sizes.emplace_back(
size, index_size::type_t::map);
556 app_specific.vis.start_map(
size);
560 >> *(x3::eps [more] >> map_item)
564 mp_map32 >> mp_d_uint32 [
567 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
568 uint32_t
size = _attr(ctx);
569 app_specific.index_sizes.emplace_back(
size, index_size::type_t::map);
570 app_specific.vis.start_map(
size);
574 >> *(x3::eps [more] >> map_item)
581 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
582 app_specific.index_sizes.emplace_back(1+1);
588 *(x3::eps [more] >> x3::char_)
593 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
594 auto const& ext = _attr(ctx);
595 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
596 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
605 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
606 app_specific.index_sizes.emplace_back(2+1);
612 *(x3::eps [more] >> x3::char_)
617 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
618 auto const& ext = _attr(ctx);
619 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
620 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
629 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
630 app_specific.index_sizes.emplace_back(4+1);
636 *(x3::eps [more] >> x3::char_)
641 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
642 auto const& ext = _attr(ctx);
643 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
644 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
653 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
654 app_specific.index_sizes.emplace_back(8+1);
660 *(x3::eps [more] >> x3::char_)
665 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
666 auto const& ext = _attr(ctx);
667 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
668 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
677 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
678 app_specific.index_sizes.emplace_back(16+1);
684 *(x3::eps [more] >> x3::char_)
689 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
690 auto const& ext = _attr(ctx);
691 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
692 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
698 mp_ext8 >> mp_d_uint8 [
701 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
702 app_specific.index_sizes.emplace_back(_attr(ctx)+1);
708 *(x3::eps [more] >> x3::char_)
713 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
714 auto const& ext = _attr(ctx);
715 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
716 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
722 mp_ext16 >> mp_d_uint16 [
725 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
726 app_specific.index_sizes.emplace_back(_attr(ctx)+1);
732 *(x3::eps [more] >> x3::char_)
737 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
738 auto const& ext = _attr(ctx);
739 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
740 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
746 mp_ext32 >> mp_d_uint32 [
749 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
750 app_specific.index_sizes.emplace_back(_attr(ctx)+1);
756 *(x3::eps [more] >> x3::char_)
761 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
762 auto const& ext = _attr(ctx);
763 auto size =
static_cast<uint32_t
>(std::distance(ext.begin(), ext.end()));
764 app_specific.vis.visit_ext(
size ? &ext.front() :
nullptr,
size);
769 const auto array_item_def =
773 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
774 app_specific.vis.start_array_item();
786 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
787 app_specific.vis.end_array_item();
793 const auto map_item_def = kv;
798 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
799 app_specific.vis.start_map_key();
810 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
811 app_specific.vis.end_map_key();
820 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
821 app_specific.vis.start_map_value();
832 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
833 app_specific.vis.end_map_value();
840 mp_object, array_item, map_item, kv
843 const auto rule = mp_object;
847 template <
typename Iterator,
typename Visitor>
848 inline bool parse(Iterator&&
begin, Iterator&&
end, Visitor&& vis) {
849 auto data = detail::make_app_specific(std::forward<Visitor>(vis));
851 std::forward<Iterator>(
begin),
852 std::forward<Iterator>(
end),
853 detail::x3::with<detail::tag_app_specific>(std::ref(data))[detail::rule]
864 #pragma GCC diagnostic pop
869 #error Boost 1.61.0 or later is required to use x3 parse
std::size_t size(T const &t)
Definition: size_equal_only.hpp:24
Definition: adaptor_base.hpp:15
msgpack::object_kv * end(msgpack::object_map &map)
Definition: iterator.hpp:25
msgpack::object_kv * begin(msgpack::object_map &map)
Definition: iterator.hpp:23
bool parse(const char *data, size_t len, size_t &off, Visitor &v)
Unpack msgpack formatted data via a visitor.
#define MSGPACK_API_VERSION_NAMESPACE(ns)
Definition: versioning.hpp:66