GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: detail/parse_into.hpp
Date: 2025-12-23 17:38:58
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 static_assert(
1134 uniquely_named_members<V>::value,
1135 "The type has several described members with the same name.");
1136
1137 using Dm = described_members<V>;
1138 using Dt = struct_element_list<V>;
1139
1140 template<class T>
1141 using MemberHandler = get_handler<T, converting_handler>;
1142 using InnerHandlers = mp11::mp_push_back<
1143 mp11::mp_transform<MemberHandler, Dt>,
1144 ignoring_handler<converting_handler> >;
1145 using InnerCount = mp11::mp_size<InnerHandlers>;
1146
1147 V* value_;
1148 P* parent_;
1149
1150 std::string key_;
1151
1152 handler_tuple<converting_handler, InnerHandlers> handlers_;
1153 int inner_active_ = -1;
1154 std::size_t activated_ = 0;
1155
1156 public:
1157 converting_handler( converting_handler const& ) = delete;
1158 converting_handler& operator=( converting_handler const& ) = delete;
1159
1160 converting_handler( V* v, P* p )
1161 : value_(v), parent_(p), handlers_(struct_accessor(), v, this)
1162 {}
1163
1164 struct is_required_checker
1165 {
1166 bool operator()( mp11::mp_size<Dt> ) const noexcept
1167 {
1168 return false;
1169 }
1170
1171 template< class I >
1172 auto operator()( I ) const noexcept
1173 {
1174 using T = mp11::mp_at<Dt, I>;
1175 return !is_optional_like<T>::value;
1176 }
1177 };
1178
1179 bool signal_value(system::error_code&)
1180 {
1181 BOOST_ASSERT( inner_active_ >= 0 );
1182 bool required_member = mp11::mp_with_index<InnerCount>(
1183 inner_active_,
1184 is_required_checker{});
1185 if( required_member )
1186 ++activated_;
1187
1188 key_ = {};
1189 inner_active_ = -1;
1190 return true;
1191 }
1192
1193 bool signal_end(system::error_code& ec)
1194 {
1195 key_ = {};
1196 inner_active_ = -1;
1197 return parent_->signal_value(ec);
1198 }
1199
1200 #define BOOST_JSON_INVOKE_INNER(fn) \
1201 if( inner_active_ < 0 ) \
1202 { \
1203 BOOST_JSON_FAIL( ec, error::not_object ); \
1204 return false; \
1205 } \
1206 auto f = [&](auto& handler) { return handler.fn ; }; \
1207 using F = decltype(f); \
1208 using H = decltype(handlers_); \
1209 return mp11::mp_with_index<InnerCount>( \
1210 inner_active_, \
1211 tuple_handler_op_invoker<H, F>{handlers_, f} );
1212
1213 bool on_object_begin( system::error_code& ec )
1214 {
1215 if( inner_active_ < 0 )
1216 return true;
1217
1218 BOOST_JSON_INVOKE_INNER( on_object_begin(ec) );
1219 }
1220
1221 bool on_object_end( system::error_code& ec )
1222 {
1223 if( inner_active_ < 0 )
1224 {
1225 using C = mp11::mp_count_if<Dt, is_optional_like>;
1226 constexpr int N = mp11::mp_size<Dt>::value - C::value;
1227 if( activated_ < N )
1228 {
1229 BOOST_JSON_FAIL( ec, error::size_mismatch );
1230 return false;
1231 }
1232
1233 return parent_->signal_value(ec);
1234 }
1235
1236 BOOST_JSON_INVOKE_INNER( on_object_end(ec) );
1237 }
1238
1239 bool on_array_begin( system::error_code& ec )
1240 {
1241 BOOST_JSON_INVOKE_INNER( on_array_begin(ec) );
1242 }
1243
1244 bool on_array_end( system::error_code& ec )
1245 {
1246 if( inner_active_ < 0 )
1247 return parent_->signal_end(ec);
1248
1249 BOOST_JSON_INVOKE_INNER( on_array_end(ec) );
1250 }
1251
1252 bool on_key_part( system::error_code& ec, string_view sv )
1253 {
1254 if( inner_active_ < 0 )
1255 {
1256 key_.append( sv.data(), sv.size() );
1257 return true;
1258 }
1259
1260 BOOST_JSON_INVOKE_INNER( on_key_part(ec, sv) );
1261 }
1262
1263 bool on_key( system::error_code& ec, string_view sv )
1264 {
1265 if( inner_active_ >= 0 )
1266 {
1267 BOOST_JSON_INVOKE_INNER( on_key(ec, sv) );
1268 }
1269
1270 string_view key = sv;
1271 if( !key_.empty() )
1272 {
1273 key_.append( sv.data(), sv.size() );
1274 key = key_;
1275 }
1276
1277 inner_active_ = InnerCount::value - 1;
1278 mp11::mp_for_each<Dm>( struct_key_searcher(key, inner_active_) );
1279 return true;
1280 }
1281
1282 bool on_string_part( system::error_code& ec, string_view sv )
1283 {
1284 BOOST_JSON_INVOKE_INNER( on_string_part(ec, sv) );
1285 }
1286
1287 bool on_string( system::error_code& ec, string_view sv )
1288 {
1289 BOOST_JSON_INVOKE_INNER( on_string(ec, sv) );
1290 }
1291
1292 bool on_number_part( system::error_code& ec )
1293 {
1294 BOOST_JSON_INVOKE_INNER( on_number_part(ec) );
1295 }
1296
1297 bool on_int64( system::error_code& ec, std::int64_t v )
1298 {
1299 BOOST_JSON_INVOKE_INNER( on_int64(ec, v) );
1300 }
1301
1302 bool on_uint64( system::error_code& ec, std::uint64_t v )
1303 {
1304 BOOST_JSON_INVOKE_INNER( on_uint64(ec, v) );
1305 }
1306
1307 bool on_double( system::error_code& ec, double v )
1308 {
1309 BOOST_JSON_INVOKE_INNER( on_double(ec, v) );
1310 }
1311
1312 bool on_bool( system::error_code& ec, bool v )
1313 {
1314 BOOST_JSON_INVOKE_INNER( on_bool(ec, v) );
1315 }
1316
1317 bool on_null( system::error_code& ec )
1318 {
1319 BOOST_JSON_INVOKE_INNER( on_null(ec) );
1320 }
1321
1322 #undef BOOST_JSON_INVOKE_INNER
1323
1324 #endif
1325 };
1326
1327 // variant handler
1328 struct object_begin_handler_event
1329 { };
1330
1331 struct object_end_handler_event
1332 { };
1333
1334 struct array_begin_handler_event
1335 { };
1336
1337 struct array_end_handler_event
1338 { };
1339
1340 struct key_handler_event
1341 {
1342 std::string value;
1343 };
1344
1345 struct string_handler_event
1346 {
1347 std::string value;
1348 };
1349
1350 struct int64_handler_event
1351 {
1352 std::int64_t value;
1353 };
1354
1355 struct uint64_handler_event
1356 {
1357 std::uint64_t value;
1358 };
1359
1360 struct double_handler_event
1361 {
1362 double value;
1363 };
1364
1365 struct bool_handler_event
1366 {
1367 bool value;
1368 };
1369
1370 struct null_handler_event
1371 { };
1372
1373 using parse_event = variant2::variant<
1374 object_begin_handler_event,
1375 object_end_handler_event,
1376 array_begin_handler_event,
1377 array_end_handler_event,
1378 key_handler_event,
1379 string_handler_event,
1380 int64_handler_event,
1381 uint64_handler_event,
1382 double_handler_event,
1383 bool_handler_event,
1384 null_handler_event>;
1385
1386 template< class H >
1387 struct event_visitor
1388 {
1389 H& handler;
1390 system::error_code& ec;
1391
1392 bool
1393 28 operator()(object_begin_handler_event&) const
1394 {
1395 28 return handler.on_object_begin(ec);
1396 }
1397
1398 bool
1399 14 operator()(object_end_handler_event&) const
1400 {
1401 14 return handler.on_object_end(ec);
1402 }
1403
1404 bool
1405 84 operator()(array_begin_handler_event&) const
1406 {
1407 84 return handler.on_array_begin(ec);
1408 }
1409
1410 bool
1411 42 operator()(array_end_handler_event&) const
1412 {
1413 42 return handler.on_array_end(ec);
1414 }
1415
1416 bool
1417 42 operator()(key_handler_event& ev) const
1418 {
1419 42 return handler.on_key(ec, ev.value);
1420 }
1421
1422 bool
1423 216 operator()(string_handler_event& ev) const
1424 {
1425
1/1
✓ Branch 2 taken 35 times.
216 return handler.on_string(ec, ev.value);
1426 }
1427
1428 bool
1429 308 operator()(int64_handler_event& ev) const
1430 {
1431 308 return handler.on_int64(ec, ev.value);
1432 }
1433
1434 bool
1435 28 operator()(uint64_handler_event& ev) const
1436 {
1437 28 return handler.on_uint64(ec, ev.value);
1438 }
1439
1440 bool
1441 42 operator()(double_handler_event& ev) const
1442 {
1443 42 return handler.on_double(ec, ev.value);
1444 }
1445
1446 bool
1447 14 operator()(bool_handler_event& ev) const
1448 {
1449 14 return handler.on_bool(ec, ev.value);
1450 }
1451
1452 bool
1453 14 operator()(null_handler_event&) const
1454 {
1455 14 return handler.on_null(ec);
1456 }
1457 };
1458
1459 // L<T...> -> variant< monostate, get_handler<T, P>... >
1460 template< class P, class L >
1461 using inner_handler_variant = mp11::mp_push_front<
1462 mp11::mp_transform_q<
1463 mp11::mp_bind_back<get_handler, P>,
1464 mp11::mp_apply<variant2::variant, L>>,
1465 variant2::monostate>;
1466
1467 template< class T, class P >
1468 class converting_handler<variant_conversion_tag, T, P>
1469 {
1470 private:
1471 using variant_size = mp11::mp_size<T>;
1472
1473 T* value_;
1474 P* parent_;
1475
1476 std::string string_;
1477 std::vector< parse_event > events_;
1478 inner_handler_variant<converting_handler, T> inner_;
1479 int inner_active_ = -1;
1480
1481 public:
1482 converting_handler( converting_handler const& ) = delete;
1483 converting_handler& operator=( converting_handler const& ) = delete;
1484
1485 180 converting_handler( T* v, P* p )
1486 180 : value_( v )
1487 180 , parent_( p )
1488 180 {}
1489
1490 252 bool signal_value(system::error_code& ec)
1491 {
1492 252 inner_.template emplace<0>();
1493 252 inner_active_ = -1;
1494 252 events_.clear();
1495 252 return parent_->signal_value(ec);
1496 }
1497
1498 28 bool signal_end(system::error_code& ec)
1499 {
1500 28 return parent_->signal_end(ec);
1501 }
1502
1503 struct alternative_selector
1504 {
1505 converting_handler* self;
1506
1507 template< class I >
1508 void
1509 454 operator()( I ) const
1510 {
1511 using V = mp11::mp_at<T, I>;
1512
1/1
✓ Branch 1 taken 157 times.
454 auto& v = self->value_->template emplace<I::value>( V{} );
1513
1/1
✓ Branch 1 taken 227 times.
454 self->inner_.template emplace<I::value + 1>(&v, self);
1514 454 }
1515 };
1516 void
1517 466 next_alternative()
1518 {
1519
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 227 times.
466 if( ++inner_active_ >= static_cast<int>(variant_size::value) )
1520 12 return;
1521
1522 454 mp11::mp_with_index< variant_size::value >(
1523
1/1
✓ Branch 1 taken 227 times.
454 inner_active_, alternative_selector{this} );
1524 }
1525
1526 struct event_processor
1527 {
1528 converting_handler* self;
1529 system::error_code& ec;
1530 parse_event& event;
1531
1532 template< class I >
1533 832 bool operator()( I ) const
1534 {
1535 832 auto& handler = variant2::get<I::value + 1>(self->inner_);
1536 using Handler = remove_cvref<decltype(handler)>;
1537 832 return variant2::visit(
1538
1/1
✓ Branch 1 taken 416 times.
1664 event_visitor<Handler>{handler, ec}, event );
1539 }
1540 };
1541 572 bool process_events(system::error_code& ec)
1542 {
1543 572 constexpr std::size_t N = variant_size::value;
1544
1545 // should be pointers not iterators, otherwise MSVC crashes
1546 572 auto const last = events_.data() + events_.size();
1547 572 auto first = last - 1;
1548 572 bool ok = false;
1549
1550
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 140 times.
572 if( inner_active_ < 0 )
1551 292 next_alternative();
1552 do
1553 {
1554
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 367 times.
746 if( static_cast<std::size_t>(inner_active_) >= N )
1555 {
1556 12 BOOST_JSON_FAIL( ec, error::exhausted_variants );
1557 12 return false;
1558 }
1559
1560
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 280 times.
1392 for ( ; first != last; ++first )
1561 {
1562 1664 ok = mp11::mp_with_index< N >(
1563
1/1
✓ Branch 1 taken 416 times.
832 inner_active_, event_processor{this, ec, *first} );
1564
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 329 times.
832 if( !ok )
1565 {
1566 174 first = events_.data();
1567 174 next_alternative();
1568 174 ec.clear();
1569 174 break;
1570 }
1571 }
1572 }
1573
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 280 times.
734 while( !ok );
1574
1575 560 return true;
1576 }
1577
1578 #define BOOST_JSON_INVOKE_INNER(ev, ec) \
1579 events_.emplace_back( ev ); \
1580 return process_events(ec);
1581
1582 14 bool on_object_begin( system::error_code& ec )
1583 {
1584
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( object_begin_handler_event{}, ec );
1585 }
1586
1587 14 bool on_object_end( system::error_code& ec )
1588 {
1589
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( object_end_handler_event{}, ec );
1590 }
1591
1592 42 bool on_array_begin( system::error_code& ec )
1593 {
1594
1/1
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( array_begin_handler_event{}, ec );
1595 }
1596
1597 56 bool on_array_end( system::error_code& ec )
1598 {
1599
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 21 times.
56 if( !inner_active_ )
1600 14 return signal_end(ec);
1601
1602
1/1
✓ Branch 1 taken 21 times.
42 BOOST_JSON_INVOKE_INNER( array_end_handler_event{}, ec );
1603 }
1604
1605 10 bool on_key_part( system::error_code&, string_view sv )
1606 {
1607
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
10 string_.append(sv);
1608 10 return true;
1609 }
1610
1611 28 bool on_key( system::error_code& ec, string_view sv )
1612 {
1613
2/2
✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
28 string_.append(sv);
1614
1/1
✓ Branch 2 taken 14 times.
56 BOOST_JSON_INVOKE_INNER( key_handler_event{ std::move(string_) }, ec );
1615 28 }
1616
1617 62 bool on_string_part( system::error_code&, string_view sv )
1618 {
1619
2/2
✓ Branch 1 taken 31 times.
✓ Branch 4 taken 31 times.
62 string_.append(sv);
1620 62 return true;
1621 }
1622
1623 96 bool on_string( system::error_code& ec, string_view sv )
1624 {
1625
2/2
✓ Branch 1 taken 48 times.
✓ Branch 4 taken 48 times.
96 string_.append(sv);
1626
1/1
✓ Branch 2 taken 48 times.
192 BOOST_JSON_INVOKE_INNER(
1627 string_handler_event{ std::move(string_) }, ec );
1628 96 }
1629
1630 120 bool on_number_part( system::error_code& )
1631 {
1632 120 return true;
1633 }
1634
1635 266 bool on_int64( system::error_code& ec, std::int64_t v )
1636 {
1637
1/1
✓ Branch 1 taken 133 times.
266 BOOST_JSON_INVOKE_INNER( int64_handler_event{v}, ec );
1638 }
1639
1640 14 bool on_uint64( system::error_code& ec, std::uint64_t v )
1641 {
1642
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( uint64_handler_event{v}, ec );
1643 }
1644
1645 28 bool on_double( system::error_code& ec, double v )
1646 {
1647
1/1
✓ Branch 1 taken 14 times.
28 BOOST_JSON_INVOKE_INNER( double_handler_event{v}, ec );
1648 }
1649
1650 14 bool on_bool( system::error_code& ec, bool v )
1651 {
1652
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( bool_handler_event{v}, ec );
1653 }
1654
1655 14 bool on_null( system::error_code& ec )
1656 {
1657
1/1
✓ Branch 1 taken 7 times.
14 BOOST_JSON_INVOKE_INNER( null_handler_event{}, ec );
1658 }
1659
1660 #undef BOOST_JSON_INVOKE_INNER
1661 };
1662
1663 // optional handler
1664 template<class V, class P>
1665 class converting_handler<optional_conversion_tag, V, P>
1666 {
1667 private:
1668 using inner_type = value_result_type<V>;
1669 using inner_handler_type = get_handler<inner_type, converting_handler>;
1670
1671 V* value_;
1672 P* parent_;
1673
1674 inner_type inner_value_ = {};
1675 inner_handler_type inner_;
1676 bool inner_active_ = false;
1677
1678 public:
1679 converting_handler( converting_handler const& ) = delete;
1680 converting_handler& operator=( converting_handler const& ) = delete;
1681
1682 converting_handler( V* v, P* p )
1683 : value_(v), parent_(p), inner_(&inner_value_, this)
1684 {}
1685
1686 bool signal_value(system::error_code& ec)
1687 {
1688 *value_ = std::move(inner_value_);
1689
1690 inner_active_ = false;
1691 return parent_->signal_value(ec);
1692 }
1693
1694 bool signal_end(system::error_code& ec)
1695 {
1696 return parent_->signal_end(ec);
1697 }
1698
1699 #define BOOST_JSON_INVOKE_INNER(fn) \
1700 if( !inner_active_ ) \
1701 inner_active_ = true; \
1702 return inner_.fn;
1703
1704 bool on_object_begin( system::error_code& ec )
1705 {
1706 BOOST_JSON_INVOKE_INNER( on_object_begin(ec) );
1707 }
1708
1709 bool on_object_end( system::error_code& ec )
1710 {
1711 BOOST_JSON_INVOKE_INNER( on_object_end(ec) );
1712 }
1713
1714 bool on_array_begin( system::error_code& ec )
1715 {
1716 BOOST_JSON_INVOKE_INNER( on_array_begin(ec) );
1717 }
1718
1719 bool on_array_end( system::error_code& ec )
1720 {
1721 if( !inner_active_ )
1722 return signal_end(ec);
1723
1724 BOOST_JSON_INVOKE_INNER( on_array_end(ec) );
1725 }
1726
1727 bool on_key_part( system::error_code& ec, string_view sv )
1728 {
1729 BOOST_JSON_INVOKE_INNER( on_key_part(ec, sv) );
1730 }
1731
1732 bool on_key( system::error_code& ec, string_view sv )
1733 {
1734 BOOST_JSON_INVOKE_INNER( on_key(ec, sv) );
1735 }
1736
1737 bool on_string_part( system::error_code& ec, string_view sv )
1738 {
1739 BOOST_JSON_INVOKE_INNER( on_string_part(ec, sv) );
1740 }
1741
1742 bool on_string( system::error_code& ec, string_view sv )
1743 {
1744 BOOST_JSON_INVOKE_INNER( on_string(ec, sv) );
1745 }
1746
1747 bool on_number_part( system::error_code& ec )
1748 {
1749 BOOST_JSON_INVOKE_INNER( on_number_part(ec) );
1750 }
1751
1752 bool on_int64( system::error_code& ec, std::int64_t v )
1753 {
1754 BOOST_JSON_INVOKE_INNER( on_int64(ec, v) );
1755 }
1756
1757 bool on_uint64( system::error_code& ec, std::uint64_t v )
1758 {
1759 BOOST_JSON_INVOKE_INNER( on_uint64(ec, v) );
1760 }
1761
1762 bool on_double( system::error_code& ec, double v )
1763 {
1764 BOOST_JSON_INVOKE_INNER( on_double(ec, v) );
1765 }
1766
1767 bool on_bool( system::error_code& ec, bool v )
1768 {
1769 BOOST_JSON_INVOKE_INNER( on_bool(ec, v) );
1770 }
1771
1772 bool on_null(system::error_code& ec)
1773 {
1774 if( !inner_active_ )
1775 {
1776 *value_ = {};
1777 return this->parent_->signal_value(ec);
1778 }
1779 else
1780 {
1781 return inner_.on_null(ec);
1782 }
1783 }
1784
1785 #undef BOOST_JSON_INVOKE_INNER
1786 };
1787
1788 // path handler
1789 template< class V, class P >
1790 class converting_handler<path_conversion_tag, V, P>
1791 : public scalar_handler<P, error::not_string>
1792 {
1793 private:
1794 V* value_;
1795 bool cleared_ = false;
1796
1797 public:
1798 converting_handler( V* v, P* p )
1799 : converting_handler::scalar_handler(p)
1800 , value_(v)
1801 {}
1802
1803 bool on_string_part( system::error_code&, string_view sv )
1804 {
1805 if( !cleared_ )
1806 {
1807 cleared_ = true;
1808 value_->clear();
1809 }
1810
1811 value_->concat( sv.begin(), sv.end() );
1812 return true;
1813 }
1814
1815 bool on_string(system::error_code& ec, string_view sv)
1816 {
1817 if( !cleared_ )
1818 value_->clear();
1819 else
1820 cleared_ = false;
1821
1822 value_->concat( sv.begin(), sv.end() );
1823
1824 return this->parent_->signal_value(ec);
1825 }
1826 };
1827
1828 // into_handler
1829 template< class V >
1830 class into_handler
1831 {
1832 private:
1833
1834 using inner_handler_type = get_handler<V, into_handler>;
1835
1836 inner_handler_type inner_;
1837 bool inner_active_ = true;
1838
1839 public:
1840
1841 into_handler( into_handler const& ) = delete;
1842 into_handler& operator=( into_handler const& ) = delete;
1843
1844 public:
1845
1846 static constexpr std::size_t max_object_size = object::max_size();
1847 static constexpr std::size_t max_array_size = array::max_size();
1848 static constexpr std::size_t max_key_size = string::max_size();
1849 static constexpr std::size_t max_string_size = string::max_size();
1850
1851 public:
1852
1853 1043 explicit into_handler( V* v ): inner_( v, this )
1854 {
1855 1043 }
1856
1857 931 bool signal_value(system::error_code&)
1858 {
1859 931 return true;
1860 }
1861
1862 14 bool signal_end(system::error_code&)
1863 {
1864 14 return true;
1865 }
1866
1867 1041 bool on_document_begin( system::error_code& )
1868 {
1869 1041 return true;
1870 }
1871
1872 945 bool on_document_end( system::error_code& )
1873 {
1874 945 inner_active_ = false;
1875 945 return true;
1876 }
1877
1878 #define BOOST_JSON_INVOKE_INNER(f) \
1879 if( !inner_active_ ) \
1880 { \
1881 BOOST_JSON_FAIL( ec, error::extra_data ); \
1882 return false; \
1883 } \
1884 else \
1885 return inner_.f
1886
1887 287 bool on_object_begin( system::error_code& ec )
1888 {
1889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
287 BOOST_JSON_INVOKE_INNER( on_object_begin(ec) );
1890 }
1891
1892 275 bool on_object_end( std::size_t, system::error_code& ec )
1893 {
1894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
275 BOOST_JSON_INVOKE_INNER( on_object_end(ec) );
1895 }
1896
1897 834 bool on_array_begin( system::error_code& ec )
1898 {
1899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 418 times.
834 BOOST_JSON_INVOKE_INNER( on_array_begin(ec) );
1900 }
1901
1902 806 bool on_array_end( std::size_t, system::error_code& ec )
1903 {
1904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 404 times.
806 BOOST_JSON_INVOKE_INNER( on_array_end(ec) );
1905 }
1906
1907 96 bool on_key_part( string_view sv, std::size_t, system::error_code& ec )
1908 {
1909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
96 BOOST_JSON_INVOKE_INNER( on_key_part(ec, sv) );
1910 }
1911
1912 276 bool on_key( string_view sv, std::size_t, system::error_code& ec )
1913 {
1914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
276 BOOST_JSON_INVOKE_INNER( on_key(ec, sv) );
1915 }
1916
1917 108 bool on_string_part( string_view sv, std::size_t, system::error_code& ec )
1918 {
1919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
108 BOOST_JSON_INVOKE_INNER( on_string_part(ec, sv) );
1920 }
1921
1922 202 bool on_string( string_view sv, std::size_t, system::error_code& ec )
1923 {
1924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
202 BOOST_JSON_INVOKE_INNER( on_string(ec, sv) );
1925 }
1926
1927 968 bool on_number_part( string_view, system::error_code& ec )
1928 {
1929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
968 BOOST_JSON_INVOKE_INNER( on_number_part(ec) );
1930 }
1931
1932 1408 bool on_int64( std::int64_t v, string_view, system::error_code& ec )
1933 {
1934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
1408 BOOST_JSON_INVOKE_INNER( on_int64(ec, v) );
1935 }
1936
1937 78 bool on_uint64( std::uint64_t v, string_view, system::error_code& ec )
1938 {
1939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
78 BOOST_JSON_INVOKE_INNER( on_uint64(ec, v) );
1940 }
1941
1942 126 bool on_double( double v, string_view, system::error_code& ec )
1943 {
1944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
126 BOOST_JSON_INVOKE_INNER( on_double(ec, v) );
1945 }
1946
1947 88 bool on_bool( bool v, system::error_code& ec )
1948 {
1949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
88 BOOST_JSON_INVOKE_INNER( on_bool(ec, v) );
1950 }
1951
1952 78 bool on_null( system::error_code& ec )
1953 {
1954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
78 BOOST_JSON_INVOKE_INNER( on_null(ec) );
1955 }
1956
1957 2508 bool on_comment_part(string_view, system::error_code&)
1958 {
1959 2508 return true;
1960 }
1961
1962 66 bool on_comment(string_view, system::error_code&)
1963 {
1964 66 return true;
1965 }
1966
1967 #undef BOOST_JSON_INVOKE_INNER
1968 };
1969
1970 } // namespace detail
1971 } // namespace boost
1972 } // namespace json
1973
1974 #endif
1975