GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: detail/parse_into.hpp
Date: 2025-12-23 17:35:06
Exec Total Coverage
Lines: 395 395 100.0%
Functions: 1627 4011 40.6%
Branches: 165 212 77.8%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/boostorg/json
9 //
10
11 #ifndef BOOST_JSON_DETAIL_PARSE_INTO_HPP
12 #define BOOST_JSON_DETAIL_PARSE_INTO_HPP
13
14 #include <boost/json/detail/config.hpp>
15
16 #include <boost/json/error.hpp>
17 #include <boost/json/conversion.hpp>
18 #include <boost/describe/enum_from_string.hpp>
19
20 #include <vector>
21
22 /*
23 * This file contains the majority of parse_into functionality, specifically
24 * the implementation of dedicated handlers for different generic categories of
25 * types.
26 *
27 * At the core of parse_into is the specialisation basic_parser<
28 * detail::into_handler<T> >. detail::into_handler<T> is a handler for
29 * basic_parser. It directly handles events on_comment_part and on_comment (by
30 * ignoring them), on_document_begin (by enabling the nested dedicated
31 * handler), and on_document_end (by disabling the nested handler).
32 *
33 * Every other event is handled by the nested handler, which has the type
34 * get_handler< T, into_handler<T> >. The second parameter is the parent
35 * handler (in this case, it's the top handler, into_handler<T>). The type is
36 * actually an alias to class template converting_handler, which has a separate
37 * specialisation for every conversion category from the list of generic
38 * conversion categories (e.g. sequence_conversion_tag, tuple_conversion_tag,
39 * etc.) Instantiations of the template store a pointer to the parent handler
40 * and a pointer to the value T.
41 *
42 * The nested handler handles specific parser events by setting error_code to
43 * an appropriate value, if it receives an event it isn't supposed to handle
44 * (e.g. a number handler getting an on_string event), and also updates the
45 * value when appropriate. Note that they never need to handle on_comment_part,
46 * on_comment, on_document_begin, and on_document_end events, as those are
47 * always handled by the top handler into_handler<T>.
48 *
49 * When the nested handler receives an event that completes the current value,
50 * it is supposed to call its parent's signal_value member function. This is
51 * necessary for correct handling of composite types (e.g. sequences).
52 *
53 * Finally, nested handlers should always call parent's signal_end member
54 * function if they don't handle on_array_end themselves. This is necessary
55 * to correctly handle nested composites (e.g. sequences inside sequences).
56 * signal_end can return false and set error state when the containing parser
57 * requires more elements.
58 *
59 * converting_handler instantiations for composite categories of types have
60 * their own nested handlers, to which they themselves delegate events. For
61 * complex types you will get a tree of handlers with into_handler<T> as the
62 * root and handlers for scalars as leaves.
63 *
64 * To reiterate, only into_handler has to handle on_comment_part, on_comment,
65 * on_document_begin, and on_document_end; only handlers for composites and
66 * into_handler has to provide signal_value and signal_end; all handlers
67 * except for into_handler have to call their parent's signal_end from
68 * their on_array_begin, if they don't handle it themselves; once a handler
69 * receives an event that finishes its current value, it should call its
70 * parent's signal_value.
71 */
72
73 namespace boost {
74 namespace json {
75 namespace detail {
76
77 template< class Impl, class T, class Parent >
78 class converting_handler;
79
80 // get_handler
81 template< class V, class P >
82 using get_handler = converting_handler< generic_conversion_category<V>, V, P >;
83
84 template<error E> class handler_error_base
85 {
86 public:
87
88 handler_error_base() = default;
89
90 handler_error_base( handler_error_base const& ) = delete;
91 handler_error_base& operator=( handler_error_base const& ) = delete;
92
93 public:
94
95 4 bool on_object_begin( system::error_code& ec ) { BOOST_JSON_FAIL( ec, E ); return false; }
96 14 bool on_array_begin( system::error_code& ec ) { BOOST_JSON_FAIL( ec, E ); return false; }
97 bool on_array_end( system::error_code& ec ) { BOOST_JSON_FAIL( ec, E ); return false; }
98 2 bool on_string_part( system::error_code& ec, string_view ) { BOOST_JSON_FAIL( ec, E ); return false; }
99 120 bool on_string( system::error_code& ec, string_view ) { BOOST_JSON_FAIL( ec, E ); return false; }
100 4 bool on_number_part( system::error_code& ec ) { BOOST_JSON_FAIL( ec, E ); return false; }
101 16 bool on_int64( system::error_code& ec, std::int64_t ) { BOOST_JSON_FAIL( ec, E ); return false; }
102 16 bool on_uint64( system::error_code& ec, std::uint64_t ) { BOOST_JSON_FAIL( ec, E ); return false; }
103 14 bool on_double( system::error_code& ec, double ) { BOOST_JSON_FAIL( ec, E ); return false; }
104 4 bool on_bool( system::error_code& ec, bool ) { BOOST_JSON_FAIL( ec, E ); return false; }
105 8 bool on_null( system::error_code& ec ) { BOOST_JSON_FAIL( ec, E ); return false; }
106
107 // LCOV_EXCL_START
108 // parses that can't handle this would fail at on_object_begin
109 bool on_object_end( system::error_code& ) { BOOST_ASSERT( false ); return false; }
110 bool on_key_part( system::error_code& ec, string_view ) { BOOST_JSON_FAIL( ec, E ); return false; }
111 bool on_key( system::error_code& ec, string_view ) { BOOST_JSON_FAIL( ec, E ); return false; }
112 // LCOV_EXCL_STOP
113 };
114
115 template< class P, error E >
116 class scalar_handler
117 : public handler_error_base<E>
118 {
119 protected:
120 P* parent_;
121
122 public:
123 scalar_handler(scalar_handler const&) = delete;
124 scalar_handler& operator=(scalar_handler const&) = delete;
125
126 1631 scalar_handler(P* p): parent_( p )
127 1631 {}
128
129 358 bool on_array_end( system::error_code& ec )
130 {
131 358 return parent_->signal_end(ec);
132 }
133 };
134
135 template< class D, class V, class P, error E >
136 class composite_handler
137 {
138 protected:
139 using inner_handler_type = get_handler<V, D>;
140
141 P* parent_;
142 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
143 # pragma GCC diagnostic push
144 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
145 #endif
146 V next_value_ = {};
147 inner_handler_type inner_;
148 bool inner_active_ = false;
149
150 public:
151 composite_handler( composite_handler const& ) = delete;
152 composite_handler& operator=( composite_handler const& ) = delete;
153
154 826 composite_handler( P* p )
155
1/1
✓ Branch 2 taken 110 times.
826 : parent_(p), inner_( &next_value_, static_cast<D*>(this) )
156 826 {}
157 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
158 # pragma GCC diagnostic pop
159 #endif
160
161 544 bool signal_end(system::error_code& ec)
162 {
163 544 inner_active_ = false;
164 544 return parent_->signal_value(ec);
165 }
166
167 #define BOOST_JSON_INVOKE_INNER(f) \
168 if( !inner_active_ ) { \
169 BOOST_JSON_FAIL(ec, E); \
170 return false; \
171 } \
172 else \
173 return inner_.f
174
175 42 bool on_object_begin( system::error_code& ec )
176 {
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( on_object_begin(ec) );
178 }
179
180 42 bool on_object_end( system::error_code& ec )
181 {
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( on_object_end(ec) );
183 }
184
185 116 bool on_array_begin( system::error_code& ec )
186 {
187
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 55 times.
116 BOOST_JSON_INVOKE_INNER( on_array_begin(ec) );
188 }
189
190 bool on_array_end( system::error_code& ec )
191 {
192 BOOST_JSON_INVOKE_INNER( on_array_end(ec) );
193 }
194
195 6 bool on_key_part( system::error_code& ec, string_view sv )
196 {
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
6 BOOST_JSON_INVOKE_INNER( on_key_part(ec, sv) );
198 }
199
200 42 bool on_key( system::error_code& ec, string_view sv )
201 {
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( on_key(ec, sv) );
203 }
204
205 48 bool on_string_part( system::error_code& ec, string_view sv )
206 {
207
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 23 times.
48 BOOST_JSON_INVOKE_INNER( on_string_part(ec, sv) );
208 }
209
210 100 bool on_string( system::error_code& ec, string_view sv )
211 {
212
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 49 times.
100 BOOST_JSON_INVOKE_INNER( on_string(ec, sv) );
213 }
214
215 458 bool on_number_part( system::error_code& ec )
216 {
217
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 227 times.
458 BOOST_JSON_INVOKE_INNER( on_number_part(ec) );
218 }
219
220 1788 bool on_int64( system::error_code& ec, std::int64_t v )
221 {
222
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 892 times.
1788 BOOST_JSON_INVOKE_INNER( on_int64(ec, v) );
223 }
224
225 14 bool on_uint64( system::error_code& ec, std::uint64_t v )
226 {
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( on_uint64(ec, v) );
228 }
229
230 84 bool on_double( system::error_code& ec, double v )
231 {
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
84 BOOST_JSON_INVOKE_INNER( on_double(ec, v) );
233 }
234
235 42 bool on_bool( system::error_code& ec, bool v )
236 {
237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( on_bool(ec, v) );
238 }
239
240 28 bool on_null( system::error_code& ec )
241 {
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
28 BOOST_JSON_INVOKE_INNER( on_null(ec) );
243 }
244
245 #undef BOOST_JSON_INVOKE_INNER
246 };
247
248 // integral handler
249 template<class V,
250 typename std::enable_if<std::is_signed<V>::value, int>::type = 0>
251 1354 bool integral_in_range( std::int64_t v )
252 {
253
3/4
✓ Branch 1 taken 678 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 678 times.
✗ Branch 5 not taken.
1354 return v >= (std::numeric_limits<V>::min)() && v <= (std::numeric_limits<V>::max)();
254 }
255
256 template<class V,
257 typename std::enable_if<!std::is_signed<V>::value, int>::type = 0>
258 70 bool integral_in_range( std::int64_t v )
259 {
260
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 35 times.
✗ Branch 4 not taken.
70 return v >= 0 && static_cast<std::uint64_t>( v ) <= (std::numeric_limits<V>::max)();
261 }
262
263 template<class V>
264 74 bool integral_in_range( std::uint64_t v )
265 {
266 74 return v <= static_cast<typename std::make_unsigned<V>::type>( (std::numeric_limits<V>::max)() );
267 }
268
269 template< class V, class P >
270 class converting_handler<integral_conversion_tag, V, P>
271 : public scalar_handler<P, error::not_integer>
272 {
273 private:
274 V* value_;
275
276 public:
277 1105 converting_handler( V* v, P* p )
278 : converting_handler::scalar_handler(p)
279 1105 , value_(v)
280 1105 {}
281
282 638 bool on_number_part( system::error_code& )
283 {
284 638 return true;
285 }
286
287 1424 bool on_int64(system::error_code& ec, std::int64_t v)
288 {
289
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 713 times.
1424 if( !integral_in_range<V>( v ) )
290 {
291 4 BOOST_JSON_FAIL( ec, error::not_exact );
292 4 return false;
293 }
294
295 1420 *value_ = static_cast<V>( v );
296 1420 return this->parent_->signal_value(ec);
297 }
298
299 74 bool on_uint64(system::error_code& ec, std::uint64_t v)
300 {
301
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 35 times.
74 if( !integral_in_range<V>(v) )
302 {
303 4 BOOST_JSON_FAIL( ec, error::not_exact );
304 4 return false;
305 }
306
307 70 *value_ = static_cast<V>(v);
308 70 return this->parent_->signal_value(ec);
309 }
310 };
311
312 // floating point handler
313 template< class V, class P>
314 class converting_handler<floating_point_conversion_tag, V, P>
315 : public scalar_handler<P, error::not_double>
316 {
317 private:
318 V* value_;
319
320 public:
321 106 converting_handler( V* v, P* p )
322 : converting_handler::scalar_handler(p)
323 106 , value_(v)
324 106 {}
325
326 198 bool on_number_part( system::error_code& )
327 {
328 198 return true;
329 }
330
331 2 bool on_int64(system::error_code& ec, std::int64_t v)
332 {
333 2 *value_ = static_cast<V>(v);
334 2 return this->parent_->signal_value(ec);
335 }
336
337 2 bool on_uint64(system::error_code& ec, std::uint64_t v)
338 {
339 2 *value_ = static_cast<V>(v);
340 2 return this->parent_->signal_value(ec);
341 }
342
343 126 bool on_double(system::error_code& ec, double v)
344 {
345 126 *value_ = static_cast<V>(v);
346 126 return this->parent_->signal_value(ec);
347 }
348 };
349
350 // string handler
351 template< class V, class P >
352 class converting_handler<string_like_conversion_tag, V, P>
353 : public scalar_handler<P, error::not_string>
354 {
355 private:
356 V* value_;
357 bool cleared_ = false;
358
359 public:
360 190 converting_handler( V* v, P* p )
361 : converting_handler::scalar_handler(p)
362 190 , value_(v)
363 190 {}
364
365 42 bool on_string_part( system::error_code&, string_view sv )
366 {
367
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 16 times.
42 if( !cleared_ )
368 {
369 10 cleared_ = true;
370 10 value_->clear();
371 }
372
373 42 value_->append( sv.begin(), sv.end() );
374 42 return true;
375 }
376
377 200 bool on_string(system::error_code& ec, string_view sv)
378 {
379
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 5 times.
200 if( !cleared_ )
380 190 value_->clear();
381 else
382 10 cleared_ = false;
383
384 200 value_->append( sv.begin(), sv.end() );
385 200 return this->parent_->signal_value(ec);
386 }
387 };
388
389 // bool handler
390 template< class V, class P >
391 class converting_handler<bool_conversion_tag, V, P>
392 : public scalar_handler<P, error::not_bool>
393 {
394 private:
395 V* value_;
396
397 public:
398 120 converting_handler( V* v, P* p )
399 : converting_handler::scalar_handler(p)
400 120 , value_(v)
401 120 {}
402
403 84 bool on_bool(system::error_code& ec, bool v)
404 {
405 84 *value_ = v;
406 84 return this->parent_->signal_value(ec);
407 }
408 };
409
410 // null handler
411 template< class V, class P >
412 class converting_handler<null_like_conversion_tag, V, P>
413 : public scalar_handler<P, error::not_null>
414 {
415 private:
416 V* value_;
417
418 public:
419 110 converting_handler( V* v, P* p )
420 : converting_handler::scalar_handler(p)
421 110 , value_(v)
422 110 {}
423
424 70 bool on_null(system::error_code& ec)
425 {
426 70 *value_ = {};
427 70 return this->parent_->signal_value(ec);
428 }
429 };
430
431 // described enum handler
432 template< class V, class P >
433 class converting_handler<described_enum_conversion_tag, V, P>
434 : public scalar_handler<P, error::not_string>
435 {
436 #ifndef BOOST_DESCRIBE_CXX14
437
438 static_assert(
439 sizeof(V) == 0, "Enum support for parse_into requires C++14" );
440
441 #else
442
443 private:
444 V* value_;
445 std::string name_;
446
447 public:
448 converting_handler( V* v, P* p )
449 : converting_handler::scalar_handler(p)
450 , value_(v)
451 {}
452
453 bool on_string_part( system::error_code&, string_view sv )
454 {
455 name_.append( sv.begin(), sv.end() );
456 return true;
457 }
458
459 bool on_string(system::error_code& ec, string_view sv)
460 {
461 string_view name = sv;
462 if( !name_.empty() )
463 {
464 name_.append( sv.begin(), sv.end() );
465 name = name_;
466 }
467
468 if( !describe::enum_from_string(name, *value_) )
469 {
470 BOOST_JSON_FAIL(ec, error::unknown_name);
471 return false;
472 }
473
474 return this->parent_->signal_value(ec);
475 }
476
477 #endif // BOOST_DESCRIBE_CXX14
478 };
479
480 template< class V, class P >
481 class converting_handler<no_conversion_tag, V, P>
482 {
483 static_assert( sizeof(V) == 0, "This type is not supported" );
484 };
485
486 // sequence handler
487 template< class It >
488 128 bool cannot_insert(It i, It e)
489 {
490 128 return i == e;
491 }
492
493 template< class It1, class It2 >
494 1008 std::false_type cannot_insert(It1, It2)
495 {
496 1008 return {};
497 }
498
499 template< class It >
500 30 bool needs_more_elements(It i, It e)
501 {
502 30 return i != e;
503 }
504
505 template< class It1, class It2 >
506 486 std::false_type needs_more_elements(It1, It2)
507 {
508 486 return {};
509 }
510
511 template<class T>
512 void
513 32 clear_container(
514 T&,
515 mp11::mp_int<2>)
516 {
517 32 }
518
519 template<class T>
520 void
521 518 clear_container(
522 T& target,
523 mp11::mp_int<1>)
524 {
525 518 target.clear();
526 518 }
527
528 template<class T>
529 void
530 297 clear_container(
531 T& target,
532 mp11::mp_int<0>)
533 {
534 297 target.clear();
535 297 }
536
537 template< class V, class P >
538 class converting_handler<sequence_conversion_tag, V, P>
539 : public composite_handler<
540 converting_handler<sequence_conversion_tag, V, P>,
541 detail::value_type<V>,
542 P,
543 error::not_array>
544 {
545 private:
546 V* value_;
547
548 using Inserter = decltype(
549 detail::inserter(*value_, inserter_implementation<V>()) );
550 Inserter inserter;
551
552 public:
553 551 converting_handler( V* v, P* p )
554 : converting_handler::composite_handler(p)
555 551 , value_(v)
556
1/1
✓ Branch 2 taken 65 times.
551 , inserter( detail::inserter(*value_, inserter_implementation<V>()) )
557 551 {}
558
559 1264 bool signal_value(system::error_code& ec)
560 {
561
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 507 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 126 times.
1264 if(cannot_insert( inserter, value_->end() ))
562 {
563 4 BOOST_JSON_FAIL( ec, error::size_mismatch );
564 4 return false;
565 }
566
567
1/1
✓ Branch 4 taken 507 times.
1260 *inserter++ = std::move(this->next_value_);
568 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
569 # pragma GCC diagnostic push
570 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
571 #endif
572 1260 this->next_value_ = {};
573 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
574 # pragma GCC diagnostic pop
575 #endif
576 1260 return true;
577 }
578
579 546 bool signal_end(system::error_code& ec)
580 {
581
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 244 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 28 times.
546 if(needs_more_elements( inserter, value_->end() ))
582 {
583 4 BOOST_JSON_FAIL( ec, error::size_mismatch );
584 4 return false;
585 }
586
587 542 inserter = detail::inserter(*value_, inserter_implementation<V>());
588
589 542 return converting_handler::composite_handler::signal_end(ec);
590 }
591
592 946 bool on_array_begin( system::error_code& ec )
593 {
594
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 292 times.
946 if( this->inner_active_ )
595 364 return this->inner_.on_array_begin( ec );
596
597 582 this->inner_active_ = true;
598 582 clear_container( *value_, inserter_implementation<V>() );
599 582 return true;
600 }
601
602 994 bool on_array_end( system::error_code& ec )
603 {
604
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 42 times.
994 if( this->inner_active_ )
605 910 return this->inner_.on_array_end( ec );
606
607 84 return this->parent_->signal_end(ec);
608 }
609 };
610
611 // map handler
612 template< class V, class P >
613 class converting_handler<map_like_conversion_tag, V, P>
614 : public composite_handler<
615 converting_handler<map_like_conversion_tag, V, P>,
616 detail::mapped_type<V>,
617 P,
618 error::not_object>
619 {
620 private:
621 V* value_;
622 std::string key_;
623
624 public:
625 273 converting_handler( V* v, P* p )
626 273 : converting_handler::composite_handler(p), value_(v)
627 273 {}
628
629 268 bool signal_value(system::error_code&)
630 {
631 268 value_->emplace( std::move(key_), std::move(this->next_value_) );
632
633 268 key_ = {};
634 268 this->next_value_ = {};
635
636 268 this->inner_active_ = false;
637
638 268 return true;
639 }
640
641 329 bool on_object_begin( system::error_code& ec )
642 {
643
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 149 times.
329 if( this->inner_active_ )
644 32 return this->inner_.on_object_begin(ec);
645
646 297 clear_container( *value_, inserter_implementation<V>() );
647 297 return true;
648 }
649
650 307 bool on_object_end(system::error_code& ec)
651 {
652
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 138 times.
307 if( this->inner_active_ )
653 32 return this->inner_.on_object_end(ec);
654
655 275 return this->parent_->signal_value(ec);
656 }
657
658 118 bool on_array_end( system::error_code& ec )
659 {
660
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 7 times.
118 if( this->inner_active_ )
661 104 return this->inner_.on_array_end(ec);
662
663 14 return this->parent_->signal_end(ec);
664 }
665
666 90 bool on_key_part( system::error_code& ec, string_view sv )
667 {
668
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43 times.
90 if( this->inner_active_ )
669 4 return this->inner_.on_key_part(ec, sv);
670
671 86 key_.append( sv.data(), sv.size() );
672 86 return true;
673 }
674
675 318 bool on_key( system::error_code& ec, string_view sv )
676 {
677
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 146 times.
318 if( this->inner_active_ )
678 28 return this->inner_.on_key(ec, sv);
679
680 290 key_.append( sv.data(), sv.size() );
681
682 290 this->inner_active_ = true;
683 290 return true;
684 }
685 };
686
687 // tuple handler
688 template<std::size_t I, class T>
689 struct handler_tuple_element
690 {
691 template< class... Args >
692 572 handler_tuple_element( Args&& ... args )
693 572 : t_( static_cast<Args&&>(args)... )
694 572 {}
695
696 T t_;
697 };
698
699 template<std::size_t I, class T>
700 T&
701 1032 get( handler_tuple_element<I, T>& e )
702 {
703 1032 return e.t_;
704 }
705
706 template<
707 class P,
708 class LV,
709 class S = mp11::make_index_sequence<mp11::mp_size<LV>::value> >
710 struct handler_tuple;
711
712 template< class P, template<class...> class L, class... V, std::size_t... I >
713 struct handler_tuple< P, L<V...>, mp11::index_sequence<I...> >
714 : handler_tuple_element<I, V>
715 ...
716 {
717 handler_tuple( handler_tuple const& ) = delete;
718 handler_tuple& operator=( handler_tuple const& ) = delete;
719
720 template< class Access, class T >
721 258 handler_tuple( Access access, T* pv, P* pp )
722 : handler_tuple_element<I, V>(
723 12 access( pv, mp11::mp_size_t<I>() ),
724 pp )
725
3/3
✓ Branch 2 taken 129 times.
✓ Branch 6 taken 127 times.
✓ Branch 10 taken 30 times.
258 ...
726 258 {}
727 };
728
729 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
730
731 template< class T >
732 struct tuple_element_list_impl
733 {
734 template< class I >
735 using tuple_element_helper = tuple_element_t<I::value, T>;
736
737 using type = mp11::mp_transform<
738 tuple_element_helper,
739 mp11::mp_iota< std::tuple_size<T> > >;
740 };
741 template< class T >
742 using tuple_element_list = typename tuple_element_list_impl<T>::type;
743
744 #else
745
746 template< class I, class T >
747 using tuple_element_helper = tuple_element_t<I::value, T>;
748 template< class T >
749 using tuple_element_list = mp11::mp_transform_q<
750 mp11::mp_bind_back< tuple_element_helper, T>,
751 mp11::mp_iota< std::tuple_size<T> > >;
752
753 #endif
754
755 template< class Op, class... Args>
756 struct handler_op_invoker
757 {
758 public:
759 std::tuple<Args&...> args;
760
761 template< class Handler >
762 bool
763 932 operator()( Handler& handler ) const
764 {
765 932 return (*this)( handler, mp11::index_sequence_for<Args...>() );
766 }
767
768 private:
769 template< class Handler, std::size_t... I >
770 bool
771 932 operator()( Handler& handler, mp11::index_sequence<I...> ) const
772 {
773
1/1
✓ Branch 2 taken 131 times.
932 return Op()( handler, std::get<I>(args)... );
774 }
775 };
776
777 template< class Handlers, class F >
778 struct tuple_handler_op_invoker
779 {
780 Handlers& handlers;
781 F fn;
782
783 template< class I >
784 bool
785 932 operator()( I ) const
786 {
787 932 return fn( get<I::value>(handlers) );
788 }
789 };
790
791 struct tuple_accessor
792 {
793 template< class T, class I >
794 572 auto operator()( T* t, I ) const -> tuple_element_t<I::value, T>*
795 {
796 using std::get;
797 572 return &get<I::value>(*t);
798 }
799 };
800
801 template< class T, class P >
802 class converting_handler<tuple_conversion_tag, T, P>
803 {
804
805 private:
806 using ElementTypes = tuple_element_list<T>;
807
808 template<class V>
809 using ElementHandler = get_handler<V, converting_handler>;
810 using InnerHandlers = mp11::mp_transform<ElementHandler, ElementTypes>;
811 using HandlerTuple = handler_tuple<converting_handler, InnerHandlers>;
812
813 T* value_;
814 P* parent_;
815
816 HandlerTuple handlers_;
817 int inner_active_ = -1;
818
819 public:
820 converting_handler( converting_handler const& ) = delete;
821 converting_handler& operator=( converting_handler const& ) = delete;
822
823 258 converting_handler( T* v, P* p )
824 258 : value_(v) , parent_(p) , handlers_(tuple_accessor(), v, this)
825 258 {}
826
827 566 bool signal_value(system::error_code&)
828 {
829 566 ++inner_active_;
830 566 return true;
831 }
832
833 246 bool signal_end(system::error_code& ec)
834 {
835 246 constexpr int N = std::tuple_size<T>::value;
836
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 119 times.
246 if( inner_active_ < N )
837 {
838 8 BOOST_JSON_FAIL( ec, error::size_mismatch );
839 8 return false;
840 }
841
842 238 inner_active_ = -1;
843 238 return parent_->signal_value(ec);
844 }
845
846 #define BOOST_JSON_HANDLE_EVENT(fn) \
847 struct do_ ## fn \
848 { \
849 template< class H, class... Args > \
850 bool operator()( H& h, Args& ... args ) const \
851 { \
852 return h. fn (args...); \
853 } \
854 }; \
855 \
856 template< class... Args > \
857 bool fn( system::error_code& ec, Args&& ... args ) \
858 { \
859 if( inner_active_ < 0 ) \
860 { \
861 BOOST_JSON_FAIL( ec, error::not_array ); \
862 return false; \
863 } \
864 constexpr int N = std::tuple_size<T>::value; \
865 if( inner_active_ >= N ) \
866 { \
867 BOOST_JSON_FAIL( ec, error::size_mismatch ); \
868 return false; \
869 } \
870 using F = handler_op_invoker< do_ ## fn, system::error_code, Args...>; \
871 using H = decltype(handlers_); \
872 return mp11::mp_with_index<N>( \
873 inner_active_, \
874 tuple_handler_op_invoker<H, F>{ \
875 handlers_, \
876 F{ std::forward_as_tuple(ec, args...) } } ); \
877 }
878
879
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 28 times.
✓ Branch 10 taken 28 times.
112 BOOST_JSON_HANDLE_EVENT( on_object_begin )
880
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
✓ Branch 10 taken 21 times.
84 BOOST_JSON_HANDLE_EVENT( on_object_end )
881
882 struct do_on_array_begin
883 {
884 HandlerTuple& handlers;
885 system::error_code& ec;
886
887 template< class I >
888 46 bool operator()( I ) const
889 {
890 46 return get<I::value>(handlers).on_array_begin(ec);
891 }
892 };
893 318 bool on_array_begin( system::error_code& ec )
894 {
895
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 25 times.
318 if( inner_active_ < 0 )
896 {
897 268 inner_active_ = 0;
898 268 return true;
899 }
900
901 50 constexpr int N = std::tuple_size<T>::value;
902
903
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
50 if( inner_active_ >= N )
904 {
905 4 BOOST_JSON_FAIL( ec, error::size_mismatch );
906 4 return false;
907 }
908
909 46 return mp11::mp_with_index<N>(
910
1/1
✓ Branch 1 taken 23 times.
46 inner_active_, do_on_array_begin{handlers_, ec} );
911 }
912
913 struct do_on_array_end
914 {
915 HandlerTuple& handlers;
916 system::error_code& ec;
917
918 template< class I >
919 54 bool operator()( I ) const
920 {
921 54 return get<I::value>(handlers).on_array_end(ec);
922 }
923 };
924 390 bool on_array_end( system::error_code& ec )
925 {
926
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 146 times.
390 if( inner_active_ < 0 )
927 98 return parent_->signal_end(ec);
928
929 292 constexpr int N = std::tuple_size<T>::value;
930
931
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 27 times.
292 if( inner_active_ >= N )
932 238 return signal_end(ec);
933
934 54 return mp11::mp_with_index<N>(
935
1/1
✓ Branch 1 taken 27 times.
54 inner_active_, do_on_array_end{handlers_, ec} );
936 }
937
938
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 10 taken 3 times.
12 BOOST_JSON_HANDLE_EVENT( on_key_part )
939
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 28 times.
✓ Branch 10 taken 28 times.
✓ Branch 2 taken 21 times.
112 BOOST_JSON_HANDLE_EVENT( on_key )
940
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✓ Branch 10 taken 5 times.
20 BOOST_JSON_HANDLE_EVENT( on_string_part )
941
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 28 times.
✓ Branch 10 taken 28 times.
✓ Branch 2 taken 14 times.
112 BOOST_JSON_HANDLE_EVENT( on_string )
942
5/5
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 76 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 75 times.
✓ Branch 10 taken 75 times.
304 BOOST_JSON_HANDLE_EVENT( on_number_part )
943
5/5
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 216 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 215 times.
✓ Branch 10 taken 215 times.
864 BOOST_JSON_HANDLE_EVENT( on_int64 )
944
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✓ Branch 10 taken 7 times.
28 BOOST_JSON_HANDLE_EVENT( on_uint64 )
945
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 35 times.
✓ Branch 10 taken 35 times.
140 BOOST_JSON_HANDLE_EVENT( on_double )
946
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✓ Branch 10 taken 14 times.
56 BOOST_JSON_HANDLE_EVENT( on_bool )
947
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✓ Branch 10 taken 7 times.
28 BOOST_JSON_HANDLE_EVENT( on_null )
948
949 #undef BOOST_JSON_HANDLE_EVENT
950 };
951
952 // described struct handler
953 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
954
955 template< class T >
956 struct struct_element_list_impl
957 {
958 template< class D >
959 using helper = described_member_t<T, D>;
960
961 using type = mp11::mp_transform< helper, described_members<T> >;
962 };
963 template< class T >
964 using struct_element_list = typename struct_element_list_impl<T>::type;
965
966 #else
967
968 template< class T >
969 using struct_element_list = mp11::mp_transform_q<
970 mp11::mp_bind_front< described_member_t, T >, described_members<T> >;
971
972 #endif
973
974 struct struct_accessor
975 {
976 template< class T >
977 auto operator()( T*, mp11::mp_size< described_members<T> > ) const
978 -> void*
979 {
980 return nullptr;
981 }
982
983 template< class T, class I >
984 auto operator()( T* t, I ) const
985 -> described_member_t<T, mp11::mp_at< described_members<T>, I> >*
986 {
987 using Ds = described_members<T>;
988 using D = mp11::mp_at<Ds, I>;
989 return &(t->*D::pointer);
990 }
991 };
992
993 struct struct_key_searcher
994 {
995 string_view key;
996 int& found;
997 int index = 0;
998
999 struct_key_searcher(string_view key, int& found) noexcept
1000 : key(key), found(found)
1001 {}
1002
1003 template< class D >
1004 void
1005 operator()( D )
1006 {
1007 if( key == D::name )
1008 found = index;
1009 ++index;
1010 }
1011 };
1012
1013 template<class P>
1014 struct ignoring_handler
1015 {
1016 P* parent_;
1017 std::size_t array_depth_ = 0;
1018 std::size_t object_depth_ = 0;
1019
1020 ignoring_handler(ignoring_handler const&) = delete;
1021 ignoring_handler& operator=(ignoring_handler const&) = delete;
1022
1023 ignoring_handler(void*, P* p) noexcept
1024 : parent_(p)
1025 {}
1026
1027 bool on_object_begin(system::error_code&)
1028 {
1029 ++object_depth_;
1030 return true;
1031 }
1032
1033 bool on_object_end(system::error_code& ec)
1034 {
1035 BOOST_ASSERT( object_depth_ > 0 );
1036 --object_depth_;
1037
1038 if( (array_depth_ + object_depth_) == 0 )
1039 return parent_->signal_value(ec);
1040 return true;
1041 }
1042
1043 bool on_array_begin(system::error_code&)
1044 {
1045 ++array_depth_;
1046 return true;
1047 }
1048
1049 bool on_array_end(system::error_code& ec)
1050 {
1051 BOOST_ASSERT( array_depth_ > 0 );
1052 --array_depth_;
1053
1054 if( (array_depth_ + object_depth_) == 0 )
1055 return parent_->signal_end(ec);
1056 return true;
1057 }
1058
1059 bool on_key_part(system::error_code&, string_view)
1060 {
1061 return true;
1062 }
1063
1064 bool on_key(system::error_code&, string_view)
1065 {
1066 return true;
1067 }
1068
1069 bool on_string_part(system::error_code&, string_view)
1070 {
1071 return true;
1072 }
1073
1074 bool on_string(system::error_code& ec, string_view)
1075 {
1076 if( (array_depth_ + object_depth_) == 0 )
1077 return parent_->signal_value(ec);
1078 return true;
1079 }
1080
1081 bool on_number_part(system::error_code&)
1082 {
1083 return true;
1084 }
1085
1086 bool on_int64(system::error_code& ec, std::int64_t)
1087 {
1088 if( (array_depth_ + object_depth_) == 0 )
1089 return parent_->signal_value(ec);
1090 return true;
1091 }
1092
1093 bool on_uint64(system::error_code& ec, std::uint64_t)
1094 {
1095 if( (array_depth_ + object_depth_) == 0 )
1096 return parent_->signal_value(ec);
1097 return true;
1098 }
1099
1100 bool on_double(system::error_code& ec, double)
1101 {
1102 if( (array_depth_ + object_depth_) == 0 )
1103 return parent_->signal_value(ec);
1104 return true;
1105 }
1106
1107 bool on_bool(system::error_code& ec, bool)
1108 {
1109 if( (array_depth_ + object_depth_) == 0 )
1110 return parent_->signal_value(ec);
1111 return true;
1112 }
1113
1114 bool on_null(system::error_code& ec)
1115 {
1116 if( (array_depth_ + object_depth_) == 0 )
1117 return parent_->signal_value(ec);
1118 return true;
1119 }
1120 };
1121
1122 template<class V, class P>
1123 class converting_handler<described_class_conversion_tag, V, P>
1124 {
1125 #if !defined(BOOST_DESCRIBE_CXX14)
1126
1127 static_assert(
1128 sizeof(V) == 0, "Struct support for parse_into requires C++14" );
1129
1130 #else
1131
1132 private:
1133 using Dm = described_members<V>;
1134 using Dt = struct_element_list<V>;
1135
1136 template<class T>
1137 using MemberHandler = get_handler<T, converting_handler>;
1138 using InnerHandlers = mp11::mp_push_back<
1139 mp11::mp_transform<MemberHandler, Dt>,
1140 ignoring_handler<converting_handler> >;
1141 using InnerCount = mp11::mp_size<InnerHandlers>;
1142
1143 V* value_;
1144 P* parent_;
1145
1146 std::string key_;
1147
1148 handler_tuple<converting_handler, InnerHandlers> handlers_;
1149 int inner_active_ = -1;
1150 std::size_t activated_ = 0;
1151
1152 public:
1153 converting_handler( converting_handler const& ) = delete;
1154 converting_handler& operator=( converting_handler const& ) = delete;
1155
1156 converting_handler( V* v, P* p )
1157 : value_(v), parent_(p), handlers_(struct_accessor(), v, this)
1158 {}
1159
1160 struct is_required_checker
1161 {
1162 bool operator()( mp11::mp_size<Dt> ) const noexcept
1163 {
1164 return false;
1165 }
1166
1167 template< class I >
1168 auto operator()( I ) const noexcept
1169 {
1170 using T = mp11::mp_at<Dt, I>;
1171 return !is_optional_like<T>::value;
1172 }
1173 };
1174
1175 bool signal_value(system::error_code&)
1176 {
1177 BOOST_ASSERT( inner_active_ >= 0 );
1178 bool required_member = mp11::mp_with_index<InnerCount>(
1179 inner_active_,
1180 is_required_checker{});
1181 if( required_member )
1182 ++activated_;
1183
1184 key_ = {};
1185 inner_active_ = -1;
1186 return true;
1187 }
1188
1189 bool signal_end(system::error_code& ec)
1190 {
1191 key_ = {};
1192 inner_active_ = -1;
1193 return parent_->signal_value(ec);
1194 }
1195
1196 #define BOOST_JSON_INVOKE_INNER(fn) \
1197 if( inner_active_ < 0 ) \
1198 { \
1199 BOOST_JSON_FAIL( ec, error::not_object ); \
1200 return false; \
1201 } \
1202 auto f = [&](auto& handler) { return handler.fn ; }; \
1203 using F = decltype(f); \
1204 using H = decltype(handlers_); \
1205 return mp11::mp_with_index<InnerCount>( \
1206 inner_active_, \
1207 tuple_handler_op_invoker<H, F>{handlers_, f} );
1208
1209 bool on_object_begin( system::error_code& ec )
1210 {
1211 if( inner_active_ < 0 )
1212 return true;
1213
1214 BOOST_JSON_INVOKE_INNER( on_object_begin(ec) );
1215 }
1216
1217 bool on_object_end( system::error_code& ec )
1218 {
1219 if( inner_active_ < 0 )
1220 {
1221 using C = mp11::mp_count_if<Dt, is_optional_like>;
1222 constexpr int N = mp11::mp_size<Dt>::value - C::value;
1223 if( activated_ < N )
1224 {
1225 BOOST_JSON_FAIL( ec, error::size_mismatch );
1226 return false;
1227 }
1228
1229 return parent_->signal_value(ec);
1230 }
1231
1232 BOOST_JSON_INVOKE_INNER( on_object_end(ec) );
1233 }
1234
1235 bool on_array_begin( system::error_code& ec )
1236 {
1237 BOOST_JSON_INVOKE_INNER( on_array_begin(ec) );
1238 }
1239
1240 bool on_array_end( system::error_code& ec )
1241 {
1242 if( inner_active_ < 0 )
1243 return parent_->signal_end(ec);
1244
1245 BOOST_JSON_INVOKE_INNER( on_array_end(ec) );
1246 }
1247
1248 bool on_key_part( system::error_code& ec, string_view sv )
1249 {
1250 if( inner_active_ < 0 )
1251 {
1252 key_.append( sv.data(), sv.size() );
1253 return true;
1254 }
1255
1256 BOOST_JSON_INVOKE_INNER( on_key_part(ec, sv) );
1257 }
1258
1259 bool on_key( system::error_code& ec, string_view sv )
1260 {
1261 if( inner_active_ >= 0 )
1262 {
1263 BOOST_JSON_INVOKE_INNER( on_key(ec, sv) );
1264 }
1265
1266 string_view key = sv;
1267 if( !key_.empty() )
1268 {
1269 key_.append( sv.data(), sv.size() );
1270 key = key_;
1271 }
1272
1273 inner_active_ = InnerCount::value - 1;
1274 mp11::mp_for_each<Dm>( struct_key_searcher(key, inner_active_) );
1275 return true;
1276 }
1277
1278 bool on_string_part( system::error_code& ec, string_view sv )
1279 {
1280 BOOST_JSON_INVOKE_INNER( on_string_part(ec, sv) );
1281 }
1282
1283 bool on_string( system::error_code& ec, string_view sv )
1284 {
1285 BOOST_JSON_INVOKE_INNER( on_string(ec, sv) );
1286 }
1287
1288 bool on_number_part( system::error_code& ec )
1289 {
1290 BOOST_JSON_INVOKE_INNER( on_number_part(ec) );
1291 }
1292
1293 bool on_int64( system::error_code& ec, std::int64_t v )
1294 {
1295 BOOST_JSON_INVOKE_INNER( on_int64(ec, v) );
1296 }
1297
1298 bool on_uint64( system::error_code& ec, std::uint64_t v )
1299 {
1300 BOOST_JSON_INVOKE_INNER( on_uint64(ec, v) );
1301 }
1302
1303 bool on_double( system::error_code& ec, double v )
1304 {
1305 BOOST_JSON_INVOKE_INNER( on_double(ec, v) );
1306 }
1307
1308 bool on_bool( system::error_code& ec, bool v )
1309 {
1310 BOOST_JSON_INVOKE_INNER( on_bool(ec, v) );
1311 }
1312
1313 bool on_null( system::error_code& ec )
1314 {
1315 BOOST_JSON_INVOKE_INNER( on_null(ec) );
1316 }
1317
1318 #undef BOOST_JSON_INVOKE_INNER
1319
1320 #endif
1321 };
1322
1323 // variant handler
1324 struct object_begin_handler_event
1325 { };
1326
1327 struct object_end_handler_event
1328 { };
1329
1330 struct array_begin_handler_event
1331 { };
1332
1333 struct array_end_handler_event
1334 { };
1335
1336 struct key_handler_event
1337 {
1338 std::string value;
1339 };
1340
1341 struct string_handler_event
1342 {
1343 std::string value;
1344 };
1345
1346 struct int64_handler_event
1347 {
1348 std::int64_t value;
1349 };
1350
1351 struct uint64_handler_event
1352 {
1353 std::uint64_t value;
1354 };
1355
1356 struct double_handler_event
1357 {
1358 double value;
1359 };
1360
1361 struct bool_handler_event
1362 {
1363 bool value;
1364 };
1365
1366 struct null_handler_event
1367 { };
1368
1369 using parse_event = variant2::variant<
1370 object_begin_handler_event,
1371 object_end_handler_event,
1372 array_begin_handler_event,
1373 array_end_handler_event,
1374 key_handler_event,
1375 string_handler_event,
1376 int64_handler_event,
1377 uint64_handler_event,
1378 double_handler_event,
1379 bool_handler_event,
1380 null_handler_event>;
1381
1382 template< class H >
1383 struct event_visitor
1384 {
1385 H& handler;
1386 system::error_code& ec;
1387
1388 bool
1389 28 operator()(object_begin_handler_event&) const
1390 {
1391 28 return handler.on_object_begin(ec);
1392 }
1393
1394 bool
1395 14 operator()(object_end_handler_event&) const
1396 {
1397 14 return handler.on_object_end(ec);
1398 }
1399
1400 bool
1401 84 operator()(array_begin_handler_event&) const
1402 {
1403 84 return handler.on_array_begin(ec);
1404 }
1405
1406 bool
1407 42 operator()(array_end_handler_event&) const
1408 {
1409 42 return handler.on_array_end(ec);
1410 }
1411
1412 bool
1413 42 operator()(key_handler_event& ev) const
1414 {
1415 42 return handler.on_key(ec, ev.value);
1416 }
1417
1418 bool
1419 216 operator()(string_handler_event& ev) const
1420 {
1421
1/1
✓ Branch 2 taken 35 times.
216 return handler.on_string(ec, ev.value);
1422 }
1423
1424 bool
1425 308 operator()(int64_handler_event& ev) const
1426 {
1427 308 return handler.on_int64(ec, ev.value);
1428 }
1429
1430 bool
1431 28 operator()(uint64_handler_event& ev) const
1432 {
1433 28 return handler.on_uint64(ec, ev.value);
1434 }
1435
1436 bool
1437 42 operator()(double_handler_event& ev) const
1438 {
1439 42 return handler.on_double(ec, ev.value);
1440 }
1441
1442 bool
1443 14 operator()(bool_handler_event& ev) const
1444 {
1445 14 return handler.on_bool(ec, ev.value);
1446 }
1447
1448 bool
1449 14 operator()(null_handler_event&) const
1450 {
1451 14 return handler.on_null(ec);
1452 }
1453 };
1454
1455 // L<T...> -> variant< monostate, get_handler<T, P>... >
1456 template< class P, class L >
1457 using inner_handler_variant = mp11::mp_push_front<
1458 mp11::mp_transform_q<
1459 mp11::mp_bind_back<get_handler, P>,
1460 mp11::mp_apply<variant2::variant, L>>,
1461 variant2::monostate>;
1462
1463 template< class T, class P >
1464 class converting_handler<variant_conversion_tag, T, P>
1465 {
1466 private:
1467 using variant_size = mp11::mp_size<T>;
1468
1469 T* value_;
1470 P* parent_;
1471
1472 std::string string_;
1473 std::vector< parse_event > events_;
1474 inner_handler_variant<converting_handler, T> inner_;
1475 int inner_active_ = -1;
1476
1477 public:
1478 converting_handler( converting_handler const& ) = delete;
1479 converting_handler& operator=( converting_handler const& ) = delete;
1480
1481 180 converting_handler( T* v, P* p )
1482 180 : value_( v )
1483 180 , parent_( p )
1484 180 {}
1485
1486 252 bool signal_value(system::error_code& ec)
1487 {
1488 252 inner_.template emplace<0>();
1489 252 inner_active_ = -1;
1490 252 events_.clear();
1491 252 return parent_->signal_value(ec);
1492 }
1493
1494 28 bool signal_end(system::error_code& ec)
1495 {
1496 28 return parent_->signal_end(ec);
1497 }
1498
1499 struct alternative_selector
1500 {
1501 converting_handler* self;
1502
1503 template< class I >
1504 void
1505 454 operator()( I ) const
1506 {
1507 using V = mp11::mp_at<T, I>;
1508
1/1
✓ Branch 1 taken 157 times.
454 auto& v = self->value_->template emplace<I::value>( V{} );
1509
1/1
✓ Branch 1 taken 227 times.
454 self->inner_.template emplace<I::value + 1>(&v, self);
1510 454 }
1511 };
1512 void
1513 466 next_alternative()
1514 {
1515
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 227 times.
466 if( ++inner_active_ >= static_cast<int>(variant_size::value) )
1516 12 return;
1517
1518 454 mp11::mp_with_index< variant_size::value >(
1519
1/1
✓ Branch 1 taken 227 times.
454 inner_active_, alternative_selector{this} );
1520 }
1521
1522 struct event_processor
1523 {
1524 converting_handler* self;
1525 system::error_code& ec;
1526 parse_event& event;
1527
1528 template< class I >
1529 832 bool operator()( I ) const
1530 {
1531 832 auto& handler = variant2::get<I::value + 1>(self->inner_);
1532 using Handler = remove_cvref<decltype(handler)>;
1533 832 return variant2::visit(
1534
1/1
✓ Branch 1 taken 416 times.
1664 event_visitor<Handler>{handler, ec}, event );
1535 }
1536 };
1537 572 bool process_events(system::error_code& ec)
1538 {
1539 572 constexpr std::size_t N = variant_size::value;
1540
1541 // should be pointers not iterators, otherwise MSVC crashes
1542 572 auto const last = events_.data() + events_.size();
1543 572 auto first = last - 1;
1544 572 bool ok = false;
1545
1546
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 140 times.
572 if( inner_active_ < 0 )
1547 292 next_alternative();
1548 do
1549 {
1550
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 367 times.
746 if( static_cast<std::size_t>(inner_active_) >= N )
1551 {
1552 12 BOOST_JSON_FAIL( ec, error::exhausted_variants );
1553 12 return false;
1554 }
1555
1556
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 280 times.
1392 for ( ; first != last; ++first )
1557 {
1558 1664 ok = mp11::mp_with_index< N >(
1559
1/1
✓ Branch 1 taken 416 times.
832 inner_active_, event_processor{this, ec, *first} );
1560
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 329 times.
832 if( !ok )
1561 {
1562 174 first = events_.data();
1563 174 next_alternative();
1564 174 ec.clear();
1565 174 break;
1566 }
1567 }
1568 }
1569
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 280 times.
734 while( !ok );
1570
1571 560 return true;
1572 }
1573
1574 #define BOOST_JSON_INVOKE_INNER(ev, ec) \
1575 events_.emplace_back( ev ); \
1576 return process_events(ec);
1577
1578 14 bool on_object_begin( system::error_code& ec )
1579 {
1580
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( object_begin_handler_event{}, ec );
1581 }
1582
1583 14 bool on_object_end( system::error_code& ec )
1584 {
1585
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( object_end_handler_event{}, ec );
1586 }
1587
1588 42 bool on_array_begin( system::error_code& ec )
1589 {
1590
1/1
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( array_begin_handler_event{}, ec );
1591 }
1592
1593 56 bool on_array_end( system::error_code& ec )
1594 {
1595
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 21 times.
56 if( !inner_active_ )
1596 14 return signal_end(ec);
1597
1598
1/1
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( array_end_handler_event{}, ec );
1599 }
1600
1601 10 bool on_key_part( system::error_code&, string_view sv )
1602 {
1603
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
10 string_.append(sv);
1604 10 return true;
1605 }
1606
1607 28 bool on_key( system::error_code& ec, string_view sv )
1608 {
1609
2/2
✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
28 string_.append(sv);
1610
1/1
✓ Branch 2 taken 14 times.
56 BOOST_JSON_INVOKE_INNER( key_handler_event{ std::move(string_) }, ec );
1611 28 }
1612
1613 62 bool on_string_part( system::error_code&, string_view sv )
1614 {
1615
2/2
✓ Branch 1 taken 31 times.
✓ Branch 4 taken 31 times.
62 string_.append(sv);
1616 62 return true;
1617 }
1618
1619 96 bool on_string( system::error_code& ec, string_view sv )
1620 {
1621
2/2
✓ Branch 1 taken 48 times.
✓ Branch 4 taken 48 times.
96 string_.append(sv);
1622
1/1
✓ Branch 2 taken 48 times.
192 BOOST_JSON_INVOKE_INNER(
1623 string_handler_event{ std::move(string_) }, ec );
1624 96 }
1625
1626 120 bool on_number_part( system::error_code& )
1627 {
1628 120 return true;
1629 }
1630
1631 266 bool on_int64( system::error_code& ec, std::int64_t v )
1632 {
1633
1/1
✓ Branch 1 taken 133 times.
266 BOOST_JSON_INVOKE_INNER( int64_handler_event{v}, ec );
1634 }
1635
1636 14 bool on_uint64( system::error_code& ec, std::uint64_t v )
1637 {
1638
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( uint64_handler_event{v}, ec );
1639 }
1640
1641 28 bool on_double( system::error_code& ec, double v )
1642 {
1643
1/1
✓ Branch 1 taken 14 times.
28 BOOST_JSON_INVOKE_INNER( double_handler_event{v}, ec );
1644 }
1645
1646 14 bool on_bool( system::error_code& ec, bool v )
1647 {
1648
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( bool_handler_event{v}, ec );
1649 }
1650
1651 14 bool on_null( system::error_code& ec )
1652 {
1653
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( null_handler_event{}, ec );
1654 }
1655
1656 #undef BOOST_JSON_INVOKE_INNER
1657 };
1658
1659 // optional handler
1660 template<class V, class P>
1661 class converting_handler<optional_conversion_tag, V, P>
1662 {
1663 private:
1664 using inner_type = value_result_type<V>;
1665 using inner_handler_type = get_handler<inner_type, converting_handler>;
1666
1667 V* value_;
1668 P* parent_;
1669
1670 inner_type inner_value_ = {};
1671 inner_handler_type inner_;
1672 bool inner_active_ = false;
1673
1674 public:
1675 converting_handler( converting_handler const& ) = delete;
1676 converting_handler& operator=( converting_handler const& ) = delete;
1677
1678 converting_handler( V* v, P* p )
1679 : value_(v), parent_(p), inner_(&inner_value_, this)
1680 {}
1681
1682 bool signal_value(system::error_code& ec)
1683 {
1684 *value_ = std::move(inner_value_);
1685
1686 inner_active_ = false;
1687 return parent_->signal_value(ec);
1688 }
1689
1690 bool signal_end(system::error_code& ec)
1691 {
1692 return parent_->signal_end(ec);
1693 }
1694
1695 #define BOOST_JSON_INVOKE_INNER(fn) \
1696 if( !inner_active_ ) \
1697 inner_active_ = true; \
1698 return inner_.fn;
1699
1700 bool on_object_begin( system::error_code& ec )
1701 {
1702 BOOST_JSON_INVOKE_INNER( on_object_begin(ec) );
1703 }
1704
1705 bool on_object_end( system::error_code& ec )
1706 {
1707 BOOST_JSON_INVOKE_INNER( on_object_end(ec) );
1708 }
1709
1710 bool on_array_begin( system::error_code& ec )
1711 {
1712 BOOST_JSON_INVOKE_INNER( on_array_begin(ec) );
1713 }
1714
1715 bool on_array_end( system::error_code& ec )
1716 {
1717 if( !inner_active_ )
1718 return signal_end(ec);
1719
1720 BOOST_JSON_INVOKE_INNER( on_array_end(ec) );
1721 }
1722
1723 bool on_key_part( system::error_code& ec, string_view sv )
1724 {
1725 BOOST_JSON_INVOKE_INNER( on_key_part(ec, sv) );
1726 }
1727
1728 bool on_key( system::error_code& ec, string_view sv )
1729 {
1730 BOOST_JSON_INVOKE_INNER( on_key(ec, sv) );
1731 }
1732
1733 bool on_string_part( system::error_code& ec, string_view sv )
1734 {
1735 BOOST_JSON_INVOKE_INNER( on_string_part(ec, sv) );
1736 }
1737
1738 bool on_string( system::error_code& ec, string_view sv )
1739 {
1740 BOOST_JSON_INVOKE_INNER( on_string(ec, sv) );
1741 }
1742
1743 bool on_number_part( system::error_code& ec )
1744 {
1745 BOOST_JSON_INVOKE_INNER( on_number_part(ec) );
1746 }
1747
1748 bool on_int64( system::error_code& ec, std::int64_t v )
1749 {
1750 BOOST_JSON_INVOKE_INNER( on_int64(ec, v) );
1751 }
1752
1753 bool on_uint64( system::error_code& ec, std::uint64_t v )
1754 {
1755 BOOST_JSON_INVOKE_INNER( on_uint64(ec, v) );
1756 }
1757
1758 bool on_double( system::error_code& ec, double v )
1759 {
1760 BOOST_JSON_INVOKE_INNER( on_double(ec, v) );
1761 }
1762
1763 bool on_bool( system::error_code& ec, bool v )
1764 {
1765 BOOST_JSON_INVOKE_INNER( on_bool(ec, v) );
1766 }
1767
1768 bool on_null(system::error_code& ec)
1769 {
1770 if( !inner_active_ )
1771 {
1772 *value_ = {};
1773 return this->parent_->signal_value(ec);
1774 }
1775 else
1776 {
1777 return inner_.on_null(ec);
1778 }
1779 }
1780
1781 #undef BOOST_JSON_INVOKE_INNER
1782 };
1783
1784 // path handler
1785 template< class V, class P >
1786 class converting_handler<path_conversion_tag, V, P>
1787 : public scalar_handler<P, error::not_string>
1788 {
1789 private:
1790 V* value_;
1791 bool cleared_ = false;
1792
1793 public:
1794 converting_handler( V* v, P* p )
1795 : converting_handler::scalar_handler(p)
1796 , value_(v)
1797 {}
1798
1799 bool on_string_part( system::error_code&, string_view sv )
1800 {
1801 if( !cleared_ )
1802 {
1803 cleared_ = true;
1804 value_->clear();
1805 }
1806
1807 value_->concat( sv.begin(), sv.end() );
1808 return true;
1809 }
1810
1811 bool on_string(system::error_code& ec, string_view sv)
1812 {
1813 if( !cleared_ )
1814 value_->clear();
1815 else
1816 cleared_ = false;
1817
1818 value_->concat( sv.begin(), sv.end() );
1819
1820 return this->parent_->signal_value(ec);
1821 }
1822 };
1823
1824 // into_handler
1825 template< class V >
1826 class into_handler
1827 {
1828 private:
1829
1830 using inner_handler_type = get_handler<V, into_handler>;
1831
1832 inner_handler_type inner_;
1833 bool inner_active_ = true;
1834
1835 public:
1836
1837 into_handler( into_handler const& ) = delete;
1838 into_handler& operator=( into_handler const& ) = delete;
1839
1840 public:
1841
1842 static constexpr std::size_t max_object_size = object::max_size();
1843 static constexpr std::size_t max_array_size = array::max_size();
1844 static constexpr std::size_t max_key_size = string::max_size();
1845 static constexpr std::size_t max_string_size = string::max_size();
1846
1847 public:
1848
1849 1043 explicit into_handler( V* v ): inner_( v, this )
1850 {
1851 1043 }
1852
1853 931 bool signal_value(system::error_code&)
1854 {
1855 931 return true;
1856 }
1857
1858 14 bool signal_end(system::error_code&)
1859 {
1860 14 return true;
1861 }
1862
1863 1041 bool on_document_begin( system::error_code& )
1864 {
1865 1041 return true;
1866 }
1867
1868 945 bool on_document_end( system::error_code& )
1869 {
1870 945 inner_active_ = false;
1871 945 return true;
1872 }
1873
1874 #define BOOST_JSON_INVOKE_INNER(f) \
1875 if( !inner_active_ ) \
1876 { \
1877 BOOST_JSON_FAIL( ec, error::extra_data ); \
1878 return false; \
1879 } \
1880 else \
1881 return inner_.f
1882
1883 287 bool on_object_begin( system::error_code& ec )
1884 {
1885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
287 BOOST_JSON_INVOKE_INNER( on_object_begin(ec) );
1886 }
1887
1888 275 bool on_object_end( std::size_t, system::error_code& ec )
1889 {
1890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
275 BOOST_JSON_INVOKE_INNER( on_object_end(ec) );
1891 }
1892
1893 834 bool on_array_begin( system::error_code& ec )
1894 {
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 418 times.
834 BOOST_JSON_INVOKE_INNER( on_array_begin(ec) );
1896 }
1897
1898 806 bool on_array_end( std::size_t, system::error_code& ec )
1899 {
1900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 404 times.
806 BOOST_JSON_INVOKE_INNER( on_array_end(ec) );
1901 }
1902
1903 96 bool on_key_part( string_view sv, std::size_t, system::error_code& ec )
1904 {
1905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
96 BOOST_JSON_INVOKE_INNER( on_key_part(ec, sv) );
1906 }
1907
1908 276 bool on_key( string_view sv, std::size_t, system::error_code& ec )
1909 {
1910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
276 BOOST_JSON_INVOKE_INNER( on_key(ec, sv) );
1911 }
1912
1913 108 bool on_string_part( string_view sv, std::size_t, system::error_code& ec )
1914 {
1915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
108 BOOST_JSON_INVOKE_INNER( on_string_part(ec, sv) );
1916 }
1917
1918 202 bool on_string( string_view sv, std::size_t, system::error_code& ec )
1919 {
1920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
202 BOOST_JSON_INVOKE_INNER( on_string(ec, sv) );
1921 }
1922
1923 968 bool on_number_part( string_view, system::error_code& ec )
1924 {
1925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
968 BOOST_JSON_INVOKE_INNER( on_number_part(ec) );
1926 }
1927
1928 1408 bool on_int64( std::int64_t v, string_view, system::error_code& ec )
1929 {
1930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
1408 BOOST_JSON_INVOKE_INNER( on_int64(ec, v) );
1931 }
1932
1933 78 bool on_uint64( std::uint64_t v, string_view, system::error_code& ec )
1934 {
1935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
78 BOOST_JSON_INVOKE_INNER( on_uint64(ec, v) );
1936 }
1937
1938 126 bool on_double( double v, string_view, system::error_code& ec )
1939 {
1940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
126 BOOST_JSON_INVOKE_INNER( on_double(ec, v) );
1941 }
1942
1943 88 bool on_bool( bool v, system::error_code& ec )
1944 {
1945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
88 BOOST_JSON_INVOKE_INNER( on_bool(ec, v) );
1946 }
1947
1948 78 bool on_null( system::error_code& ec )
1949 {
1950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
78 BOOST_JSON_INVOKE_INNER( on_null(ec) );
1951 }
1952
1953 2508 bool on_comment_part(string_view, system::error_code&)
1954 {
1955 2508 return true;
1956 }
1957
1958 66 bool on_comment(string_view, system::error_code&)
1959 {
1960 66 return true;
1961 }
1962
1963 #undef BOOST_JSON_INVOKE_INNER
1964 };
1965
1966 } // namespace detail
1967 } // namespace boost
1968 } // namespace json
1969
1970 #endif
1971