MessagePack for C++
x3_parse.hpp
Go to the documentation of this file.
1 //
2 // MessagePack for C++ deserializing routine
3 //
4 // Copyright (C) 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_X3_PARSE_HPP
11 #define MSGPACK_V2_X3_PARSE_HPP
12 
13 #if defined(MSGPACK_USE_X3_PARSE)
14 
15 #include <boost/version.hpp>
16 
17 #if BOOST_VERSION >= 106100
18 
19 #include "msgpack/versioning.hpp"
21 
22 #if __GNUC__ >= 4
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wunused-parameter"
25 #pragma GCC diagnostic ignored "-Wconversion"
26 #endif // __GNUC__ >= 4
27 
28 #include <boost/config/warning_disable.hpp>
29 #include <boost/spirit/home/x3.hpp>
30 #include <boost/spirit/home/x3/binary.hpp>
31 
32 namespace msgpack {
33 
37 
38 namespace detail {
39 
40 namespace x3 = boost::spirit::x3;
41 
42 using x3::byte_;
43 
44 // byte range utility
45 const auto byte_range = [](const std::uint8_t from, const std::uint8_t to) {
46  const auto check = [from, to](auto& ctx)
47  {
48  const std::uint8_t value = x3::_attr(ctx);
49  x3::_val(ctx) = value;
50  x3::_pass(ctx) = from <= value && value <= to;
51  };
52  return x3::byte_ [check];
53 };
54 
55 // MessagePack rule
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);
92 
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;
97 
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;
102 
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");
107 
108 struct tag_app_specific {};
109 struct index_size {
110  enum struct type_t {
111  array,
112  map,
113  other
114  };
115  index_size(std::size_t size, type_t type = type_t::other):size(size), type(type) {}
116  std::size_t index = 0;
117  std::size_t size;
118  type_t type;
119 };
120 
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;
126  Visitor vis;
127 };
128 
129 template <typename Visitor>
130 app_specific<Visitor> make_app_specific(Visitor&& vis) {
131  return app_specific<Visitor>(std::forward<Visitor>(vis));
132 }
133 
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;
137 };
138 
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) {
142  _pass(ctx) = true;
143  switch (app_specific.index_sizes.back().type) {
144  case index_size::type_t::array:
145  app_specific.vis.end_array();
146  break;
147  case index_size::type_t::map:
148  app_specific.vis.end_map();
149  break;
150  case index_size::type_t::other:
151  break;
152  }
153  app_specific.index_sizes.pop_back();
154  }
155  else {
156  _pass(ctx) = false;
157  }
158 };
159 
160 const auto mp_object_def =
161  // -----------------------------------------------
162  mp_nil [
163  (
164  [](auto& ctx){
165  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
166  app_specific.vis.visit_nil();
167  }
168  )
169  ]
170  |
171  // -----------------------------------------------
172  mp_true [
173  (
174  [](auto& ctx){
175  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
176  app_specific.vis.visit_boolean(true);
177  }
178  )
179  ]
180  |
181  // -----------------------------------------------
182  mp_false [
183  (
184  [](auto& ctx){
185  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
186  app_specific.vis.visit_boolean(false);
187  }
188  )
189  ]
190  |
191  // -----------------------------------------------
192  mp_positive_fixint [
193  (
194  [](auto& ctx){
195  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
196  app_specific.vis.visit_positive_integer(_attr(ctx));
197  }
198  )
199  ]
200  |
201  // -----------------------------------------------
202  mp_negative_fixint [
203  (
204  [](auto& 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);
208  }
209  )
210  ]
211  |
212  // -----------------------------------------------
213  mp_uint8 >> mp_d_uint8 [
214  (
215  [](auto& ctx){
216  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
217  app_specific.vis.visit_negative_integer(_attr(ctx));
218  }
219  )
220  ]
221  |
222  // -----------------------------------------------
223  mp_uint16 >> mp_d_uint16 [
224  (
225  [](auto& ctx){
226  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
227  app_specific.vis.visit_positive_integer(_attr(ctx));
228  }
229  )
230  ]
231  |
232  // -----------------------------------------------
233  mp_uint32 >> mp_d_uint32 [
234  (
235  [](auto& ctx){
236  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
237  app_specific.vis.visit_positive_integer(_attr(ctx));
238  }
239  )
240  ]
241  |
242  // -----------------------------------------------
243  mp_uint64 >> mp_d_uint64 [
244  (
245  [](auto& ctx){
246  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
247  app_specific.vis.visit_positive_integer(_attr(ctx));
248  }
249  )
250  ]
251  |
252  // -----------------------------------------------
253  mp_int8 >> mp_d_int8 [
254  (
255  [](auto& ctx){
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);
259  }
260  )
261  ]
262  |
263  // -----------------------------------------------
264  mp_int16 >> mp_d_int16 [
265  (
266  [](auto& ctx){
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);
270  }
271  )
272  ]
273  |
274  // -----------------------------------------------
275  mp_int32 >> mp_d_int32 [
276  (
277  [](auto& ctx){
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);
281  }
282  )
283  ]
284  |
285  // -----------------------------------------------
286  mp_int64 >> mp_d_int64 [
287  (
288  [](auto& ctx){
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);
292  }
293  )
294  ]
295  |
296  // -----------------------------------------------
297  mp_float32 >> mp_d_uint32 [
298  (
299  [](auto& ctx){
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);
303  }
304  )
305  ]
306  |
307  // -----------------------------------------------
308  mp_float64 >> mp_d_uint64 [
309  (
310  [](auto& ctx){
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)
314  // ok
315 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
316  // https://github.com/msgpack/msgpack-perl/pull/1
317  mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
318 #endif
319  app_specific.vis.visit_float64(mem.f);
320  }
321  )
322  ]
323  |
324  // -----------------------------------------------
325  mp_fixstr [
326  (
327  [](auto& ctx){
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);
331  }
332  )
333  ]
334  >>
335  x3::raw [
336  *(x3::eps [more] >> x3::char_)
337  >> x3::eps [done]
338  ][
339  (
340  [](auto& ctx){
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);
345  }
346  )
347  ]
348  |
349  // -----------------------------------------------
350  mp_str8 >> mp_d_uint8 [
351  (
352  [](auto& ctx){
353  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
354  app_specific.index_sizes.emplace_back(_attr(ctx));
355  }
356  )
357  ]
358  >>
359  x3::raw [
360  *(x3::eps [more] >> x3::char_)
361  >> x3::eps [done]
362  ][
363  (
364  [](auto& ctx){
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);
369  }
370  )
371  ]
372  |
373  // -----------------------------------------------
374  mp_str16 >> mp_d_uint16 [
375  (
376  [](auto& ctx){
377  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
378  app_specific.index_sizes.emplace_back(_attr(ctx));
379  }
380  )
381  ]
382  >>
383  x3::raw [
384  *(x3::eps [more] >> x3::char_)
385  >> x3::eps [done]
386  ][
387  (
388  [](auto& ctx){
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);
393  }
394  )
395  ]
396  |
397  // -----------------------------------------------
398  mp_str32 >> mp_d_uint32 [
399  (
400  [](auto& ctx){
401  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
402  app_specific.index_sizes.emplace_back(_attr(ctx));
403  }
404  )
405  ]
406  >>
407  x3::raw [
408  *(x3::eps [more] >> x3::char_)
409  >> x3::eps [done]
410  ][
411  (
412  [](auto& ctx){
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);
417  }
418  )
419  ]
420  |
421  // -----------------------------------------------
422  mp_bin8 >> mp_d_uint8 [
423  (
424  [](auto& ctx){
425  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
426  app_specific.index_sizes.emplace_back(_attr(ctx));
427  }
428  )
429  ]
430  >>
431  x3::raw [
432  *(x3::eps [more] >> x3::char_)
433  >> x3::eps [done]
434  ][
435  (
436  [](auto& ctx){
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);
441  }
442  )
443  ]
444  |
445  // -----------------------------------------------
446  mp_bin16 >> mp_d_uint16 [
447  (
448  [](auto& ctx){
449  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
450  app_specific.index_sizes.emplace_back(_attr(ctx));
451  }
452  )
453  ]
454  >>
455  x3::raw [
456  *(x3::eps [more] >> x3::char_)
457  >> x3::eps [done]
458  ][
459  (
460  [](auto& ctx){
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);
465  }
466  )
467  ]
468  |
469  // -----------------------------------------------
470  mp_bin32 >> mp_d_uint32 [
471  (
472  [](auto& ctx){
473  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
474  app_specific.index_sizes.emplace_back(_attr(ctx));
475  }
476  )
477  ]
478  >>
479  x3::raw [
480  *(x3::eps [more] >> x3::char_)
481  >> x3::eps [done]
482  ][
483  (
484  [](auto& ctx){
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);
489  }
490  )
491  ]
492  |
493  // -----------------------------------------------
494  mp_fixarray [
495  (
496  [](auto& ctx){
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);
501  }
502  )
503  ]
504  >> *(x3::eps [more] >> array_item)
505  >> x3::eps [done]
506  |
507  // -----------------------------------------------
508  mp_array16 >> mp_d_uint16 [
509  (
510  [](auto& ctx){
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);
515  }
516  )
517  ]
518  >> *(x3::eps [more] >> array_item)
519  >> x3::eps [done]
520  |
521  // -----------------------------------------------
522  mp_array32 >> mp_d_uint32 [
523  (
524  [](auto& ctx){
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);
529  }
530  )
531  ]
532  >> *(x3::eps [more] >> array_item)
533  >> x3::eps [done]
534  |
535  // -----------------------------------------------
536  mp_fixmap [
537  (
538  [](auto& ctx){
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);
543  }
544  )
545  ]
546  >> *(x3::eps [more] >> map_item)
547  >> x3::eps [done]
548  |
549  // -----------------------------------------------
550  mp_map16 >> mp_d_uint16 [
551  (
552  [](auto& ctx){
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);
557  }
558  )
559  ]
560  >> *(x3::eps [more] >> map_item)
561  >> x3::eps [done]
562  |
563  // -----------------------------------------------
564  mp_map32 >> mp_d_uint32 [
565  (
566  [](auto& ctx){
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);
571  }
572  )
573  ]
574  >> *(x3::eps [more] >> map_item)
575  >> x3::eps [done]
576  |
577  // -----------------------------------------------
578  mp_fixext1 [
579  (
580  [](auto& ctx){
581  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
582  app_specific.index_sizes.emplace_back(1+1);
583  }
584  )
585  ]
586  >>
587  x3::raw [
588  *(x3::eps [more] >> x3::char_)
589  >> x3::eps [done]
590  ][
591  (
592  [](auto& ctx){
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);
597  }
598  )
599  ]
600  |
601  // -----------------------------------------------
602  mp_fixext2 [
603  (
604  [](auto& ctx){
605  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
606  app_specific.index_sizes.emplace_back(2+1);
607  }
608  )
609  ]
610  >>
611  x3::raw [
612  *(x3::eps [more] >> x3::char_)
613  >> x3::eps [done]
614  ][
615  (
616  [](auto& ctx){
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);
621  }
622  )
623  ]
624  |
625  // -----------------------------------------------
626  mp_fixext4 [
627  (
628  [](auto& ctx){
629  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
630  app_specific.index_sizes.emplace_back(4+1);
631  }
632  )
633  ]
634  >>
635  x3::raw [
636  *(x3::eps [more] >> x3::char_)
637  >> x3::eps [done]
638  ][
639  (
640  [](auto& ctx){
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);
645  }
646  )
647  ]
648  |
649  // -----------------------------------------------
650  mp_fixext8 [
651  (
652  [](auto& ctx){
653  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
654  app_specific.index_sizes.emplace_back(8+1);
655  }
656  )
657  ]
658  >>
659  x3::raw [
660  *(x3::eps [more] >> x3::char_)
661  >> x3::eps [done]
662  ][
663  (
664  [](auto& ctx){
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);
669  }
670  )
671  ]
672  |
673  // -----------------------------------------------
674  mp_fixext16 [
675  (
676  [](auto& ctx){
677  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
678  app_specific.index_sizes.emplace_back(16+1);
679  }
680  )
681  ]
682  >>
683  x3::raw [
684  *(x3::eps [more] >> x3::char_)
685  >> x3::eps [done]
686  ][
687  (
688  [](auto& ctx){
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);
693  }
694  )
695  ]
696  |
697  // -----------------------------------------------
698  mp_ext8 >> mp_d_uint8 [
699  (
700  [](auto& ctx){
701  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
702  app_specific.index_sizes.emplace_back(_attr(ctx)+1);
703  }
704  )
705  ]
706  >>
707  x3::raw [
708  *(x3::eps [more] >> x3::char_)
709  >> x3::eps [done]
710  ][
711  (
712  [](auto& ctx){
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);
717  }
718  )
719  ]
720  |
721  // -----------------------------------------------
722  mp_ext16 >> mp_d_uint16 [
723  (
724  [](auto& ctx){
725  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
726  app_specific.index_sizes.emplace_back(_attr(ctx)+1);
727  }
728  )
729  ]
730  >>
731  x3::raw [
732  *(x3::eps [more] >> x3::char_)
733  >> x3::eps [done]
734  ][
735  (
736  [](auto& ctx){
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);
741  }
742  )
743  ]
744  |
745  // -----------------------------------------------
746  mp_ext32 >> mp_d_uint32 [
747  (
748  [](auto& ctx){
749  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
750  app_specific.index_sizes.emplace_back(_attr(ctx)+1);
751  }
752  )
753  ]
754  >>
755  x3::raw [
756  *(x3::eps [more] >> x3::char_)
757  >> x3::eps [done]
758  ][
759  (
760  [](auto& ctx){
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);
765  }
766  )
767  ];
768 
769 const auto array_item_def =
770  x3::eps[
771  (
772  [](auto& ctx){
773  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
774  app_specific.vis.start_array_item();
775 
776  _pass(ctx) = true;
777  }
778  )
779  ]
780  >>
781  mp_object
782  >>
783  x3::eps[
784  (
785  [](auto& ctx){
786  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
787  app_specific.vis.end_array_item();
788  _pass(ctx) = true;
789  }
790  )
791  ];
792 
793 const auto map_item_def = kv;
794 const auto kv_def =
795  x3::eps[
796  (
797  [](auto& ctx){
798  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
799  app_specific.vis.start_map_key();
800  _pass(ctx) = true;
801  }
802  )
803  ]
804  >>
805  mp_object
806  >>
807  x3::eps[
808  (
809  [](auto& ctx){
810  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
811  app_specific.vis.end_map_key();
812  _pass(ctx) = true;
813  }
814  )
815  ]
816  >>
817  x3::eps[
818  (
819  [](auto& ctx){
820  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
821  app_specific.vis.start_map_value();
822  _pass(ctx) = true;
823  }
824  )
825  ]
826  >>
827  mp_object
828  >>
829  x3::eps[
830  (
831  [](auto& ctx){
832  auto& app_specific = x3::get<tag_app_specific>(ctx).get();
833  app_specific.vis.end_map_value();
834  _pass(ctx) = true;
835  }
836  )
837  ];
838 
839 BOOST_SPIRIT_DEFINE(
840  mp_object, array_item, map_item, kv
841 );
842 
843 const auto rule = mp_object;
844 
845 } // namespace detail
846 
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));
850  return detail::x3::parse(
851  std::forward<Iterator>(begin),
852  std::forward<Iterator>(end),
853  detail::x3::with<detail::tag_app_specific>(std::ref(data))[detail::rule]
854  );
855 }
856 
858 } // MSGPACK_API_VERSION_NAMESPACE(v2)
860 
861 } // namespace msgpack
862 
863 #if __GNUC__ >= 4
864 #pragma GCC diagnostic pop
865 #endif // __GNUC__ >= 4
866 
867 #else // BOOST_VERSION >= 106100
868 
869 #error Boost 1.61.0 or later is required to use x3 parse
870 
871 #endif // BOOST_VERSION >= 106100
872 
873 #endif // defined(MSGPACK_USE_X3_PARSE)
874 
875 #endif // MSGPACK_V2_X3_PARSE_HPP
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