DAW JSON Link
daw_json_parse_value.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
11#include "version.h"
12
13#include "daw_json_assert.h"
17#include "daw_json_parse_name.h"
18#include "daw_json_parse_real.h"
24#include "daw_json_traits.h"
25
26#include <daw/daw_algorithm.h>
27#include <daw/daw_attributes.h>
28#include <daw/daw_traits.h>
29#include <daw/daw_utility.h>
30
31#include <ciso646>
32#include <cstddef>
33#include <cstdint>
34#include <iterator>
35#include <tuple>
36
37#if defined( __cpp_constexpr_dynamic_alloc )
38#define CPP20CONSTEXPR constexpr
39#else
40#define CPP20CONSTEXPR
41#endif
42
43namespace daw::json {
44 inline namespace DAW_JSON_VER {
45 namespace json_details {
46 /***
47 * Depending on the type of literal, it may always be quoted, sometimes,
48 * or never. This method handles the always and sometimes cases.
49 * In checked input, ensures State has more data.
50 * @tparam literal_as_string Is the literal being parsed enclosed in
51 * quotes.
52 * @tparam ParseState ParseState idiom
53 * @param parse_state Current parsing state
54 */
55 template<LiteralAsStringOpt literal_as_string, typename ParseState>
56 DAW_ATTRIB_INLINE inline constexpr void
58 if constexpr( literal_as_string == LiteralAsStringOpt::Always ) {
59 daw_json_assert_weak( parse_state.is_quotes_checked( ),
60 ErrorReason::InvalidNumberUnexpectedQuoting,
62 parse_state.remove_prefix( );
63 } else if constexpr( literal_as_string == LiteralAsStringOpt::Maybe ) {
65 ErrorReason::UnexpectedEndOfData, parse_state );
66 if( parse_state.front( ) == '"' ) {
67 parse_state.remove_prefix( );
68 }
69 }
70 }
71
72 template<typename JsonMember, bool KnownBounds, typename ParseState>
73 [[nodiscard,
74 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
76 using constructor_t = typename JsonMember::constructor_t;
77 using element_t = typename JsonMember::base_type;
78
79 if constexpr( JsonMember::literal_as_string !=
81 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
83 if constexpr( JsonMember::allow_number_errors ==
85 JsonMember::allow_number_errors ==
87 element_t sign = element_t( 1.0 );
88 if( parse_state.front( ) == '-' ) {
89 sign = element_t( -1.0 );
90 parse_state.first++;
91 }
92 // Looking for Inf as that will match Infinity too.
93 if( parse_state.size( ) >= 4 and
94 parse_state.starts_with( "Inf" ) ) {
95
96 parse_state.first += 3;
97 if( parse_state.front( ) == '"' ) {
98 parse_state.first++;
99 } else if( parse_state.size( ) >= 6 and
100 parse_state.starts_with( R"(inity")" ) ) {
101 parse_state.first += 6;
102 } else {
103 daw_json_error( ErrorReason::InvalidString, parse_state );
104 }
106 not parse_state.has_more( ) or
108 ErrorReason::InvalidEndOfValue, parse_state );
109 return daw::cxmath::copy_sign(
110 daw::numeric_limits<element_t>::infinity( ), sign );
111 } else if( sign < element_t( 0 ) ) {
112 parse_state.first--;
113 }
114 }
115 if constexpr( JsonMember::allow_number_errors ==
117 JsonMember::allow_number_errors ==
119 if( parse_state.starts_with( "NaN" ) ) {
120 parse_state.template move_to_next_of<'"'>( );
121 parse_state.remove_prefix( );
123 not parse_state.has_more( ) or
125 ErrorReason::InvalidEndOfValue, parse_state );
126 return daw::numeric_limits<element_t>::quiet_NaN( );
127 }
128 }
129 }
130 if constexpr( KnownBounds ) {
131 return construct_value(
132 template_args<json_result<JsonMember>, constructor_t>, parse_state,
133 parse_real<element_t, true>( parse_state ) );
134 } else {
136 parse_state.has_more( ) and
138 ErrorReason::InvalidNumberStart, parse_state );
139
140 auto result = construct_value(
141 template_args<json_result<JsonMember>, constructor_t>, parse_state,
142 parse_real<element_t, false>( parse_state ) );
143 if constexpr( JsonMember::literal_as_string !=
145 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
146 parse_state );
147 }
148
150 not parse_state.has_more( ) or
152 ErrorReason::InvalidEndOfValue, parse_state );
153 return result;
154 }
155 }
156
157 template<typename JsonMember, bool KnownBounds, typename ParseState>
158 [[nodiscard,
159 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
161 using constructor_t = typename JsonMember::constructor_t;
162 using element_t = typename JsonMember::base_type;
163 using int_type =
164 typename std::conditional_t<std::is_enum_v<element_t>,
165 std::underlying_type<element_t>,
166 daw::traits::identity<element_t>>::type;
167
168 static_assert( daw::is_signed<int_type>::value,
169 "Expected signed type" );
170 if constexpr( KnownBounds ) {
173 ErrorReason::InvalidNumberStart, parse_state );
174 } else {
175 if constexpr( JsonMember::literal_as_string !=
177 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
178 parse_state );
179 } else if constexpr( not ParseState::is_zero_terminated_string ) {
181 ErrorReason::UnexpectedEndOfData,
182 parse_state );
183 }
184 }
185 auto const sign = static_cast<int_type>(
187 using uint_type =
188 typename std::conditional_t<daw::is_system_integral_v<int_type>,
189 daw::make_unsigned<int_type>,
190 daw::traits::identity<int_type>>::type;
191 auto parsed_val = to_signed(
192 unsigned_parser<uint_type, JsonMember::range_check, KnownBounds>(
193 ParseState::exec_tag, parse_state ),
194 sign );
195
196 if constexpr( KnownBounds ) {
197 return construct_value(
198 template_args<json_result<JsonMember>, constructor_t>, parse_state,
199 static_cast<element_t>( parsed_val ) );
200 } else {
201 auto result = construct_value(
202 template_args<json_result<JsonMember>, constructor_t>, parse_state,
203 static_cast<element_t>( parsed_val ) );
204 if constexpr( JsonMember::literal_as_string !=
206 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
207 parse_state );
208 }
209 parse_state.trim_left( );
211 not parse_state.has_more( ) or
213 ErrorReason::InvalidEndOfValue, parse_state );
214 return result;
215 }
216 }
217
218 template<typename JsonMember, bool KnownBounds, typename ParseState>
219 [[nodiscard,
220 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
223 using constructor_t = typename JsonMember::constructor_t;
224 using element_t = typename JsonMember::base_type;
225 using uint_type =
226 typename std::conditional_t<std::is_enum_v<element_t>,
227 std::underlying_type<element_t>,
228 daw::traits::identity<element_t>>::type;
229
230 if constexpr( KnownBounds ) {
231 if constexpr( JsonMember::literal_as_string !=
233 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
234 parse_state );
235 }
237
238 return construct_value(
239 template_args<json_result<JsonMember>, constructor_t>, parse_state,
240 unsigned_parser<uint_type, JsonMember::range_check, KnownBounds>(
241 ParseState::exec_tag, parse_state ) );
242 } else {
243 if constexpr( JsonMember::literal_as_string !=
245 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
246 parse_state );
247 if constexpr( not ParseState::is_zero_terminated_string ) {
249 ErrorReason::UnexpectedEndOfData,
250 parse_state );
251 }
252 } else if constexpr( not ParseState::is_zero_terminated_string ) {
254 ErrorReason::UnexpectedEndOfData,
255 parse_state );
256 }
259 ErrorReason::InvalidNumber, parse_state );
260 auto result = construct_value(
261 template_args<json_result<JsonMember>, constructor_t>, parse_state,
262 unsigned_parser<uint_type, JsonMember::range_check, KnownBounds>(
263 ParseState::exec_tag, parse_state ) );
264 if constexpr( JsonMember::literal_as_string !=
266 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
267 parse_state );
268 if constexpr( not ParseState::is_zero_terminated_string ) {
270 ErrorReason::UnexpectedEndOfData,
271 parse_state );
272 }
273 }
275 not parse_state.has_more( ) or
277 ErrorReason::InvalidEndOfValue, parse_state );
278 return result;
279 }
280 }
281
282 template<typename JsonMember, bool KnownBounds, typename ParseState>
283 [[nodiscard,
284 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
286
287 using constructor_t = typename JsonMember::constructor_t;
288 if constexpr( KnownBounds ) {
289 // skip_value will leave a null parse_state
290 if( parse_state.is_null( ) ) {
291 if constexpr( JsonMember::nullable == JsonNullable::Nullable ) {
292 return construct_value(
293 template_args<json_result<JsonMember>, constructor_t>,
294 parse_state );
295 } else {
296 daw_json_error( missing_member(
297 std::string_view( std::data( JsonMember::name ),
298 std::size( JsonMember::name ) ) ) );
299 }
300 }
301 return parse_value<JsonMember, true>(
303 } else if constexpr( ParseState::is_unchecked_input ) {
304 if( not parse_state.has_more( ) ) {
305 if constexpr( JsonMember::nullable == JsonNullable::Nullable ) {
306 return construct_value(
307 template_args<json_result<JsonMember>, constructor_t>,
308 parse_state );
309 } else {
310 daw_json_error( missing_member(
311 std::string_view( std::data( JsonMember::name ),
312 std::size( JsonMember::name ) ) ) );
313 }
314 } else if( parse_state.front( ) == 'n' ) {
315 parse_state.remove_prefix( 4 );
316 parse_state.trim_left_unchecked( );
317 parse_state.remove_prefix( );
318 return construct_value(
319 template_args<json_result<JsonMember>, constructor_t>,
320 parse_state );
321 }
322 return parse_value<JsonMember>(
324 } else {
325 if( parse_state.starts_with( "null" ) ) {
326 parse_state.remove_prefix( 4 );
328 not parse_state.has_more( ) or
330 ErrorReason::InvalidLiteral, parse_state );
331 parse_state.trim_left_checked( );
332 return construct_value(
333 template_args<json_result<JsonMember>, constructor_t>,
334 parse_state );
335 }
336 return parse_value<JsonMember>(
338 }
339 }
340
341 template<typename JsonMember, bool KnownBounds, typename ParseState>
342 [[nodiscard,
343 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
345 using constructor_t = typename JsonMember::constructor_t;
346
347 if constexpr( KnownBounds ) {
348 // We have already checked if it is a true/false
349 if constexpr( ParseState::is_unchecked_input ) {
350 return static_cast<bool>( parse_state.counter );
351 } else {
352 switch( parse_state.front( ) ) {
353 case 't':
354 return construct_value(
355 template_args<json_result<JsonMember>, constructor_t>,
356 parse_state, true );
357 case 'f':
358 return construct_value(
359 template_args<json_result<JsonMember>, constructor_t>,
360 parse_state, false );
361 }
362 daw_json_error( ErrorReason::InvalidLiteral, parse_state );
363 }
364 } else {
365 // Beginning quotes
366 if constexpr( JsonMember::literal_as_string !=
368 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
369 parse_state );
370 }
371 bool result = false;
372 if constexpr( ParseState::is_unchecked_input ) {
373 if( parse_state.front( ) == 't' ) /* true */ {
374 result = true;
375 parse_state.remove_prefix( 4 );
376 } else /* false */ {
377 parse_state.remove_prefix( 5 );
378 }
379 } else {
380 if( parse_state.starts_with( "true" ) ) {
381 parse_state.remove_prefix( 4 );
382 result = true;
383 } else if( parse_state.starts_with( "false" ) ) {
384 parse_state.remove_prefix( 5 );
385 } else {
386 daw_json_error( ErrorReason::InvalidLiteral, parse_state );
387 }
388 }
389 // Trailing quotes
390 if constexpr( JsonMember::literal_as_string !=
392 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
393 parse_state );
394 }
395 parse_state.trim_left( );
397 not parse_state.has_more( ) or
399 ErrorReason::InvalidEndOfValue, parse_state );
400 return construct_value(
401 template_args<json_result<JsonMember>, constructor_t>, parse_state,
402 result );
403 }
404 }
405
406 template<typename JsonMember, bool KnownBounds, typename ParseState>
407 [[nodiscard,
408 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
411
412 using constructor_t = typename JsonMember::constructor_t;
413 if constexpr( KnownBounds ) {
414 if constexpr( JsonMember::empty_is_null == EmptyStringNull::yes ) {
415 if( parse_state.empty( ) ) {
416 return construct_value(
417 template_args<json_result<JsonMember>, constructor_t>,
418 parse_state );
419 }
420 }
421 return construct_value(
422 template_args<json_result<JsonMember>, constructor_t>, parse_state,
423 std::data( parse_state ), std::size( parse_state ) );
424 } else {
425 if constexpr( JsonMember::allow_escape_character ==
427 auto const str = skip_string( parse_state );
428 if constexpr( JsonMember::empty_is_null == EmptyStringNull::yes ) {
429 if( str.empty( ) ) {
430 return construct_value(
431 template_args<json_result<JsonMember>, constructor_t>,
432 parse_state );
433 }
434 }
435 return construct_value(
436 template_args<json_result<JsonMember>, constructor_t>,
437 parse_state, std::data( str ), std::size( str ) );
438 } else {
439 parse_state.remove_prefix( );
440
441 char const *const first = parse_state.first;
442 parse_state.template move_to_next_of<'"'>( );
443 char const *const last = parse_state.first;
444 parse_state.remove_prefix( );
445 if constexpr( JsonMember::empty_is_null == EmptyStringNull::yes ) {
446 if( first == last ) {
447 return construct_value(
448 template_args<json_result<JsonMember>, constructor_t>,
449 parse_state );
450 }
451 return construct_value(
452 template_args<json_result<JsonMember>, constructor_t>,
453 parse_state, first, static_cast<std::size_t>( last - first ) );
454 } else {
455 return construct_value(
456 template_args<json_result<JsonMember>, constructor_t>,
457 parse_state, first, static_cast<std::size_t>( last - first ) );
458 }
459 }
460 }
461 }
462
463 /***
464 * We know that we are constructing a std::string or
465 * std::optional<std::string> We can take advantage of this and reduce
466 * the allocator time by presizing the string up front and then using a
467 * pointer to the data( ).
468 */
469 template<typename JsonMember>
471 : std::disjunction<
472 can_single_allocation_string<json_result<JsonMember>>,
473 can_single_allocation_string<json_base_type<JsonMember>>> {};
474
475 template<typename T>
476 using json_member_constructor_t = typename T::constructor_t;
477
478 template<typename T>
479 using json_member_parse_to_t = typename T::parse_to_t;
480
481 template<typename T>
482 inline constexpr bool has_json_member_constructor_v =
483 daw::is_detected<json_member_constructor_t, T>::value;
484
485 template<typename T>
486 inline constexpr bool has_json_member_parse_to_v =
487 daw::is_detected<json_member_constructor_t, T>::value;
488
489 template<typename JsonMember, bool KnownBounds, typename ParseState>
490 [[nodiscard, maybe_unused]] constexpr json_result<JsonMember>
493 static_assert( has_json_member_constructor_v<JsonMember> );
494 static_assert( has_json_member_parse_to_v<JsonMember> );
495
496 using constructor_t = typename JsonMember::constructor_t;
498 using AllowHighEightbits =
499 std::bool_constant<JsonMember::eight_bit_mode !=
501 auto parse_state2 =
502 KnownBounds ? parse_state : skip_string( parse_state );
503 // FIXME this needs std::string, fix
504 if( not AllowHighEightbits::value or
505 needs_slow_path( parse_state2 ) ) {
506 // There are escapes in the string
507 return parse_string_known_stdstring<AllowHighEightbits::value,
508 JsonMember, true>(
509 parse_state2 );
510 }
511 // There are no escapes in the string, we can just use the ptr/size
512 // ctor
513 return construct_value(
514 template_args<json_result<JsonMember>, constructor_t>, parse_state,
515 std::data( parse_state2 ), daw::data_end( parse_state2 ) );
516 } else {
517 auto parse_state2 =
518 KnownBounds ? parse_state : skip_string( parse_state );
519 using AllowHighEightbits =
520 std::bool_constant<JsonMember::eight_bit_mode !=
522 if( not AllowHighEightbits::value or
523 needs_slow_path( parse_state2 ) ) {
524 // There are escapes in the string
525 return parse_string_known_stdstring<AllowHighEightbits::value,
526 JsonMember, true>(
527 parse_state2 );
528 }
529 // There are no escapes in the string, we can just use the ptr/size
530 // ctor
531 return construct_value(
532 template_args<json_result<JsonMember>, constructor_t>, parse_state,
533 std::data( parse_state2 ), daw::data_end( parse_state2 ) );
534 }
535 }
536
537 template<typename JsonMember, bool KnownBounds, typename ParseState>
538 [[nodiscard,
539 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
541
543 ErrorReason::UnexpectedEndOfData, parse_state );
544 auto str = KnownBounds ? parse_state : skip_string( parse_state );
545 using constructor_t = typename JsonMember::constructor_t;
546 return construct_value(
547 template_args<json_result<JsonMember>, constructor_t>, parse_state,
548 std::data( str ), std::size( str ) );
549 }
550
551 template<typename JsonMember, bool KnownBounds, typename ParseState>
552 [[nodiscard, maybe_unused]] constexpr json_result<JsonMember>
554
555 auto const str = [&] {
556 if constexpr( JsonMember::custom_json_type ==
558 if constexpr( KnownBounds ) {
559 return parse_state;
560 } else {
561 return skip_string( parse_state );
562 }
563 } else if constexpr( JsonMember::custom_json_type ==
565 return KnownBounds ? parse_state : skip_literal( parse_state );
566 } else {
567 static_assert( JsonMember::custom_json_type ==
569 // If we are a root object, parse_state will have the quotes and
570 // KnownBounds cannot be true This tells us that there is an array
571 // start '[' or a member name previous to current position
572 if constexpr( KnownBounds ) {
573 auto result = parse_state;
574 if( *( result.first - 1 ) == '"' ) {
575 result.first--;
576 }
577 return result;
578 } else {
579 if( parse_state.front( ) == '"' ) {
580 auto result = skip_string( parse_state );
581 result.first--;
582 return result;
583 }
584 return skip_value( parse_state );
585 }
586 }
587 }( );
589 str.has_more( ) and not( str.front( ) == '[' or str.front( ) == '{' ),
590 ErrorReason::InvalidStartOfValue, str );
591 using constructor_t = typename JsonMember::from_converter_t;
592 return construct_value(
593 template_args<json_result<JsonMember>, constructor_t>, parse_state,
594 std::string_view( std::data( str ), std::size( str ) ) );
595 }
596
597 inline namespace {
598 template<typename ParseState>
599 struct trim_left_cleanup {
600 ParseState &parse_state;
601
602 CPP20CONSTEXPR ~trim_left_cleanup( ) noexcept( false ) {
603#if defined( DAW_HAS_CONSTEXPR_SCOPE_GUARD )
604 if( DAW_IS_CONSTANT_EVALUATED( ) ) {
605 parse_state.trim_left_checked( );
606 } else {
607#endif
608 if( std::uncaught_exceptions( ) == 0 ) {
609 parse_state.trim_left_checked( );
610 }
611#if defined( DAW_HAS_CONSTEXPR_SCOPE_GUARD )
612 }
613#endif
614 }
615 };
616 } // namespace
617
618 template<typename JsonMember, bool KnownBounds, typename ParseState>
619 [[nodiscard,
620 maybe_unused]] DAW_ATTRIB_FLATTEN constexpr json_result<JsonMember>
622
623 using element_t = typename JsonMember::base_type;
625 ErrorReason::UnexpectedEndOfData, parse_state );
626
627 if constexpr( use_direct_construction_v<ParseState, JsonMember> ) {
628 // This relies on non-trivial dtor's being allowed. So C++20
629 // constexpr or not in a constant expression. It does allow for
630 // construction of classes without move/copy special members
631 if constexpr( KnownBounds ) {
633 parse_state, template_arg<JsonMember> );
634 } else {
635 auto const run_after_parse =
636 trim_left_cleanup<ParseState>{ parse_state };
637 (void)run_after_parse;
639 parse_state, template_arg<JsonMember> );
640 }
641 } else {
642 if constexpr( KnownBounds ) {
644 parse_state, template_arg<JsonMember> );
645 } else {
646 if constexpr( force_aggregate_construction_v<element_t> ) {
647 auto const run_after_parse =
648 trim_left_cleanup<ParseState>{ parse_state };
649 (void)run_after_parse;
651 parse_state, template_arg<JsonMember> );
652 } else {
653 auto result =
655 parse_state, template_arg<JsonMember> );
656 // TODO: make trim_left
657 parse_state.trim_left_checked( );
658 return result;
659 }
660 }
661 }
662 }
663
672 template<typename JsonMember, bool KnownBounds, typename ParseState>
673 [[nodiscard,
674 maybe_unused]] DAW_ATTRIB_FLATTEN constexpr json_result<JsonMember>
677
678 static_assert( JsonMember::expected_type == JsonParseTypes::KeyValue,
679 "Expected a json_key_value" );
680 daw_json_assert_weak( parse_state.is_opening_brace_checked( ),
681 ErrorReason::ExpectedKeyValueToStartWithBrace,
682 parse_state );
683
684 parse_state.remove_prefix( );
685 parse_state.trim_left( );
686
687#if defined( __GNUC__ ) or defined( __clang__ )
688 using iter_t =
690#else
691 using iter_t =
693#endif
694 using constructor_t = typename JsonMember::constructor_t;
695 return construct_value(
696 template_args<json_result<JsonMember>, constructor_t>, parse_state,
697 iter_t( parse_state ), iter_t( ) );
698 }
699
708 template<typename JsonMember, bool KnownBounds, typename ParseState>
709 [[nodiscard,
710 maybe_unused]] DAW_ATTRIB_FLATTEN constexpr json_result<JsonMember>
713
714 static_assert( JsonMember::expected_type ==
716 "Expected a json_key_value" );
718 parse_state.is_opening_bracket_checked( ),
719 ErrorReason::ExpectedKeyValueArrayToStartWithBracket, parse_state );
720
721 parse_state.remove_prefix( );
722
723 using iter_t =
725 using constructor_t = typename JsonMember::constructor_t;
726 return construct_value(
727 template_args<json_result<JsonMember>, constructor_t>, parse_state,
728 iter_t( parse_state ), iter_t( ) );
729 }
730
731 template<typename JsonMember, bool KnownBounds, typename ParseState>
732 [[nodiscard,
733 maybe_unused]] DAW_ATTRIB_FLATTEN constexpr json_result<JsonMember>
735 parse_state.trim_left( );
736 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
737 ErrorReason::InvalidArrayStart, parse_state );
738 parse_state.remove_prefix( );
739 parse_state.trim_left_unchecked( );
740 // TODO: add parse option to disable random access iterators. This is
741 // coding to the implementations
742
743 using iterator_t =
745 using constructor_t = typename JsonMember::constructor_t;
746 return construct_value(
747 template_args<json_result<JsonMember>, constructor_t>, parse_state,
748 iterator_t( parse_state ), iterator_t( ) );
749 }
750
751 template<typename JsonMember, bool KnownBounds, typename ParseState>
752 [[nodiscard,
753 maybe_unused]] DAW_ATTRIB_FLATTEN constexpr json_result<JsonMember>
756
757 using size_member = dependent_member_t<JsonMember>;
758
759 auto [is_found, parse_state2] = find_range<ParseState>(
760 ParseState( parse_state.class_first, parse_state.last ),
761 size_member::name );
762
763 daw_json_assert( is_found, ErrorReason::TagMemberNotFound,
764 parse_state );
765 auto const sz = parse_value<size_member>(
766 parse_state2, ParseTag<size_member::expected_type>{ } );
767
768 if constexpr( KnownBounds and ParseState::is_unchecked_input ) {
769 // We have the requested size and the actual size. Let's see if they
770 // match
771 auto cnt = static_cast<std::ptrdiff_t>( parse_state.counter );
772 daw_json_assert( sz >= 0 and ( cnt < 0 or parse_state.counter == sz ),
773 ErrorReason::NumberOutOfRange, parse_state );
774 }
775 parse_state.trim_left( );
776 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
777 ErrorReason::InvalidArrayStart, parse_state );
778 parse_state.remove_prefix( );
779 parse_state.trim_left_unchecked( );
780 // TODO: add parse option to disable random access iterators. This is
781 // coding to the implementations
782 using iterator_t =
784 using constructor_t = typename JsonMember::constructor_t;
785 return construct_value(
786 template_args<json_result<JsonMember>, constructor_t>, parse_state,
787 iterator_t( parse_state ), iterator_t( ),
788 static_cast<std::size_t>( sz ) );
789 }
790
791 template<JsonBaseParseTypes BPT, typename JsonMembers,
792 typename ParseState>
793 [[nodiscard,
794 maybe_unused]] DAW_ATTRIB_FLATTEN constexpr json_result<JsonMembers>
796 using element_t = typename JsonMembers::json_elements;
797 using idx = daw::constant<(
798 JsonMembers::base_map::base_map[static_cast<int_fast8_t>( BPT )] )>;
799
800 if constexpr( idx::value <
801 pack_size_v<typename element_t::element_map_t> ) {
802 using JsonMember =
803 pack_element_t<idx::value, typename element_t::element_map_t>;
804 return parse_value<JsonMember>(
806 } else {
807 if constexpr( ParseState::is_unchecked_input ) {
808 DAW_UNREACHABLE( );
809 } else {
810 daw_json_error( ErrorReason::UnexpectedJSONVariantType );
811 }
812 }
813 }
814
815 template<typename JsonMember, bool /*KnownBounds*/, typename ParseState>
816 [[nodiscard,
817 maybe_unused]] DAW_ATTRIB_INLINE constexpr json_result<JsonMember>
820 switch( parse_state.front( ) ) {
821 case '{':
822 return parse_variant_value<JsonBaseParseTypes::Class, JsonMember>(
823 parse_state );
824 case '[':
825 return parse_variant_value<JsonBaseParseTypes::Array, JsonMember>(
826 parse_state );
827 case 't':
828 case 'f':
829 return parse_variant_value<JsonBaseParseTypes::Bool, JsonMember>(
830 parse_state );
831 case '"':
832 return parse_variant_value<JsonBaseParseTypes::String, JsonMember>(
833 parse_state );
834 case '0':
835 case '1':
836 case '2':
837 case '3':
838 case '4':
839 case '5':
840 case '6':
841 case '7':
842 case '8':
843 case '9':
844 case '+':
845 case '-':
846 return parse_variant_value<JsonBaseParseTypes::Number, JsonMember>(
847 parse_state );
848 }
849 if constexpr( ParseState::is_unchecked_input ) {
850 DAW_UNREACHABLE( );
851 } else {
852 daw_json_error( ErrorReason::InvalidStartOfValue, parse_state );
853 }
854 }
855
856 template<typename Result, typename TypeList, std::size_t pos = 0,
857 typename ParseState>
858 DAW_ATTRIB_INLINE constexpr Result
859 parse_visit( std::size_t idx, ParseState &parse_state ) {
860 if( idx == pos ) {
861 using JsonMember = pack_element_t<pos, TypeList>;
862 if constexpr( std::is_same_v<json_result<JsonMember>, Result> ) {
863 return parse_value<JsonMember>(
865 } else {
866 return { parse_value<JsonMember>(
868 }
869 }
870 if constexpr( pos + 1 < pack_size_v<TypeList> ) {
871 return parse_visit<Result, TypeList, pos + 1>( idx, parse_state );
872 } else {
873 if constexpr( ParseState::is_unchecked_input ) {
874 DAW_UNREACHABLE( );
875 } else {
876 daw_json_error( ErrorReason::MissingMemberNameOrEndOfClass,
877 parse_state );
878 }
879 }
880 }
881
882 template<typename JsonMember, typename ParseState>
883 constexpr auto find_index( ParseState parse_state ) {
884 using tag_member = typename JsonMember::tag_member;
885 using class_wrapper_t = typename JsonMember::tag_member_class_wrapper;
886
887 using switcher_t = typename JsonMember::switcher;
888 auto parse_state2 =
889 ParseState( parse_state.class_first, parse_state.class_last,
890 parse_state.class_first, parse_state.class_last );
891 if constexpr( is_an_ordered_member_v<tag_member> ) {
892 // This is an ordered class, class must start with '['
893 daw_json_assert_weak( parse_state2.is_opening_bracket_checked( ),
894 ErrorReason::InvalidArrayStart, parse_state );
895 return switcher_t{ }( std::get<0>( parse_value<class_wrapper_t>(
896 parse_state2, ParseTag<class_wrapper_t::expected_type>{ } ) ) );
897 } else {
898 // This is a regular class, class must start with '{'
899 daw_json_assert_weak( parse_state2.is_opening_brace_checked( ),
900 ErrorReason::InvalidClassStart, parse_state );
901 return switcher_t{ }( std::get<0>(
902 parse_value<class_wrapper_t>(
904 .members ) );
905 }
906 }
907
908 template<typename JsonMember, bool /*KnownBounds*/, typename ParseState>
909 [[nodiscard,
910 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
913 auto const index = find_index<JsonMember>( parse_state );
914 return parse_visit<json_result<JsonMember>,
915 typename JsonMember::json_elements::element_map_t>(
916 index, parse_state );
917 }
918
919 template<typename JsonMember, bool /*KnownBounds*/, typename ParseState>
920 [[nodiscard,
921 maybe_unused]] DAW_ATTRIB_INLINE inline constexpr json_result<JsonMember>
924 auto const index = [&] {
925 using tag_submember = typename JsonMember::tag_submember;
926 using class_wrapper_t =
927 typename JsonMember::tag_submember_class_wrapper;
928 auto parse_state2 = parse_state;
929 using switcher_t = typename JsonMember::switcher;
930 if constexpr( is_an_ordered_member_v<tag_submember> ) {
931 return switcher_t{ }( std::get<0>( parse_value<class_wrapper_t>(
932 parse_state2, ParseTag<class_wrapper_t::expected_type>{ } ) ) );
933 } else {
934 return switcher_t{ }( std::get<0>(
935 parse_value<class_wrapper_t>(
937 .members ) );
938 }
939 }( );
940
941 return parse_visit<json_result<JsonMember>,
942 typename JsonMember::json_elements::element_map_t>(
943 index, parse_state );
944 }
945
946 template<typename JsonMember, bool KnownBounds, std::size_t N,
947 typename ParseState, bool B>
948 [[nodiscard]] constexpr json_result<JsonMember>
951 using tag_member = dependent_member_t<JsonMember>;
952 auto [is_found, parse_state2] = find_range<ParseState>(
953 ParseState( parse_state.class_first, parse_state.last ),
954 tag_member::name );
955
956 daw_json_assert( is_found, ErrorReason::TagMemberNotFound,
957 parse_state );
958 auto index = typename JsonMember::switcher{ }( parse_value<tag_member>(
959 parse_state2, ParseTag<tag_member::expected_type>{ } ) );
960
961 return parse_visit<json_result<JsonMember>,
962 typename JsonMember::json_elements::element_map_t>(
963 index, parse_state );
964 }
965
966 template<bool AllMembersMustExist, typename ParseState,
967 typename OldClassPos>
969 ParseState &parse_state;
970 OldClassPos const &old_class_pos;
971
972 DAW_ATTRIB_INLINE
973 CPP20CONSTEXPR inline ~ordered_class_cleanup( ) noexcept( false ) {
974#if defined( DAW_HAS_CONSTEXPR_SCOPE_GUARD )
975 if( DAW_IS_CONSTANT_EVALUATED( ) ) {
976 if constexpr( AllMembersMustExist ) {
977 parse_state.trim_left( );
978 daw_json_assert_weak( parse_state.front( ) == ']',
979 ErrorReason::UnknownMember, parse_state );
980 parse_state.remove_prefix( );
981 parse_state.trim_left_checked( );
982 } else {
983 (void)parse_state.skip_array( );
984 }
985 parse_state.set_class_position( old_class_pos );
986 } else {
987#endif
988 if( std::uncaught_exceptions( ) == 0 ) {
989 if constexpr( AllMembersMustExist ) {
990 parse_state.trim_left( );
991 daw_json_assert_weak( parse_state.front( ) == ']',
992 ErrorReason::UnknownMember, parse_state );
993 parse_state.remove_prefix( );
994 parse_state.trim_left_checked( );
995 } else {
996 (void)parse_state.skip_array( );
997 }
998 parse_state.set_class_position( old_class_pos );
999 }
1000#if defined( DAW_HAS_CONSTEXPR_SCOPE_GUARD )
1001 }
1002#endif
1003 }
1004 };
1005
1006 namespace pocm_details {
1007 /***
1008 * Maybe skip json members
1009 * @tparam ParseState see IteratorRange
1010 * @param parse_state JSON data
1011 * @param current_position current member index
1012 * @param desired_position desired member index
1013 */
1014 template<bool Nullable, typename ParseState>
1015 DAW_ATTRIB_INLINE inline constexpr void
1017 std::size_t &current_position,
1018 std::size_t desired_position ) {
1019
1020 daw_json_assert_weak( current_position <= desired_position,
1021 ErrorReason::OutOfOrderOrderedMembers,
1022 parse_state );
1023 using skip_check_end =
1024 std::bool_constant<( ParseState::is_unchecked_input and Nullable )>;
1025 while( ( current_position < desired_position ) &
1026 ( skip_check_end::value or parse_state.front( ) != ']' ) ) {
1027 (void)skip_value( parse_state );
1028 parse_state.move_next_member_or_end( );
1029 ++current_position;
1030 daw_json_assert_weak( parse_state.has_more( ),
1031 ErrorReason::UnexpectedEndOfData,
1032 parse_state );
1033 }
1034 }
1035
1036#if defined( _MSC_VER ) and not defined( __clang__ )
1037 template<typename ParseState>
1038 struct position_info {
1039 std::size_t index;
1040 ParseState state{ };
1041
1042 constexpr explicit operator bool( ) const {
1043 return not state.is_null( );
1044 }
1045 };
1046
1047 /***
1048 * Maybe skip json members
1049 * @tparam ParseState see IteratorRange
1050 * @param parse_state JSON data
1051 * @param current_position current member index
1052 * @param desired_position desired member index
1053 */
1054 template<bool Nullable, typename ParseState, std::size_t N>
1055 DAW_ATTRIB_INLINE inline constexpr ParseState maybe_skip_members(
1056 ParseState &parse_state, std::size_t &current_position,
1057 std::size_t desired_position,
1058 std::array<position_info<ParseState>, N> &parse_locations ) {
1059
1060 auto const desired = daw::algorithm::find_if(
1061 std::data( parse_locations ), daw::data_end( parse_locations ),
1062 [desired_position]( position_info<ParseState> const &loc ) {
1063 return loc.index == desired_position;
1064 } );
1065 if( *desired ) {
1066 return desired->state;
1067 }
1068#if not defined( NDEBUG )
1069 daw_json_assert( desired != daw::data_end( parse_locations ),
1070 ErrorReason::UnexpectedEndOfData, parse_state );
1071#endif
1072 using skip_check_end =
1073 std::bool_constant<( ParseState::is_unchecked_input and Nullable )>;
1074 while( ( current_position < desired_position ) &
1075 ( skip_check_end::value or parse_state.front( ) != ']' ) ) {
1076 auto const current = daw::algorithm::find_if(
1077 std::data( parse_locations ), daw::data_end( parse_locations ),
1078 [current_position]( position_info<ParseState> const &loc ) {
1079 return loc.index == current_position;
1080 } );
1081 auto state = skip_value( parse_state );
1082 if( current != daw::data_end( parse_locations ) ) {
1083 current->state = state;
1084 }
1085 parse_state.move_next_member_or_end( );
1086 ++current_position;
1087 daw_json_assert_weak( parse_state.has_more( ),
1088 ErrorReason::UnexpectedEndOfData,
1089 parse_state );
1090 }
1091 return parse_state;
1092 }
1093#endif
1094 } // namespace pocm_details
1095
1096 template<typename JsonMember, bool KnownBounds, typename ParseState,
1097 std::size_t... Is>
1098 DAW_ATTRIB_INLINE constexpr json_result<JsonMember>
1099 parse_tuple_value( ParseState &parse_state, std::index_sequence<Is...> ) {
1100 parse_state.trim_left( );
1101 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
1102 ErrorReason::InvalidArrayStart, parse_state );
1103
1104 auto const old_class_pos = parse_state.get_class_position( );
1105 parse_state.set_class_position( );
1106 parse_state.remove_prefix( );
1107 parse_state.move_next_member_or_end( );
1108 using tuple_t = typename JsonMember::base_type;
1109 using tuple_members = typename JsonMember::sub_member_list;
1110
1111#if defined( _MSC_VER ) and not defined( __clang__ )
1112 using position_info_t = pocm_details::position_info<ParseState>;
1113 std::size_t parse_locations_last_index = 0U;
1114 std::array<position_info_t, sizeof...( Is )> parse_locations{
1115 [&]( auto Index ) mutable -> position_info_t {
1116 constexpr std::size_t index = decltype( Index )::value;
1117 using member_t = std::tuple_element_t<index, tuple_members>;
1118 if constexpr( is_an_ordered_member_v<member_t> ) {
1119 parse_locations_last_index = member_t::member_index;
1120 return { member_t::member_index };
1121 } else {
1122 return { parse_locations_last_index++ };
1123 }
1124 }( daw::constant<Is>{ } )... };
1125#endif
1126 auto const parse_value_help = [&]( auto PackIdx,
1127 std::size_t &ClassIdx ) {
1128 using index_t = decltype( PackIdx );
1129 using CurrentMember =
1130 std::tuple_element_t<index_t::value, tuple_members>;
1131
1132 using json_member_t = ordered_member_subtype_t<CurrentMember>;
1133#if defined( _MSC_VER ) and not defined( __clang__ )
1134 ParseState parse_state2 =
1135 pocm_details::maybe_skip_members<is_json_nullable_v<json_member_t>>(
1136 parse_state, ClassIdx, index_t::value, parse_locations );
1137 if constexpr( sizeof...( Is ) > 1 ) {
1138 ++ClassIdx;
1139 if( parse_state2.first == parse_state.first ) {
1140 if constexpr( use_direct_construction_v<ParseState,
1141 JsonMember> ) {
1142 auto const run_after_parse = daw::on_exit_success(
1143 [&] { parse_state.move_next_member_or_end( ); } );
1144 (void)run_after_parse;
1145 return parse_value<without_name<json_member_t>>(
1147 } else {
1148 auto result = parse_value<without_name<json_member_t>>(
1150 parse_state.move_next_member_or_end( );
1151 return result;
1152 }
1153 } else {
1154 // Known Bounds
1155 return parse_value<without_name<json_member_t>, true>(
1156 parse_state2, ParseTag<json_member_t::expected_type>{ } );
1157 }
1158 } else {
1159#endif
1160 if constexpr( is_an_ordered_member_v<CurrentMember> ) {
1162 is_json_nullable_v<json_member_t>>(
1163 parse_state, ClassIdx, CurrentMember::member_index );
1164 } else {
1165 daw_json_assert_weak( parse_state.has_more( ),
1166 ErrorReason::UnexpectedEndOfData,
1167 parse_state );
1168 }
1169 ++ClassIdx;
1170 if constexpr( use_direct_construction_v<ParseState, JsonMember> ) {
1171 auto const run_after_parse = daw::on_exit_success(
1172 [&] { parse_state.move_next_member_or_end( ); } );
1173 (void)run_after_parse;
1174 return parse_value<without_name<json_member_t>>(
1176 } else {
1177 auto result = parse_value<without_name<json_member_t>>(
1179 parse_state.move_next_member_or_end( );
1180 return result;
1181 }
1182#if defined( _MSC_VER ) and not defined( __clang__ )
1183 }
1184#endif
1185 };
1186
1187 static_assert( is_a_json_type<JsonMember>::value );
1188 using Constructor = typename JsonMember::constructor_t;
1189
1190 parse_state.trim_left( );
1191
1192 std::size_t class_idx = 0;
1193 if constexpr( use_direct_construction_v<ParseState, JsonMember> ) {
1194 auto const run_after_parse = ordered_class_cleanup<
1195 json_details::all_json_members_must_exist_v<JsonMember, ParseState>,
1196 ParseState, decltype( old_class_pos )>{ parse_state,
1197 old_class_pos };
1198 (void)run_after_parse;
1199 if constexpr( force_aggregate_construction_v<JsonMember> ) {
1200 return tuple_t{
1201 parse_value_help( daw::constant<Is>{ }, class_idx )... };
1202 } else {
1203 return construct_value_tp<tuple_t, Constructor>(
1204 parse_state, fwd_pack{ parse_value_help( daw::constant<Is>{ },
1205 class_idx )... } );
1206 }
1207 } else {
1208 auto result = [&] {
1209 if constexpr( force_aggregate_construction_v<JsonMember> ) {
1210 return tuple_t{
1211 parse_value_help( daw::constant<Is>{ }, class_idx )... };
1212 } else {
1213 return construct_value_tp<tuple_t, Constructor>(
1214 parse_state, fwd_pack{ parse_value_help( daw::constant<Is>{ },
1215 class_idx )... } );
1216 }
1217 }( );
1219 tuple_t, ParseState> ) {
1220 parse_state.trim_left( );
1221 daw_json_assert_weak( parse_state.front( ) == ']',
1222 ErrorReason::UnknownMember, parse_state );
1223 parse_state.remove_prefix( );
1224 parse_state.trim_left( );
1225 } else {
1226 (void)parse_state.skip_array( );
1227 }
1228 parse_state.set_class_position( old_class_pos );
1229 return result;
1230 }
1231 }
1232
1233 template<typename JsonMember, bool KnownBounds, typename ParseState>
1234 DAW_ATTRIB_FLATTEN constexpr json_result<JsonMember>
1236 using element_pack =
1237 typename JsonMember::sub_member_list; // tuple_elements_pack<tuple_t>;
1238
1239 return parse_tuple_value<JsonMember, KnownBounds>(
1241 std::make_index_sequence<std::tuple_size_v<element_pack>>{ } );
1242 }
1243
1244 template<typename JsonMember, bool KnownBounds, typename ParseState>
1245 DAW_ATTRIB_INLINE constexpr json_result<JsonMember>
1248 using constructor_t = typename JsonMember::constructor_t;
1249 if constexpr( KnownBounds ) {
1250 return construct_value(
1251 template_args<json_result<JsonMember>, constructor_t>, parse_state,
1252 std::data( parse_state ), std::size( parse_state ) );
1253 } else {
1254 auto value_parse_state = skip_value( parse_state );
1255 return construct_value(
1256 template_args<json_result<JsonMember>, constructor_t>, parse_state,
1257 std::data( value_parse_state ), std::size( value_parse_state ) );
1258 }
1259 }
1260
1261 template<std::size_t N, typename JsonClass, bool KnownBounds,
1262 typename... JsonClasses, typename ParseState>
1263 DAW_ATTRIB_INLINE constexpr json_result<JsonClass>
1264 parse_nth_class( std::size_t idx, ParseState &parse_state ) {
1265 // Precondition of caller to verify/ensure.
1266 DAW_ASSUME( idx < sizeof...( JsonClasses ) );
1267 using T = typename JsonClass::base_type;
1268 using Constructor = typename JsonClass::constructor_t;
1269 if constexpr( sizeof...( JsonClasses ) >= N + 8 ) {
1270 switch( idx ) {
1271 case N + 0: {
1272 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1273 return construct_value(
1274 template_args<T, Constructor>, parse_state,
1275 parse_value<cur_json_class_t>(
1278 }
1279 case N + 1: {
1280 using cur_json_class_t = traits::nth_element<N + 1, JsonClasses...>;
1281 return construct_value(
1282 template_args<T, Constructor>, parse_state,
1283 parse_value<cur_json_class_t>(
1286 }
1287 case N + 2: {
1288 using cur_json_class_t = traits::nth_element<N + 2, JsonClasses...>;
1289 return construct_value(
1290 template_args<T, Constructor>, parse_state,
1291 parse_value<cur_json_class_t>(
1294 }
1295 case N + 3: {
1296 using cur_json_class_t = traits::nth_element<N + 3, JsonClasses...>;
1297 return construct_value(
1298 template_args<T, Constructor>, parse_state,
1299 parse_value<cur_json_class_t>(
1302 }
1303 case N + 4: {
1304 using cur_json_class_t = traits::nth_element<N + 4, JsonClasses...>;
1305 return construct_value(
1306 template_args<T, Constructor>, parse_state,
1307 parse_value<cur_json_class_t>(
1310 }
1311 case N + 5: {
1312 using cur_json_class_t = traits::nth_element<N + 5, JsonClasses...>;
1313 return construct_value(
1314 template_args<T, Constructor>, parse_state,
1315 parse_value<cur_json_class_t>(
1318 }
1319 case N + 6: {
1320 using cur_json_class_t = traits::nth_element<N + 6, JsonClasses...>;
1321 return construct_value(
1322 template_args<T, Constructor>, parse_state,
1323 parse_value<cur_json_class_t>(
1326 }
1327 case N + 7: {
1328 using cur_json_class_t = traits::nth_element<N + 7, JsonClasses...>;
1329 return construct_value(
1330 template_args<T, Constructor>, parse_state,
1331 parse_value<cur_json_class_t>(
1334 }
1335 default:
1336 if constexpr( sizeof...( JsonClasses ) >= N + 8 ) {
1337 return parse_nth_class<N + 8, JsonClass, KnownBounds,
1338 JsonClasses...>( idx, parse_state );
1339 } else {
1340 DAW_UNREACHABLE( );
1341 }
1342 }
1343 } else if constexpr( sizeof...( JsonClasses ) == N + 7 ) {
1344 switch( idx ) {
1345 case N + 0: {
1346 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1347 return construct_value(
1348 template_args<T, Constructor>, parse_state,
1349 parse_value<cur_json_class_t>(
1352 }
1353 case N + 1: {
1354 using cur_json_class_t = traits::nth_element<N + 1, JsonClasses...>;
1355 return construct_value(
1356 template_args<T, Constructor>, parse_state,
1357 parse_value<cur_json_class_t>(
1360 }
1361 case N + 2: {
1362 using cur_json_class_t = traits::nth_element<N + 2, JsonClasses...>;
1363 return construct_value(
1364 template_args<T, Constructor>, parse_state,
1365 parse_value<cur_json_class_t>(
1368 }
1369 case N + 3: {
1370 using cur_json_class_t = traits::nth_element<N + 3, JsonClasses...>;
1371 return construct_value(
1372 template_args<T, Constructor>, parse_state,
1373 parse_value<cur_json_class_t>(
1376 }
1377 case N + 4: {
1378 using cur_json_class_t = traits::nth_element<N + 4, JsonClasses...>;
1379 return construct_value(
1380 template_args<T, Constructor>, parse_state,
1381 parse_value<cur_json_class_t>(
1384 }
1385 case N + 5: {
1386 using cur_json_class_t = traits::nth_element<N + 5, JsonClasses...>;
1387 return construct_value(
1388 template_args<T, Constructor>, parse_state,
1389 parse_value<cur_json_class_t>(
1392 }
1393 default: {
1394 DAW_ASSUME( idx == N + 6 );
1395 using cur_json_class_t = traits::nth_element<N + 6, JsonClasses...>;
1396 return construct_value(
1397 template_args<T, Constructor>, parse_state,
1398 parse_value<cur_json_class_t>(
1401 }
1402 }
1403 } else if constexpr( sizeof...( JsonClasses ) == N + 6 ) {
1404 switch( idx ) {
1405 case N + 0: {
1406 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1407 return construct_value(
1408 template_args<T, Constructor>, parse_state,
1409 parse_value<cur_json_class_t>(
1412 }
1413 case N + 1: {
1414 using cur_json_class_t = traits::nth_element<N + 1, JsonClasses...>;
1415 return construct_value(
1416 template_args<T, Constructor>, parse_state,
1417 parse_value<cur_json_class_t>(
1420 }
1421 case N + 2: {
1422 using cur_json_class_t = traits::nth_element<N + 2, JsonClasses...>;
1423 return construct_value(
1424 template_args<T, Constructor>, parse_state,
1425 parse_value<cur_json_class_t>(
1428 }
1429 case N + 3: {
1430 using cur_json_class_t = traits::nth_element<N + 3, JsonClasses...>;
1431 return construct_value(
1432 template_args<T, Constructor>, parse_state,
1433 parse_value<cur_json_class_t>(
1436 }
1437 case N + 4: {
1438 using cur_json_class_t = traits::nth_element<N + 4, JsonClasses...>;
1439 return construct_value(
1440 template_args<T, Constructor>, parse_state,
1441 parse_value<cur_json_class_t>(
1444 }
1445 default: {
1446 DAW_ASSUME( idx == N + 5 );
1447 using cur_json_class_t = traits::nth_element<N + 5, JsonClasses...>;
1448 return construct_value(
1449 template_args<T, Constructor>, parse_state,
1450 parse_value<cur_json_class_t>(
1453 }
1454 }
1455 } else if constexpr( sizeof...( JsonClasses ) == N + 5 ) {
1456 switch( idx ) {
1457 case N + 0: {
1458 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1459 return construct_value(
1460 template_args<T, Constructor>, parse_state,
1461 parse_value<cur_json_class_t>(
1464 }
1465 case N + 1: {
1466 using cur_json_class_t = traits::nth_element<N + 1, JsonClasses...>;
1467 return construct_value(
1468 template_args<T, Constructor>, parse_state,
1469 parse_value<cur_json_class_t>(
1472 }
1473 case N + 2: {
1474 using cur_json_class_t = traits::nth_element<N + 2, JsonClasses...>;
1475 return construct_value(
1476 template_args<T, Constructor>, parse_state,
1477 parse_value<cur_json_class_t>(
1480 }
1481 case N + 3: {
1482 using cur_json_class_t = traits::nth_element<N + 3, JsonClasses...>;
1483 return construct_value(
1484 template_args<T, Constructor>, parse_state,
1485 parse_value<cur_json_class_t>(
1488 }
1489 default: {
1490 DAW_ASSUME( idx == N + 4 );
1491 using cur_json_class_t = traits::nth_element<N + 4, JsonClasses...>;
1492 return construct_value(
1493 template_args<T, Constructor>, parse_state,
1494 parse_value<cur_json_class_t>(
1497 }
1498 }
1499 } else if constexpr( sizeof...( JsonClasses ) == N + 4 ) {
1500 switch( idx ) {
1501 case N + 0: {
1502 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1503 return construct_value(
1504 template_args<T, Constructor>, parse_state,
1505 parse_value<cur_json_class_t>(
1508 }
1509 case N + 1: {
1510 using cur_json_class_t = traits::nth_element<N + 1, JsonClasses...>;
1511 return construct_value(
1512 template_args<T, Constructor>, parse_state,
1513 parse_value<cur_json_class_t>(
1516 }
1517 case N + 2: {
1518 using cur_json_class_t = traits::nth_element<N + 2, JsonClasses...>;
1519 return construct_value(
1520 template_args<T, Constructor>, parse_state,
1521 parse_value<cur_json_class_t>(
1524 }
1525 default: {
1526 DAW_ASSUME( idx == N + 3 );
1527 using cur_json_class_t = traits::nth_element<N + 3, JsonClasses...>;
1528 return construct_value(
1529 template_args<T, Constructor>, parse_state,
1530 parse_value<cur_json_class_t>(
1533 }
1534 }
1535 } else if constexpr( sizeof...( JsonClasses ) == N + 3 ) {
1536 switch( idx ) {
1537 case N + 0: {
1538 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1539 return construct_value(
1540 template_args<T, Constructor>, parse_state,
1541 parse_value<cur_json_class_t>(
1544 }
1545 case N + 1: {
1546 using cur_json_class_t = traits::nth_element<N + 1, JsonClasses...>;
1547 return construct_value(
1548 template_args<T, Constructor>, parse_state,
1549 parse_value<cur_json_class_t>(
1552 }
1553 default: {
1554 DAW_ASSUME( idx == N + 2 );
1555 using cur_json_class_t = traits::nth_element<N + 2, JsonClasses...>;
1556 return construct_value(
1557 template_args<T, Constructor>, parse_state,
1558 parse_value<cur_json_class_t>(
1561 }
1562 }
1563 } else if constexpr( sizeof...( JsonClasses ) == N + 2 ) {
1564 if( idx == N ) {
1565 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1566 return construct_value(
1567 template_args<T, Constructor>, parse_state,
1568 parse_value<cur_json_class_t>(
1571 }
1572 using cur_json_class_t = traits::nth_element<N + 1, JsonClasses...>;
1573 return construct_value(
1574 template_args<T, Constructor>, parse_state,
1575 parse_value<cur_json_class_t>(
1578 } else {
1579 using cur_json_class_t = traits::nth_element<N + 0, JsonClasses...>;
1580 return construct_value(
1581 template_args<T, Constructor>, parse_state,
1582 parse_value<cur_json_class_t>(
1585 }
1586 }
1587 } // namespace json_details
1588 } // namespace DAW_JSON_VER
1589} // namespace daw::json
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:190
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:179
OldClassPos const & old_class_pos
Definition: daw_json_parse_class.h:183
#define CPP20CONSTEXPR
Definition: daw_json_parse_value.h:40
ParseState & parse_state
Definition: daw_json_parse_value.h:600
constexpr DAW_ATTRIB_INLINE void maybe_skip_members(ParseState &parse_state, std::size_t &current_position, std::size_t desired_position)
Definition: daw_json_parse_value.h:1016
constexpr auto parse_string_known_stdstring(ParseState &parse_state)
Definition: daw_json_parse_std_string.h:197
constexpr ParseState skip_value(ParseState &parse_state)
Definition: daw_json_skip.h:304
constexpr DAW_ATTRIB_INLINE json_result< JsonMember > parse_value(ParseState &parse_state, ParseTag< JsonParseTypes::Real >)
Definition: daw_json_parse_value.h:75
constexpr bool has_json_member_constructor_v
Definition: daw_json_parse_value.h:482
constexpr DAW_ATTRIB_INLINE Result parse_visit(std::size_t idx, ParseState &parse_state)
Definition: daw_json_parse_value.h:859
constexpr ParseState skip_literal(ParseState &parse_state)
Definition: daw_json_skip.h:393
std::bool_constant< daw::is_detected_v< json_type_t, T > > is_a_json_type
Definition: daw_json_traits.h:446
typename daw::detected_or_t< T, ordered_member_subtype_test, T > ordered_member_subtype_t
Definition: daw_json_parse_common.h:51
constexpr bool all_json_members_must_exist_v
Definition: daw_json_traits.h:641
constexpr DAW_ATTRIB_INLINE json_result< JsonClass > parse_nth_class(std::size_t idx, ParseState &parse_state)
Definition: daw_json_parse_value.h:1264
typename JsonMember::dependent_member dependent_member_t
Definition: daw_json_parse_common.h:995
typename T::parse_to_t json_member_parse_to_t
Definition: daw_json_parse_value.h:479
constexpr DAW_ATTRIB_INLINE json_result< JsonMember > parse_tuple_value(ParseState &parse_state, std::index_sequence< Is... >)
Definition: daw_json_parse_value.h:1099
constexpr DAW_ATTRIB_FLATTEN json_result< JsonMembers > parse_variant_value(ParseState &parse_state)
Definition: daw_json_parse_value.h:795
constexpr DAW_ATTRIB_FLATINLINE ParseState skip_string(ParseState &parse_state)
Definition: daw_json_skip.h:56
AllMembersMustExist
Definition: daw_json_location_info.h:206
typename JsonMember::switcher switcher_t
Definition: daw_json_traits.h:159
typename T::constructor_t json_member_constructor_t
Definition: daw_json_parse_value.h:476
constexpr auto find_index(ParseState parse_state)
Definition: daw_json_parse_value.h:883
static constexpr DAW_ATTRIB_FLATINLINE auto construct_value(template_params< Value, Constructor >, ParseState &parse_state, Args &&...args)
Definition: daw_json_parse_common.h:60
typename JsonMember::parse_to_t json_result
Definition: daw_json_parse_common.h:200
constexpr bool needs_slow_path(ParseState const &parse_state)
Definition: daw_json_parse_string_need_slow.h:23
constexpr DAW_ATTRIB_INLINE void skip_quote_when_literal_as_string(ParseState &parse_state)
Definition: daw_json_parse_value.h:57
constexpr bool use_direct_construction_v
Definition: daw_json_parse_common.h:959
constexpr Signed to_signed(Unsigned &&u, Signed sign)
Definition: daw_json_parse_unsigned_int.h:38
constexpr bool has_json_member_parse_to_v
Definition: daw_json_parse_value.h:486
constexpr DAW_ATTRIB_FLATINLINE int validate_signed_first(ParseState &parse_state)
Definition: daw_json_parse_policy_policy_details.h:73
constexpr DAW_ATTRIB_FLATINLINE bool is_number(char c)
Definition: daw_json_parse_policy_policy_details.h:34
constexpr DAW_ATTRIB_FLATINLINE void validate_unsigned_first(ParseState const &parse_state)
Definition: daw_json_parse_policy_policy_details.h:41
constexpr DAW_ATTRIB_FLATINLINE bool at_end_of_item(char c)
Definition: daw_json_parse_policy_policy_details.h:25
constexpr DAW_ATTRIB_FLATINLINE bool is_number_start(char c)
Definition: daw_json_parse_policy_policy_details.h:107
@ KeyValueArray
Class - Member names form the string key into a key/value,map, or dictionary like type.
daw::constant< v > ParseTag
Definition: daw_json_enums.h:119
typename json_data_contract< T >::type json_data_contract_trait_t
Definition: daw_json_traits.h:135
DAW_ATTRIB_NOINLINE void daw_json_error(ErrorReason reason)
Definition: daw_json_assert.h:39
JsonBaseParseTypes
The fundamental JSON types.
Definition: daw_json_enums.h:53
Definition: daw_from_json.h:22
Definition: daw_json_parse_array_iterator.h:64
Definition: daw_json_parse_kv_array_iterator.h:60
Definition: daw_json_parse_kv_class_iterator.h:65
ParseState & parse_state
Definition: daw_json_parse_value.h:969
OldClassPos const & old_class_pos
Definition: daw_json_parse_value.h:970
DAW_ATTRIB_INLINE CPP20CONSTEXPR ~ordered_class_cleanup() noexcept(false)
Definition: daw_json_parse_value.h:973
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition: version.h:16