GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: detail/parse_into.hpp
Date: 2025-12-23 17:20:53
Exec Total Coverage
Lines: 426 426 100.0%
Functions: 1953 4539 43.0%
Branches: 170 217 78.3%

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