DAW JSON Link
Loading...
Searching...
No Matches
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
12
15#if defined( DAW_ALLOW_SSE42 )
17#endif
29
30#include <daw/algorithms/daw_algorithm_find.h>
31#include <daw/daw_arith_traits.h>
32#include <daw/daw_attributes.h>
33#include <daw/daw_callable.h>
34#include <daw/daw_constant.h>
35#include <daw/daw_cxmath.h>
36#include <daw/daw_scope_guard.h>
37#include <daw/traits/daw_traits_conditional.h>
38#include <daw/traits/daw_traits_identity.h>
39
40#include <cstddef>
41#include <cstdint>
42#include <daw/stdinc/data_access.h>
43#include <daw/stdinc/tuple_traits.h>
44#include <type_traits>
45
46namespace daw::json {
47 inline namespace DAW_JSON_VER {
48 namespace json_details {
49 /***
50 * Depending on the type of literal, it may always be quoted, sometimes,
51 * or never. This method handles the always and sometimes cases.
52 * In checked input, ensures State has more data.
53 * @tparam literal_as_string Is the literal being parsed enclosed in
54 * quotes.
55 * @tparam ParseState ParseState idiom
56 * @param parse_state Current parsing state
57 */
58 template<options::LiteralAsStringOpt literal_as_string,
59 typename ParseState>
60 DAW_ATTRIB_INLINE constexpr void
61 skip_quote_when_literal_as_string( ParseState &parse_state ) {
62 if constexpr( literal_as_string ==
63 options::LiteralAsStringOpt::Always ) {
64 daw_json_assert_weak( parse_state.is_quotes_checked( ),
65 ErrorReason::InvalidNumberUnexpectedQuoting,
66 parse_state );
67 parse_state.remove_prefix( );
68 } else if constexpr( literal_as_string ==
69 options::LiteralAsStringOpt::Maybe ) {
70 daw_json_assert_weak( parse_state.has_more( ),
71 ErrorReason::UnexpectedEndOfData,
72 parse_state );
73 if( parse_state.front( ) == '"' ) {
74 parse_state.remove_prefix( );
75 }
76 }
77 }
78
79 template<typename JsonMember, bool KnownBounds, typename ParseState>
80 [[nodiscard]] constexpr json_result_t<JsonMember>
81 parse_value_real( ParseState &parse_state ) {
82 using constructor_t = json_constructor_t<JsonMember>;
83 using element_t = json_base_type_t<JsonMember>;
84
85 if constexpr( JsonMember::literal_as_string !=
86 options::LiteralAsStringOpt::Never ) {
87 if constexpr( not KnownBounds ) {
88 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
89 parse_state );
90 }
91 if constexpr( JsonMember::allow_number_errors ==
92 options::JsonNumberErrors::AllowInf or
93 JsonMember::allow_number_errors ==
94 options::JsonNumberErrors::AllowNanInf ) {
95 element_t sign = element_t( 1.0 );
96 if( parse_state.front( ) == '-' ) {
97 sign = element_t( -1.0 );
98 ++parse_state.first;
99 }
100 // Looking for Inf as that will match Infinity too.
101 if( parse_state.starts_with_skip( "Inf" ) ) {
102 if( not( parse_state.starts_with_skip( "\"" ) or
103 parse_state.starts_with_skip( "inity\"" ) ) ) {
104 daw_json_error( true, ErrorReason::InvalidString, parse_state );
105 }
106 if constexpr( KnownBounds ) {
107 daw_json_assert_weak( parse_state.empty( ),
108 ErrorReason::InvalidNumber,
109 parse_state );
110 } else {
111 daw_json_assert_weak( parse_state.empty( ) or
112 parse_policy_details::at_end_of_item(
113 parse_state.front( ) ),
114 ErrorReason::InvalidEndOfValue,
115 parse_state );
116 }
117 return daw::cxmath::copy_sign(
118 daw::numeric_limits<element_t>::infinity( ), sign );
119 } else if( sign < element_t( 0 ) ) {
120 parse_state.first--;
121 }
122 }
123 if constexpr( JsonMember::allow_number_errors ==
124 options::JsonNumberErrors::AllowNaN or
125 JsonMember::allow_number_errors ==
126 options::JsonNumberErrors::AllowNanInf ) {
127 if( parse_state.starts_with( "NaN" ) ) {
128 parse_state.template move_to_next_of<'"'>( );
129 parse_state.remove_prefix( );
130 if constexpr( KnownBounds ) {
131 daw_json_assert_weak( parse_state.empty( ),
132 ErrorReason::InvalidNumber,
133 parse_state );
134 } else {
135 daw_json_assert_weak( parse_state.empty( ) or
136 parse_policy_details::at_end_of_item(
137 parse_state.front( ) ),
138 ErrorReason::InvalidEndOfValue,
139 parse_state );
140 }
141 return daw::numeric_limits<element_t>::quiet_NaN( );
142 }
143 }
144 }
145 if constexpr( KnownBounds and JsonMember::literal_as_string ==
146 options::LiteralAsStringOpt::Never ) {
147 return construct_value<json_result_t<JsonMember>, constructor_t>(
148 parse_state, parse_real<element_t, true>( parse_state ) );
149 } else {
151 parse_state.has_more( ) and
152 parse_policy_details::is_number_start( parse_state.front( ) ),
153 ErrorReason::InvalidNumberStart,
154 parse_state );
155
156 auto result =
157 construct_value<json_result_t<JsonMember>, constructor_t>(
158 parse_state, parse_real<element_t, false>( parse_state ) );
159
160 if constexpr( KnownBounds ) {
162 parse_state.empty( ) or
163 parse_policy_details::at_end_of_item( parse_state.front( ) ),
164 ErrorReason::InvalidEndOfValue,
165 parse_state );
166 } else {
167 if constexpr( JsonMember::literal_as_string !=
168 options::LiteralAsStringOpt::Never ) {
169 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
170 parse_state );
171 }
173 parse_state.empty( ) or
174 parse_policy_details::at_end_of_item( parse_state.front( ) ),
175 ErrorReason::InvalidEndOfValue,
176 parse_state );
177 }
178 return result;
179 }
180 }
181
182 template<typename JsonMember, bool KnownBounds, typename ParseState>
183 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
184 parse_value_signed( ParseState &parse_state ) {
185 using constructor_t = json_constructor_t<JsonMember>;
186 using element_t = json_base_type_t<JsonMember>;
187 using int_type =
188 typename daw::conditional_t<std::is_enum_v<element_t>,
189 std::underlying_type<element_t>,
190 daw::traits::identity<element_t>>::type;
191
192 static_assert( daw::is_signed_v<int_type>, "Expected signed type" );
193 if constexpr( KnownBounds ) {
195 parse_policy_details::is_number_start( parse_state.front( ) ),
196 ErrorReason::InvalidNumberStart,
197 parse_state );
198 } else {
199 if constexpr( JsonMember::literal_as_string !=
200 options::LiteralAsStringOpt::Never ) {
201 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
202 parse_state );
203 } else if constexpr( not ParseState::is_zero_terminated_string ) {
204 daw_json_assert_weak( parse_state.has_more( ),
205 ErrorReason::UnexpectedEndOfData,
206 parse_state );
207 }
208 }
209 auto const sign = static_cast<int_type>(
210 parse_policy_details::validate_signed_first( parse_state ) );
211 using uint_type =
212 typename daw::conditional_t<daw::is_system_integral_v<int_type>,
213 daw::make_unsigned<int_type>,
214 daw::traits::identity<int_type>>::type;
215 auto parsed_val = to_signed(
216 unsigned_parser<uint_type, JsonMember::range_check, KnownBounds>(
217 parse_state ),
218 sign );
219
220 if constexpr( KnownBounds ) {
221 return construct_value<json_result_t<JsonMember>, constructor_t>(
222 parse_state, static_cast<element_t>( parsed_val ) );
223 } else {
224 auto result =
225 construct_value<json_result_t<JsonMember>, constructor_t>(
226 parse_state, static_cast<element_t>( parsed_val ) );
227 if constexpr( JsonMember::literal_as_string !=
228 options::LiteralAsStringOpt::Never ) {
229 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
230 parse_state );
231 }
232 parse_state.trim_left( );
234 not parse_state.has_more( ) or
235 parse_policy_details::at_end_of_item( parse_state.front( ) ),
236 ErrorReason::InvalidEndOfValue,
237 parse_state );
238 return result;
239 }
240 }
241
242 template<typename JsonMember, bool KnownBounds, typename ParseState>
243 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
244 parse_value_unsigned( ParseState &parse_state ) {
245 using constructor_t = json_constructor_t<JsonMember>;
246 using element_t = json_base_type_t<JsonMember>;
247 using uint_type =
248 typename daw::conditional_t<std::is_enum_v<element_t>,
249 std::underlying_type<element_t>,
250 daw::traits::identity<element_t>>::type;
251
252 if constexpr( KnownBounds ) {
253 parse_policy_details::validate_unsigned_first( parse_state );
254
255 return construct_value<json_result_t<JsonMember>, constructor_t>(
256 parse_state,
257 unsigned_parser<uint_type, JsonMember::range_check, KnownBounds>(
258 parse_state ) );
259 } else {
260 if constexpr( JsonMember::literal_as_string !=
261 options::LiteralAsStringOpt::Never ) {
262 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
263 parse_state );
264 if constexpr( not ParseState::is_zero_terminated_string ) {
265 daw_json_assert_weak( parse_state.has_more( ),
266 ErrorReason::UnexpectedEndOfData,
267 parse_state );
268 }
269 } else if constexpr( not ParseState::is_zero_terminated_string ) {
270 daw_json_assert_weak( parse_state.has_more( ),
271 ErrorReason::UnexpectedEndOfData,
272 parse_state );
273 }
275 parse_policy_details::is_number( parse_state.front( ) ),
276 ErrorReason::InvalidNumber,
277 parse_state );
278 auto result =
279 construct_value<json_result_t<JsonMember>, constructor_t>(
280 parse_state,
281 unsigned_parser<uint_type, JsonMember::range_check, KnownBounds>(
282 parse_state ) );
283 if constexpr( JsonMember::literal_as_string !=
284 options::LiteralAsStringOpt::Never ) {
285 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
286 parse_state );
287 if constexpr( not ParseState::is_zero_terminated_string ) {
288 daw_json_assert_weak( parse_state.has_more( ),
289 ErrorReason::UnexpectedEndOfData,
290 parse_state );
291 }
292 }
294 not parse_state.has_more( ) or
295 parse_policy_details::at_end_of_item( parse_state.front( ) ),
296 ErrorReason::InvalidEndOfValue,
297 parse_state );
298 return result;
299 }
300 }
301
302 template<typename JsonMember, bool KnownBounds, typename ParseState>
303 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
304 parse_value_null( ParseState &parse_state ) {
305
306 using constructor_t = json_constructor_t<JsonMember>;
307 auto const construct_empty = [&] {
308 if constexpr( daw::is_callable_v<
309 constructor_t,
310 concepts::construct_nullable_with_empty_t> ) {
311 return construct_value<typename JsonMember::wrapped_type,
312 constructor_t>(
313 parse_state, concepts::construct_nullable_with_empty );
314 } else {
315 return construct_value<typename JsonMember::wrapped_type,
316 constructor_t>( parse_state );
317 }
318 };
319
320 using base_member_type = typename JsonMember::member_type;
321 static_assert( not std::is_same_v<base_member_type, JsonMember> );
322 if constexpr( KnownBounds ) {
323 // skip_value will leave a null parse_state
324 if( parse_state.is_null( ) ) {
325 return construct_empty( );
326 }
327 return construct_value<base_member_type, constructor_t>(
328 parse_state,
329 parse_value<base_member_type,
330 true,
331 base_member_type::expected_type>( parse_state ) );
332 } else if constexpr( ParseState::is_unchecked_input ) {
333 if( not parse_state.has_more( ) or
334 parse_state.is_at_token_after_value( ) ) {
335 return construct_empty( );
336 }
337 if( parse_state.front( ) == 'n' ) {
338 parse_state.remove_prefix( 4 );
339 parse_state.trim_left_unchecked( );
340 parse_state.remove_prefix( );
341 return construct_empty( );
342 }
343 return construct_value<base_member_type, constructor_t>(
344 parse_state,
345 parse_value<base_member_type,
346 false,
347 base_member_type::expected_type>( parse_state ) );
348 } else {
349 if( not parse_state.has_more( ) or
350 parse_state.is_at_token_after_value( ) ) {
351 return construct_empty( );
352 }
353 if( parse_state.starts_with( "null" ) ) {
354 parse_state.remove_prefix( 4 );
356 not parse_state.has_more( ) or
357 parse_policy_details::at_end_of_item( parse_state.front( ) ),
358 ErrorReason::InvalidLiteral,
359 parse_state );
360 parse_state.trim_left_checked( );
361 return construct_empty( );
362 }
363 using parse_to_t = json_result_t<base_member_type>;
364 if constexpr( not std::is_move_constructible_v<parse_to_t> and
365 not std::is_copy_constructible_v<parse_to_t> ) {
366 static_assert(
367 daw::is_callable_v<
368 concepts::nullable_value_traits<json_result_t<JsonMember>>,
369 concepts::construct_nullable_with_pointer_t,
370 parse_to_t *> );
371 return construct_value<base_member_type, constructor_t>(
372 parse_state,
373 concepts::construct_nullable_with_pointer,
374 new parse_to_t{
375 parse_value<base_member_type,
376 false,
377 base_member_type::expected_type>( parse_state ) } );
378 } else {
379 return construct_value<base_member_type, constructor_t>(
380 parse_state,
381 parse_value<base_member_type,
382 false,
383 base_member_type::expected_type>( parse_state ) );
384 }
385 }
386 }
387
388 template<typename JsonMember, bool KnownBounds, typename ParseState>
389 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
390 parse_value_bool( ParseState &parse_state ) {
391 using constructor_t = json_constructor_t<JsonMember>;
392
393 if constexpr( KnownBounds ) {
394 // We have already checked if it is a true/false
395 if constexpr( ParseState::is_unchecked_input ) {
396 return static_cast<bool>( parse_state.counter );
397 } else {
398 switch( parse_state.front( ) ) {
399 case 't':
400 return construct_value<json_result_t<JsonMember>, constructor_t>(
401 parse_state, true );
402 case 'f':
403 return construct_value<json_result_t<JsonMember>, constructor_t>(
404 parse_state, false );
405 }
406 daw_json_error( true, ErrorReason::InvalidLiteral, parse_state );
407 }
408 } else {
409 // Beginning quotes
410 if constexpr( JsonMember::literal_as_string !=
411 options::LiteralAsStringOpt::Never ) {
412 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
413 parse_state );
414 }
415 bool result = false;
416 if constexpr( ParseState::is_unchecked_input ) {
417 if( parse_state.front( ) == 't' ) /* true */ {
418 result = true;
419 parse_state.remove_prefix( 4 );
420 } else /* false */ {
421 parse_state.remove_prefix( 5 );
422 }
423 } else {
424 if( parse_state.starts_with( "true" ) ) {
425 parse_state.remove_prefix( 4 );
426 result = true;
427 } else if( parse_state.starts_with( "false" ) ) {
428 parse_state.remove_prefix( 5 );
429 } else {
430 daw_json_error( true, ErrorReason::InvalidLiteral, parse_state );
431 }
432 }
433 // Trailing quotes
434 if constexpr( JsonMember::literal_as_string !=
435 options::LiteralAsStringOpt::Never ) {
436 skip_quote_when_literal_as_string<JsonMember::literal_as_string>(
437 parse_state );
438 }
439 parse_state.trim_left( );
441 not parse_state.has_more( ) or
442 parse_policy_details::at_end_of_item( parse_state.front( ) ),
443 ErrorReason::InvalidEndOfValue,
444 parse_state );
445 return construct_value<json_result_t<JsonMember>, constructor_t>(
446 parse_state, result );
447 }
448 }
449
450 template<typename JsonMember, bool KnownBounds, typename ParseState>
451 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
452 parse_value_string_raw( ParseState &parse_state ) {
453
454 using constructor_t = json_constructor_t<JsonMember>;
455 if constexpr( KnownBounds ) {
456 return construct_value<json_result_t<JsonMember>, constructor_t>(
457 parse_state, std::data( parse_state ), std::size( parse_state ) );
458 } else {
459 if constexpr( JsonMember::allow_escape_character ==
460 options::AllowEscapeCharacter::Allow ) {
461 auto const str = skip_string( parse_state );
462 return construct_value<json_result_t<JsonMember>, constructor_t>(
463 parse_state, std::data( str ), std::size( str ) );
464 } else {
465 parse_state.remove_prefix( );
466
467 char const *const first = parse_state.first;
468 parse_state.template move_to_next_of<'"'>( );
469 char const *const last = parse_state.first;
470 parse_state.remove_prefix( );
471 return construct_value<json_result_t<JsonMember>, constructor_t>(
472 parse_state, first, static_cast<std::size_t>( last - first ) );
473 }
474 }
475 }
476
477 /***
478 * We know that we are constructing a std::string or
479 * std::optional<std::string> We can take advantage of this and reduce
480 * the allocator time by presizing the string up front and then using a
481 * pointer to the data( ).
482 */
483 template<typename JsonMember>
484 DAW_CPP20_CONCEPT can_parse_to_stdstring_fast_v =
485 can_single_allocation_string_v<json_result_t<JsonMember>> or
486 can_single_allocation_string_v<json_base_type_t<JsonMember>>;
487
488 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT_NT( has_json_member_constructor_v,
489 json_constructor_t<T> );
490
491 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT_NT( has_json_member_parse_to_v,
492 json_result_t<T> );
493
494 template<typename JsonMember, bool KnownBounds, typename ParseState>
495 [[nodiscard]] DAW_ATTRIB_INLINE constexpr json_result_t<JsonMember>
496 parse_value_string_escaped( ParseState &parse_state ) {
497 static_assert( has_json_member_constructor_v<JsonMember> );
498 static_assert( has_json_member_parse_to_v<JsonMember> );
499 if constexpr( not KnownBounds ) {
500 daw_json_ensure( not parse_state.empty( ),
501 ErrorReason::UnexpectedNull );
502 }
503 using constructor_t = json_constructor_t<JsonMember>;
504 if constexpr( can_parse_to_stdstring_fast_v<JsonMember> ) {
505 using AllowHighEightbits =
506 std::bool_constant<JsonMember::eight_bit_mode !=
507 options::EightBitModes::DisallowHigh>;
508 auto parse_state2 =
509 KnownBounds ? parse_state : skip_string( parse_state );
510 if( not AllowHighEightbits::value or
511 needs_slow_path( parse_state2 ) ) {
512 // There are escapes in the string
513 return parse_string_known_stdstring<AllowHighEightbits::value,
514 JsonMember,
515 true>( parse_state2 );
516 }
517 // There are no escapes in the string, we can just use the ptr/size
518 // ctor
519 return construct_value<json_result_t<JsonMember>, constructor_t>(
520 parse_state,
521 std::data( parse_state2 ),
522 daw::data_end( parse_state2 ) );
523 } else {
524 auto parse_state2 =
525 KnownBounds ? parse_state : skip_string( parse_state );
526 using AllowHighEightbits =
527 std::bool_constant<JsonMember::eight_bit_mode !=
528 options::EightBitModes::DisallowHigh>;
529 if( not AllowHighEightbits::value or
530 needs_slow_path( parse_state2 ) ) {
531 // There are escapes in the string
532 return parse_string_known_stdstring<AllowHighEightbits::value,
533 JsonMember,
534 true>( parse_state2 );
535 }
536 // There are no escapes in the string, we can just use the ptr/size
537 // ctor
538 return construct_value<json_result_t<JsonMember>, constructor_t>(
539 parse_state,
540 std::data( parse_state2 ),
541 daw::data_end( parse_state2 ) );
542 }
543 }
544
545 template<typename JsonMember, bool KnownBounds, typename ParseState>
546 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
547 parse_value_date( ParseState &parse_state ) {
548
549 daw_json_assert_weak( parse_state.has_more( ),
550 ErrorReason::UnexpectedEndOfData,
551 parse_state );
552 auto str = KnownBounds ? parse_state : skip_string( parse_state );
553 using constructor_t = json_constructor_t<JsonMember>;
554 return construct_value<json_result_t<JsonMember>, constructor_t>(
555 parse_state, std::data( str ), std::size( str ) );
556 }
557
558 template<typename JsonMember, bool KnownBounds, typename ParseState>
559 [[nodiscard]] static constexpr json_result_t<JsonMember>
560 parse_value_custom( ParseState &parse_state ) {
561
562 auto const str = [&] {
563 if constexpr( JsonMember::custom_json_type ==
564 options::JsonCustomTypes::String ) {
565 if constexpr( KnownBounds ) {
566 return parse_state;
567 } else {
568 return skip_string( parse_state );
569 }
570 } else if constexpr( JsonMember::custom_json_type ==
571 options::JsonCustomTypes::Literal ) {
572 return KnownBounds ? parse_state : skip_literal( parse_state );
573 } else {
574 static_assert( JsonMember::custom_json_type ==
575 options::JsonCustomTypes::Any );
576 // If we are a root object, parse_state will have the quotes and
577 // KnownBounds cannot be true This tells us that there is an array
578 // start '[' or a member name previous to current position
579 if constexpr( KnownBounds ) {
580 auto result = parse_state;
581 if( *( result.first - 1 ) == '"' ) {
582 result.first--;
583 }
584 return result;
585 } else {
586 if( parse_state.front( ) == '"' ) {
587 auto result = skip_string( parse_state );
588 result.first--;
589 return result;
590 }
591 return skip_value( parse_state );
592 }
593 }
594 }( );
596 str.has_more( ) and not( str.front( ) == '[' or str.front( ) == '{' ),
597 ErrorReason::InvalidStartOfValue,
598 str );
599 using constructor_t = typename JsonMember::from_converter_t;
600 return construct_value<json_result_t<JsonMember>, constructor_t>(
601 parse_state, std::string_view( std::data( str ), std::size( str ) ) );
602 }
603
604 template<typename JsonMember, bool KnownBounds, typename ParseState>
605 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
606 parse_value_class( ParseState &parse_state ) {
607
608 using element_t = typename JsonMember::wrapped_type;
609 daw_json_assert_weak( parse_state.has_more( ),
610 ErrorReason::UnexpectedEndOfData,
611 parse_state );
612
613 if constexpr( KnownBounds ) {
615 template parse_to_class<JsonMember, KnownBounds>( parse_state );
616 } else if constexpr( is_pinned_type_v<element_t> ) {
617 auto const run_after_parse = daw::on_exit_success( [&] {
618 parse_state.trim_left_checked( );
619 } );
620 (void)run_after_parse;
622 template parse_to_class<JsonMember, KnownBounds>( parse_state );
623 } else if constexpr( is_deduced_empty_class_v<JsonMember> ) {
624 parse_state.trim_left_checked( );
625 return json_result_t<JsonMember>{ };
626 } else {
628 template parse_to_class<JsonMember, KnownBounds>( parse_state );
629 parse_state.trim_left_checked( );
630 return result;
631 }
632 }
633
634#if defined( DAW_JSON_HAS_REFLECTION )
635 template<typename JsonMember, bool /*KnownBounds*/, typename ParseState>
636 constexpr json_result_t<JsonMember>
637 parse_value_reflected_class( ParseState &parse_state ) {
638 daw_json_assert_weak( parse_state.has_more( ),
639 ErrorReason::UnexpectedEndOfData,
640 parse_state );
641
642 return JsonMember::parse_to_class( parse_state );
643 }
644#endif
645
654 template<typename JsonMember, bool KnownBounds, typename ParseState>
655 [[nodiscard]] static constexpr json_result_t<JsonMember>
656 parse_value_keyvalue( ParseState &parse_state ) {
657
658 static_assert( JsonMember::expected_type == JsonParseTypes::KeyValue,
659 "Expected a json_key_value" );
660 daw_json_assert_weak( parse_state.is_opening_brace_checked( ),
661 ErrorReason::ExpectedKeyValueToStartWithBrace,
662 parse_state );
663
664 parse_state.remove_prefix( );
665 parse_state.trim_left( );
666
667 using iter_t =
668 json_parse_kv_class_iterator<JsonMember,
669 ParseState,
670 can_be_random_iterator_v<KnownBounds>>;
671
672 using constructor_t = json_constructor_t<JsonMember>;
673 return construct_value<json_result_t<JsonMember>, constructor_t>(
674 parse_state, iter_t( parse_state ), iter_t( ) );
675 }
676
685 template<typename JsonMember, bool KnownBounds, typename ParseState>
686 [[nodiscard]] static constexpr json_result_t<JsonMember>
687 parse_value_keyvalue_array( ParseState &parse_state ) {
688
689 static_assert( JsonMember::expected_type ==
690 JsonParseTypes::KeyValueArray,
691 "Expected a json_key_value" );
693 parse_state.is_opening_bracket_checked( ),
694 ErrorReason::ExpectedKeyValueArrayToStartWithBracket,
695 parse_state );
696
697 parse_state.remove_prefix( );
698
699 using iter_t =
700 json_parse_kv_array_iterator<JsonMember,
701 ParseState,
702 can_be_random_iterator_v<KnownBounds>>;
703 using constructor_t = json_constructor_t<JsonMember>;
704 return construct_value<json_result_t<JsonMember>, constructor_t>(
705 parse_state, iter_t( parse_state ), iter_t( ) );
706 }
707
708 template<typename JsonMember, bool KnownBounds, typename ParseState>
709 [[nodiscard]] static constexpr json_result_t<JsonMember>
710 parse_value_array( ParseState &parse_state ) {
711 parse_state.trim_left( );
712 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
713 ErrorReason::InvalidArrayStart,
714 parse_state );
715 parse_state.remove_prefix( );
716 parse_state.trim_left_unchecked( );
717 // TODO: add parse option to disable random access iterators. This is
718 // coding to the implementations
719
720 using iterator_t =
721 json_parse_array_iterator<JsonMember,
722 ParseState,
723 can_be_random_iterator_v<KnownBounds>>;
724 using constructor_t = json_constructor_t<JsonMember>;
725 return construct_value<json_result_t<JsonMember>, constructor_t>(
726 parse_state, iterator_t( parse_state ), iterator_t( ) );
727 }
728
729 template<typename JsonMember, bool KnownBounds, typename ParseState>
730 [[nodiscard]] static constexpr json_result_t<JsonMember>
731 parse_value_sz_array( ParseState &parse_state ) {
732
733 using size_member = dependent_member_t<JsonMember>;
734
735 auto [parse_state2, is_found] = find_range<ParseState>(
736 ParseState( parse_state.class_first, parse_state.last ),
737 size_member::name );
738
740 is_found, ErrorReason::TagMemberNotFound, parse_state );
741 auto const sz =
742 parse_value<size_member, false, size_member::expected_type>(
743 parse_state2 );
744
745 if constexpr( KnownBounds and ParseState::is_unchecked_input ) {
746 // We have the requested size and the actual size. Let's see if they
747 // match
748 auto cnt = static_cast<std::ptrdiff_t>( parse_state.counter );
749 daw_json_ensure( sz >= 0 and ( cnt < 0 or parse_state.counter == sz ),
750 ErrorReason::NumberOutOfRange,
751 parse_state );
752 }
753 parse_state.trim_left( );
754 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
755 ErrorReason::InvalidArrayStart,
756 parse_state );
757 parse_state.remove_prefix( );
758 parse_state.trim_left_unchecked( );
759 // TODO: add parse option to disable random access iterators. This is
760 // coding to the implementations
761 using iterator_t =
762 json_parse_array_iterator<JsonMember, ParseState, false>;
763 using constructor_t = json_constructor_t<JsonMember>;
764 return construct_value<json_result_t<JsonMember>, constructor_t>(
765 parse_state,
766 iterator_t( parse_state ),
767 iterator_t( ),
768 static_cast<std::size_t>( sz ) );
769 }
770
771 template<JsonBaseParseTypes BPT, typename JsonMembers, bool KnownBounds,
772 typename ParseState>
773 [[nodiscard]] constexpr json_result_t<JsonMembers>
774 parse_variant_value( ParseState &parse_state ) {
775 using element_t = typename JsonMembers::json_elements;
776 using idx = daw::constant<( JsonMembers::base_map::base_map
777 [static_cast<std::int_fast8_t>( BPT )] )>;
778
779 if constexpr( idx::value <
780 pack_size_v<typename element_t::element_map_t> ) {
781 using JsonMember =
782 pack_element_t<idx::value, typename element_t::element_map_t>;
783 return parse_value<JsonMember,
784 KnownBounds,
785 JsonMember::expected_type>( parse_state );
786 } else {
787 daw_json_error( true, ErrorReason::UnexpectedJSONVariantType );
788 }
789 }
790
791 template<typename JsonMember, bool KnownBounds, typename ParseState>
792 [[nodiscard]] static constexpr json_result_t<JsonMember>
793 parse_value_variant( ParseState &parse_state ) {
794 if constexpr( KnownBounds ) {
795 // We are only in this branch when a member has been skipped. This
796 // means we can look backwards
797 if( *( parse_state.first - 1 ) == '"' ) {
798 // We are a string, the skipper trims them
799 return parse_variant_value<JsonBaseParseTypes::String,
800 JsonMember,
801 KnownBounds>( parse_state );
802 }
803 }
804 switch( parse_state.front( ) ) {
805 case '{':
806 return parse_variant_value<JsonBaseParseTypes::Class,
807 JsonMember,
808 KnownBounds>( parse_state );
809 case '[':
810 return parse_variant_value<JsonBaseParseTypes::Array,
811 JsonMember,
812 KnownBounds>( parse_state );
813 case 't':
814 case 'f':
815 return parse_variant_value<JsonBaseParseTypes::Bool,
816 JsonMember,
817 KnownBounds>( parse_state );
818 case '"':
819 return parse_variant_value<JsonBaseParseTypes::String,
820 JsonMember,
821 KnownBounds>( parse_state );
822 case '0':
823 case '1':
824 case '2':
825 case '3':
826 case '4':
827 case '5':
828 case '6':
829 case '7':
830 case '8':
831 case '9':
832 case '+':
833 case '-':
834 return parse_variant_value<JsonBaseParseTypes::Number,
835 JsonMember,
836 KnownBounds>( parse_state );
837 }
838 if constexpr( ParseState::is_unchecked_input ) {
839 DAW_UNREACHABLE( );
840 } else {
841 daw_json_error( true, ErrorReason::InvalidStartOfValue, parse_state );
842 }
843 }
844
845 template<typename Result, typename TypeList, std::size_t pos = 0,
846 typename ParseState>
847 DAW_ATTRIB_INLINE constexpr Result
848 parse_visit( std::size_t idx, ParseState &parse_state ) {
849 if( idx == pos ) {
850 using JsonMember = pack_element_t<pos, TypeList>;
851 if constexpr( std::is_same_v<json_result_t<JsonMember>, Result> ) {
852 return parse_value<JsonMember, false, JsonMember::expected_type>(
853 parse_state );
854 } else {
855 return Result{
856 parse_value<JsonMember, false, JsonMember::expected_type>(
857 parse_state ) };
858 }
859 }
860 if constexpr( pos + 1 < pack_size_v<TypeList> ) {
861 return parse_visit<Result, TypeList, pos + 1>( idx, parse_state );
862 } else {
863 if constexpr( ParseState::is_unchecked_input ) {
864 DAW_UNREACHABLE( );
865 } else {
867 true, ErrorReason::MissingMemberNameOrEndOfClass, parse_state );
868 }
869 }
870 }
871
872 template<typename JsonMember, typename ParseState>
873 [[nodiscard]] constexpr auto find_index( ParseState const &parse_state ) {
874 using tag_member = typename JsonMember::tag_member;
875 using class_wrapper_t = typename JsonMember::tag_member_class_wrapper;
876
877 using switcher_t = typename JsonMember::switcher;
878 auto parse_state2 = ParseState( parse_state.class_first,
879 parse_state.class_last,
880 parse_state.class_first,
881 parse_state.class_last );
882 if constexpr( is_an_ordered_member_v<tag_member> ) {
883 // This is an ordered class, class must start with '['
884 daw_json_assert_weak( parse_state2.is_opening_bracket_checked( ),
885 ErrorReason::InvalidArrayStart,
886 parse_state );
887 return switcher_t{ }( std::get<0>(
888 parse_value<class_wrapper_t, false, class_wrapper_t::expected_type>(
889 parse_state2 ) ) );
890 } else {
891 // This is a regular class, class must start with '{'
892 daw_json_assert_weak( parse_state2.is_opening_brace_checked( ),
893 ErrorReason::InvalidClassStart,
894 parse_state );
895 return switcher_t{ }( std::get<0>(
896 parse_value<class_wrapper_t, false, class_wrapper_t::expected_type>(
897 parse_state2 )
898 .members ) );
899 }
900 }
901
902 template<typename JsonMember, typename ParseState>
903 [[nodiscard]] constexpr json_result_t<JsonMember>
904 parse_value_variant_tagged( ParseState &parse_state ) {
905 auto const index = find_index<JsonMember>( parse_state );
906 return parse_visit<json_result_t<JsonMember>,
907 typename JsonMember::json_elements::element_map_t>(
908 index, parse_state );
909 }
910
911 template<typename JsonMember, typename ParseState>
912 [[nodiscard]] constexpr json_result_t<JsonMember>
913 parse_value_variant_intrusive( ParseState &parse_state ) {
914 auto const index = [&] {
915 using tag_submember = typename JsonMember::tag_submember;
916 using class_wrapper_t =
917 typename JsonMember::tag_submember_class_wrapper;
918 auto parse_state2 = parse_state;
919 using switcher_t = typename JsonMember::switcher;
920 if constexpr( is_an_ordered_member_v<tag_submember> ) {
921 return switcher_t{ }( std::get<0>(
922 parse_value<class_wrapper_t,
923 false,
924 class_wrapper_t::expected_type>( parse_state2 ) ) );
925 } else {
926 return switcher_t{ }( std::get<0>(
927 parse_value<class_wrapper_t,
928 false,
929 class_wrapper_t::expected_type>( parse_state2 )
930 .members ) );
931 }
932 }( );
933
934 return parse_visit<json_result_t<JsonMember>,
935 typename JsonMember::json_elements::element_map_t>(
936 index, parse_state );
937 }
938
939 template<bool AllMembersMustExist, typename ParseState,
940 typename OldClassPos>
941 DAW_ATTRIB_INLINE constexpr void ordered_class_cleanup(
942 ParseState &parse_state,
943 OldClassPos const
944 &old_class_pos ) noexcept( not use_daw_json_exceptions_v ) {
945 if constexpr( AllMembersMustExist ) {
946 parse_state.trim_left( );
947 daw_json_assert_weak( parse_state.front( ) == ']',
948 ErrorReason::UnknownMember,
949 parse_state );
950 parse_state.remove_prefix( );
951 parse_state.trim_left_checked( );
952 } else {
953 (void)parse_state.skip_array( );
954 }
955 parse_state.set_class_position( old_class_pos );
956 }
957
958 namespace pocm_details {
959 /***
960 * Maybe skip json members
961 * @tparam ParseState see IteratorRange
962 * @param parse_state JSON data
963 * @param current_position current member index
964 * @param desired_position desired member index
965 */
966 template<bool Nullable, typename ParseState>
967 constexpr void maybe_skip_members( ParseState &parse_state,
968 std::size_t &current_position,
969 std::size_t desired_position ) {
970
971 daw_json_assert_weak( current_position <= desired_position,
972 ErrorReason::OutOfOrderOrderedMembers,
973 parse_state );
974 using skip_check_end =
975 std::bool_constant<( ParseState::is_unchecked_input and Nullable )>;
976 while( ( current_position < desired_position ) &
977 ( skip_check_end::value or parse_state.front( ) != ']' ) ) {
978 (void)skip_value( parse_state );
979 parse_state.move_next_member_or_end( );
980 ++current_position;
981 daw_json_assert_weak( parse_state.has_more( ),
982 ErrorReason::UnexpectedEndOfData,
983 parse_state );
984 }
985 }
986
987#if defined( DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002 )
988 template<typename ParseState>
989 struct position_info {
990 std::size_t index;
991 ParseState state{ };
992
993 constexpr explicit operator bool( ) const {
994 return not state.is_null( );
995 }
996 };
997
998 /***
999 * Maybe skip json members
1000 * @tparam ParseState see IteratorRange
1001 * @param parse_state JSON data
1002 * @param current_position current member index
1003 * @param desired_position desired member index
1004 */
1005 template<bool Nullable, typename ParseState, std::size_t N>
1006 DAW_ATTRIB_INLINE static constexpr ParseState maybe_skip_members(
1007 ParseState &parse_state, std::size_t &current_position,
1008 std::size_t desired_position,
1009 std::array<position_info<ParseState>, N> &parse_locations ) {
1010
1011 auto const desired = daw::algorithm::find_if(
1012 std::data( parse_locations ),
1013 daw::data_end( parse_locations ),
1014 [desired_position]( position_info<ParseState> const &loc ) {
1015 return loc.index == desired_position;
1016 } );
1017 if( *desired ) {
1018 return desired->state;
1019 }
1020#if not defined( NDEBUG )
1021 daw_json_ensure( desired != daw::data_end( parse_locations ),
1022 ErrorReason::UnexpectedEndOfData,
1023 parse_state );
1024#endif
1025 using skip_check_end =
1026 std::bool_constant<( ParseState::is_unchecked_input and Nullable )>;
1027 while( ( current_position < desired_position ) &
1028 ( skip_check_end::value or parse_state.front( ) != ']' ) ) {
1029 auto const current = daw::algorithm::find_if(
1030 std::data( parse_locations ),
1031 daw::data_end( parse_locations ),
1032 [current_position]( position_info<ParseState> const &loc ) {
1033 return loc.index == current_position;
1034 } );
1035 auto state = skip_value( parse_state );
1036 if( current != daw::data_end( parse_locations ) ) {
1037 current->state = state;
1038 }
1039 parse_state.move_next_member_or_end( );
1040 ++current_position;
1041 daw_json_assert_weak( parse_state.has_more( ),
1042 ErrorReason::UnexpectedEndOfData,
1043 parse_state );
1044 }
1045 return parse_state;
1046 }
1047#endif
1048 DAW_JSON_MAKE_REQ_TRAIT( has_member_index_v, T::member_index );
1049
1050 template<typename T>
1051 struct member_index_t {
1052 static constexpr std::size_t value = T::member_index;
1053 };
1054
1055 template<typename Idx, typename JsonMember>
1056 inline constexpr std::size_t member_index_v =
1057 daw::conditional_t<has_member_index_v<JsonMember>,
1058 member_index_t<JsonMember>, Idx>::value;
1059 } // namespace pocm_details
1060
1061 template<typename JsonMember, bool KnownBounds, typename ParseState,
1062 std::size_t... Is>
1063 DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
1064 parse_tuple_value( ParseState &parse_state, std::index_sequence<Is...> ) {
1065 parse_state.trim_left( );
1066 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
1067 ErrorReason::InvalidArrayStart,
1068 parse_state );
1069
1070 auto const old_class_pos = parse_state.get_class_position( );
1071 parse_state.set_class_position( );
1072 parse_state.remove_prefix( );
1073 parse_state.move_next_member_or_end( );
1074 using tuple_t = json_base_type_t<JsonMember>;
1075 using tuple_members = typename JsonMember::sub_member_list;
1076
1077#if defined( DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002 )
1078 using position_info_t = pocm_details::position_info<ParseState>;
1079 std::size_t parse_locations_last_index = 0U;
1080 std::array<position_info_t, sizeof...( Is )> parse_locations{
1081 [&]( auto Index ) mutable -> position_info_t {
1082 constexpr std::size_t index = decltype( Index )::value;
1083 using member_t = std::tuple_element_t<index, tuple_members>;
1084 if constexpr( is_an_ordered_member_v<member_t> ) {
1085 parse_locations_last_index = member_t::member_index;
1086 return { member_t::member_index };
1087 } else {
1088 return { parse_locations_last_index++ };
1089 }
1090 }(daw::constant_v<Is>)... };
1091#endif
1092 auto const parse_value_help = [&]( auto PackIdx,
1093 std::size_t &ClassIdx ) {
1094 using index_t = decltype( PackIdx );
1095 using CurrentMember =
1096 std::tuple_element_t<index_t::value, tuple_members>;
1097
1098 using json_member_t = ordered_member_subtype_t<CurrentMember>;
1099
1100#if defined( DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002 )
1101 ParseState parse_state2 =
1102 pocm_details::maybe_skip_members<is_json_nullable_v<json_member_t>>(
1103 parse_state,
1104 ClassIdx, /*index_t::value*/
1105 pocm_details::member_index_v<index_t, CurrentMember>,
1106 parse_locations );
1107 if constexpr( sizeof...( Is ) > 1 ) {
1108 ++ClassIdx;
1109 if( parse_state2.first == parse_state.first ) {
1110 if constexpr( is_pinned_type_v<json_result_t<JsonMember>> ) {
1111 auto const run_after_parse = daw::on_exit_success( [&] {
1112 parse_state.move_next_member_or_end( );
1113 } );
1114 (void)run_after_parse;
1115 return parse_value<json_member_t,
1116 false,
1117 json_member_t::expected_type>( parse_state );
1118 } else {
1119 auto result =
1120 parse_value<json_member_t,
1121 false,
1122 json_member_t::expected_type>( parse_state );
1123 parse_state.move_next_member_or_end( );
1124 return result;
1125 }
1126 } else {
1127 // Known Bounds
1128 return parse_value<json_member_t,
1129 true,
1130 json_member_t::expected_type>( parse_state2 );
1131 }
1132 } else {
1133#endif
1134 if constexpr( is_an_ordered_member_v<CurrentMember> ) {
1135 pocm_details::maybe_skip_members<
1136 is_json_nullable_v<json_member_t>>(
1137 parse_state, ClassIdx, CurrentMember::member_index );
1138 } else {
1139 daw_json_assert_weak( parse_state.has_more( ),
1140 ErrorReason::UnexpectedEndOfData,
1141 parse_state );
1142 }
1143 ++ClassIdx;
1144 if constexpr( is_pinned_type_v<json_result_t<JsonMember>> ) {
1145 auto const run_after_parse = daw::on_exit_success( [&] {
1146 parse_state.move_next_member_or_end( );
1147 } );
1148 (void)run_after_parse;
1149 return parse_value<json_member_t,
1150 false,
1151 json_member_t::expected_type>( parse_state );
1152 } else {
1153 auto result =
1154 parse_value<json_member_t, false, json_member_t::expected_type>(
1155 parse_state );
1156 parse_state.move_next_member_or_end( );
1157 return result;
1158 }
1159#if defined( DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002 )
1160 }
1161#endif
1162 };
1163
1164 static_assert( is_a_json_type_v<JsonMember> );
1165 using Constructor = json_constructor_t<JsonMember>;
1166
1167 parse_state.trim_left( );
1168
1169 std::size_t class_idx = 0;
1170 if constexpr( is_pinned_type_v<json_result_t<JsonMember>> ) {
1171 auto const run_after_parse = daw::on_exit_success( [&] {
1172 ordered_class_cleanup<
1173 all_json_members_must_exist_v<JsonMember, ParseState>,
1174 ParseState,
1175 decltype( old_class_pos )>( parse_state, old_class_pos );
1176 } );
1177 (void)run_after_parse;
1178 if constexpr( should_construct_explicitly_v<Constructor,
1179 tuple_t,
1180 ParseState> ) {
1181 return tuple_t{
1182 parse_value_help( daw::constant_v<Is>, class_idx )... };
1183 } else {
1184 return construct_value_tp<tuple_t, Constructor>(
1185 parse_state,
1186 fwd_pack{
1187 parse_value_help( daw::constant_v<Is>, class_idx )... } );
1188 }
1189 } else {
1190 auto result = [&] {
1191 if constexpr( should_construct_explicitly_v<Constructor,
1192 tuple_t,
1193 ParseState> ) {
1194 return tuple_t{
1195 parse_value_help( daw::constant_v<Is>, class_idx )... };
1196 } else {
1197 return construct_value_tp<tuple_t, Constructor>(
1198 parse_state,
1199 fwd_pack{
1200 parse_value_help( daw::constant_v<Is>, class_idx )... } );
1201 }
1202 }( );
1203 if constexpr( all_json_members_must_exist_v<tuple_t, ParseState> ) {
1204 parse_state.trim_left( );
1205 daw_json_assert_weak( parse_state.front( ) == ']',
1206 ErrorReason::UnknownMember,
1207 parse_state );
1208 parse_state.remove_prefix( );
1209 parse_state.trim_left( );
1210 } else {
1211 (void)parse_state.skip_array( );
1212 }
1213 parse_state.set_class_position( old_class_pos );
1214 return result;
1215 }
1216 }
1217
1218 template<typename JsonMember, bool KnownBounds, typename ParseState>
1219 static constexpr json_result_t<JsonMember>
1220 parse_value_tuple( ParseState &parse_state ) {
1221 using element_pack =
1222 typename JsonMember::sub_member_list; // tuple_elements_pack<tuple_t>;
1223
1224 return parse_tuple_value<JsonMember, KnownBounds>(
1225 parse_state,
1226 std::make_index_sequence<std::tuple_size_v<element_pack>>{ } );
1227 }
1228
1229 template<typename JsonMember, bool KnownBounds, typename ParseState>
1230 DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
1231 parse_value_unknown( ParseState &parse_state ) {
1232 using constructor_t = json_constructor_t<JsonMember>;
1233 if constexpr( KnownBounds ) {
1234 return construct_value<json_result_t<JsonMember>, constructor_t>(
1235 parse_state, std::data( parse_state ), std::size( parse_state ) );
1236 } else {
1237 auto value_parse_state = skip_value<true>( parse_state );
1238 return construct_value<json_result_t<JsonMember>, constructor_t>(
1239 parse_state,
1240 std::data( value_parse_state ),
1241 std::size( value_parse_state ) );
1242 }
1243 }
1244
1245 template<typename JsonMember, bool KnownBounds, JsonParseTypes PTag,
1246 typename ParseState>
1247 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_result_t<JsonMember>
1248 parse_value( ParseState &parse_state ) {
1249 if constexpr( PTag == JsonParseTypes::Real ) {
1250 return parse_value_real<JsonMember, KnownBounds>( parse_state );
1251 } else if constexpr( PTag == JsonParseTypes::Signed ) {
1252 return parse_value_signed<JsonMember, KnownBounds>( parse_state );
1253 } else if constexpr( PTag == JsonParseTypes::Unsigned ) {
1254 return parse_value_unsigned<JsonMember, KnownBounds>( parse_state );
1255 } else if constexpr( PTag == JsonParseTypes::Null ) {
1256 return parse_value_null<JsonMember, KnownBounds>( parse_state );
1257 } else if constexpr( PTag == JsonParseTypes::Bool ) {
1258 return parse_value_bool<JsonMember, KnownBounds>( parse_state );
1259 } else if constexpr( PTag == JsonParseTypes::StringRaw ) {
1260 return parse_value_string_raw<JsonMember, KnownBounds>( parse_state );
1261 } else if constexpr( PTag == JsonParseTypes::StringEscaped ) {
1262 return parse_value_string_escaped<JsonMember, KnownBounds>(
1263 parse_state );
1264 } else if constexpr( PTag == JsonParseTypes::Date ) {
1265 return parse_value_date<JsonMember, KnownBounds>( parse_state );
1266 } else if constexpr( PTag == JsonParseTypes::Custom ) {
1267 return parse_value_custom<JsonMember, KnownBounds>( parse_state );
1268 } else if constexpr( PTag == JsonParseTypes::Class ) {
1269 return parse_value_class<JsonMember, KnownBounds>( parse_state );
1270 } else if constexpr( PTag == JsonParseTypes::KeyValue ) {
1271 return parse_value_keyvalue<JsonMember, KnownBounds>( parse_state );
1272 } else if constexpr( PTag == JsonParseTypes::KeyValueArray ) {
1273 return parse_value_keyvalue_array<JsonMember, KnownBounds>(
1274 parse_state );
1275 } else if constexpr( PTag == JsonParseTypes::Array ) {
1276 return parse_value_array<JsonMember, KnownBounds>( parse_state );
1277 } else if constexpr( PTag == JsonParseTypes::SizedArray ) {
1278 return parse_value_sz_array<JsonMember, KnownBounds>( parse_state );
1279 } else if constexpr( PTag == JsonParseTypes::Variant ) {
1280 return parse_value_variant<JsonMember, KnownBounds>( parse_state );
1281 } else if constexpr( PTag == JsonParseTypes::VariantTagged ) {
1282 return parse_value_variant_tagged<JsonMember>( parse_state );
1283 } else if constexpr( PTag == JsonParseTypes::VariantIntrusive ) {
1284 return parse_value_variant_intrusive<JsonMember>( parse_state );
1285 } else if constexpr( PTag == JsonParseTypes::Tuple ) {
1286 return parse_value_tuple<JsonMember, KnownBounds>( parse_state );
1287#if defined( DAW_JSON_HAS_REFLECTION )
1288 } else if constexpr( PTag == JsonParseTypes::ReflectedClass ) {
1289 return parse_value_reflected_class<JsonMember, KnownBounds>(
1290 parse_state );
1291#endif
1292 } else /*if constexpr( PTag == JsonParseTypes::Unknown )*/ {
1293 static_assert( PTag == JsonParseTypes::Unknown,
1294 "Unexpected JsonParseType" );
1295 return parse_value_unknown<JsonMember, KnownBounds>( parse_state );
1296 }
1297 }
1298
1299 template<std::size_t N, typename JsonClass, bool KnownBounds,
1300 typename... JsonClasses, typename ParseState>
1301 DAW_ATTRIB_INLINE constexpr json_result_t<JsonClass>
1302 parse_nth_class( std::size_t idx, ParseState &parse_state ) {
1303 // Precondition of caller to verify/ensure.
1304 DAW_ASSUME( idx < sizeof...( JsonClasses ) );
1305 using T = json_base_type_t<JsonClass>;
1306 using Constructor = json_constructor_t<JsonClass>;
1307 if constexpr( sizeof...( JsonClasses ) >= N + 8 ) {
1308 switch( idx ) {
1309 case N + 0: {
1310 using cur_json_class_t =
1311 daw::traits::nth_element<N + 0, JsonClasses...>;
1312 return construct_value<T, Constructor>(
1313 parse_state,
1314 parse_value<cur_json_class_t,
1315 false,
1316 cur_json_class_t::expected_type>( parse_state ) );
1317 }
1318 case N + 1: {
1319 using cur_json_class_t =
1320 daw::traits::nth_element<N + 1, JsonClasses...>;
1321 return construct_value<T, Constructor>(
1322 parse_state,
1323 parse_value<cur_json_class_t,
1324 false,
1325 cur_json_class_t::expected_type>( parse_state ) );
1326 }
1327 case N + 2: {
1328 using cur_json_class_t =
1329 daw::traits::nth_element<N + 2, JsonClasses...>;
1330 return construct_value<T, Constructor>(
1331 parse_state,
1332 parse_value<cur_json_class_t,
1333 false,
1334 cur_json_class_t::expected_type>( parse_state ) );
1335 }
1336 case N + 3: {
1337 using cur_json_class_t =
1338 daw::traits::nth_element<N + 3, JsonClasses...>;
1339 return construct_value<T, Constructor>(
1340 parse_state,
1341 parse_value<cur_json_class_t,
1342 false,
1343 cur_json_class_t::expected_type>( parse_state ) );
1344 }
1345 case N + 4: {
1346 using cur_json_class_t =
1347 daw::traits::nth_element<N + 4, JsonClasses...>;
1348 return construct_value<T, Constructor>(
1349 parse_state,
1350 parse_value<cur_json_class_t,
1351 false,
1352 cur_json_class_t::expected_type>( parse_state ) );
1353 }
1354 case N + 5: {
1355 using cur_json_class_t =
1356 daw::traits::nth_element<N + 5, JsonClasses...>;
1357 return construct_value<T, Constructor>(
1358 parse_state,
1359 parse_value<cur_json_class_t,
1360 false,
1361 cur_json_class_t::expected_type>( parse_state ) );
1362 }
1363 case N + 6: {
1364 using cur_json_class_t =
1365 daw::traits::nth_element<N + 6, JsonClasses...>;
1366 return construct_value<T, Constructor>(
1367 parse_state,
1368 parse_value<cur_json_class_t,
1369 false,
1370 cur_json_class_t::expected_type>( parse_state ) );
1371 }
1372 case N + 7: {
1373 using cur_json_class_t =
1374 daw::traits::nth_element<N + 7, JsonClasses...>;
1375 return construct_value<T, Constructor>(
1376 parse_state,
1377 parse_value<cur_json_class_t,
1378 false,
1379 cur_json_class_t::expected_type>( parse_state ) );
1380 }
1381 default:
1382 if constexpr( sizeof...( JsonClasses ) >= N + 8 ) {
1383 return parse_nth_class<N + 8,
1384 JsonClass,
1385 KnownBounds,
1386 JsonClasses...>( idx, parse_state );
1387 } else {
1388 DAW_UNREACHABLE( );
1389 }
1390 }
1391 } else if constexpr( sizeof...( JsonClasses ) == N + 7 ) {
1392 switch( idx ) {
1393 case N + 0: {
1394 using cur_json_class_t =
1395 daw::traits::nth_element<N + 0, JsonClasses...>;
1396 return construct_value<T, Constructor>(
1397 parse_state,
1398 parse_value<cur_json_class_t,
1399 false,
1400 cur_json_class_t::expected_type>( parse_state ) );
1401 }
1402 case N + 1: {
1403 using cur_json_class_t =
1404 daw::traits::nth_element<N + 1, JsonClasses...>;
1405 return construct_value<T, Constructor>(
1406 parse_state,
1407 parse_value<cur_json_class_t,
1408 false,
1409 cur_json_class_t::expected_type>( parse_state ) );
1410 }
1411 case N + 2: {
1412 using cur_json_class_t =
1413 daw::traits::nth_element<N + 2, JsonClasses...>;
1414 return construct_value<T, Constructor>(
1415 parse_state,
1416 parse_value<cur_json_class_t,
1417 false,
1418 cur_json_class_t::expected_type>( parse_state ) );
1419 }
1420 case N + 3: {
1421 using cur_json_class_t =
1422 daw::traits::nth_element<N + 3, JsonClasses...>;
1423 return construct_value<T, Constructor>(
1424 parse_state,
1425 parse_value<cur_json_class_t,
1426 false,
1427 cur_json_class_t::expected_type>( parse_state ) );
1428 }
1429 case N + 4: {
1430 using cur_json_class_t =
1431 daw::traits::nth_element<N + 4, JsonClasses...>;
1432 return construct_value<T, Constructor>(
1433 parse_state,
1434 parse_value<cur_json_class_t,
1435 false,
1436 cur_json_class_t::expected_type>( parse_state ) );
1437 }
1438 case N + 5: {
1439 using cur_json_class_t =
1440 daw::traits::nth_element<N + 5, JsonClasses...>;
1441 return construct_value<T, Constructor>(
1442 parse_state,
1443 parse_value<cur_json_class_t,
1444 false,
1445 cur_json_class_t::expected_type>( parse_state ) );
1446 }
1447 default: {
1448 DAW_ASSUME( idx == N + 6 );
1449 using cur_json_class_t =
1450 daw::traits::nth_element<N + 6, JsonClasses...>;
1451 return construct_value<T, Constructor>(
1452 parse_state,
1453 parse_value<cur_json_class_t,
1454 false,
1455 cur_json_class_t::expected_type>( parse_state ) );
1456 }
1457 }
1458 } else if constexpr( sizeof...( JsonClasses ) == N + 6 ) {
1459 switch( idx ) {
1460 case N + 0: {
1461 using cur_json_class_t =
1462 daw::traits::nth_element<N + 0, JsonClasses...>;
1463 return construct_value<T, Constructor>(
1464 parse_state,
1465 parse_value<cur_json_class_t,
1466 false,
1467 cur_json_class_t::expected_type>( parse_state ) );
1468 }
1469 case N + 1: {
1470 using cur_json_class_t =
1471 daw::traits::nth_element<N + 1, JsonClasses...>;
1472 return construct_value<T, Constructor>(
1473 parse_state,
1474 parse_value<cur_json_class_t,
1475 false,
1476 cur_json_class_t::expected_type>( parse_state ) );
1477 }
1478 case N + 2: {
1479 using cur_json_class_t =
1480 daw::traits::nth_element<N + 2, JsonClasses...>;
1481 return construct_value<T, Constructor>(
1482 parse_state,
1483 parse_value<cur_json_class_t,
1484 false,
1485 cur_json_class_t::expected_type>( parse_state ) );
1486 }
1487 case N + 3: {
1488 using cur_json_class_t =
1489 daw::traits::nth_element<N + 3, JsonClasses...>;
1490 return construct_value<T, Constructor>(
1491 parse_state,
1492 parse_value<cur_json_class_t,
1493 false,
1494 cur_json_class_t::expected_type>( parse_state ) );
1495 }
1496 case N + 4: {
1497 using cur_json_class_t =
1498 daw::traits::nth_element<N + 4, JsonClasses...>;
1499 return construct_value<T, Constructor>(
1500 parse_state,
1501 parse_value<cur_json_class_t,
1502 false,
1503 cur_json_class_t::expected_type>( parse_state ) );
1504 }
1505 default: {
1506 DAW_ASSUME( idx == N + 5 );
1507 using cur_json_class_t =
1508 daw::traits::nth_element<N + 5, JsonClasses...>;
1509 return construct_value<T, Constructor>(
1510 parse_state,
1511 parse_value<cur_json_class_t,
1512 false,
1513 cur_json_class_t::expected_type>( parse_state ) );
1514 }
1515 }
1516 } else if constexpr( sizeof...( JsonClasses ) == N + 5 ) {
1517 switch( idx ) {
1518 case N + 0: {
1519 using cur_json_class_t =
1520 daw::traits::nth_element<N + 0, JsonClasses...>;
1521 return construct_value<T, Constructor>(
1522 parse_state,
1523 parse_value<cur_json_class_t,
1524 false,
1525 cur_json_class_t::expected_type>( parse_state ) );
1526 }
1527 case N + 1: {
1528 using cur_json_class_t =
1529 daw::traits::nth_element<N + 1, JsonClasses...>;
1530 return construct_value<T, Constructor>(
1531 parse_state,
1532 parse_value<cur_json_class_t,
1533 false,
1534 cur_json_class_t::expected_type>( parse_state ) );
1535 }
1536 case N + 2: {
1537 using cur_json_class_t =
1538 daw::traits::nth_element<N + 2, JsonClasses...>;
1539 return construct_value<T, Constructor>(
1540 parse_state,
1541 parse_value<cur_json_class_t,
1542 false,
1543 cur_json_class_t::expected_type>( parse_state ) );
1544 }
1545 case N + 3: {
1546 using cur_json_class_t =
1547 daw::traits::nth_element<N + 3, JsonClasses...>;
1548 return construct_value<T, Constructor>(
1549 parse_state,
1550 parse_value<cur_json_class_t,
1551 false,
1552 cur_json_class_t::expected_type>( parse_state ) );
1553 }
1554 default: {
1555 DAW_ASSUME( idx == N + 4 );
1556 using cur_json_class_t =
1557 daw::traits::nth_element<N + 4, JsonClasses...>;
1558 return construct_value<T, Constructor>(
1559 parse_state,
1560 parse_value<cur_json_class_t,
1561 false,
1562 cur_json_class_t::expected_type>( parse_state ) );
1563 }
1564 }
1565 } else if constexpr( sizeof...( JsonClasses ) == N + 4 ) {
1566 switch( idx ) {
1567 case N + 0: {
1568 using cur_json_class_t =
1569 daw::traits::nth_element<N + 0, JsonClasses...>;
1570 return construct_value<T, Constructor>(
1571 parse_state,
1572 parse_value<cur_json_class_t,
1573 false,
1574 cur_json_class_t::expected_type>( parse_state ) );
1575 }
1576 case N + 1: {
1577 using cur_json_class_t =
1578 daw::traits::nth_element<N + 1, JsonClasses...>;
1579 return construct_value<T, Constructor>(
1580 parse_state,
1581 parse_value<cur_json_class_t,
1582 false,
1583 cur_json_class_t::expected_type>( parse_state ) );
1584 }
1585 case N + 2: {
1586 using cur_json_class_t =
1587 daw::traits::nth_element<N + 2, JsonClasses...>;
1588 return construct_value<T, Constructor>(
1589 parse_state,
1590 parse_value<cur_json_class_t,
1591 false,
1592 cur_json_class_t::expected_type>( parse_state ) );
1593 }
1594 default: {
1595 DAW_ASSUME( idx == N + 3 );
1596 using cur_json_class_t =
1597 daw::traits::nth_element<N + 3, JsonClasses...>;
1598 return construct_value<T, Constructor>(
1599 parse_state,
1600 parse_value<cur_json_class_t,
1601 false,
1602 cur_json_class_t::expected_type>( parse_state ) );
1603 }
1604 }
1605 } else if constexpr( sizeof...( JsonClasses ) == N + 3 ) {
1606 switch( idx ) {
1607 case N + 0: {
1608 using cur_json_class_t =
1609 daw::traits::nth_element<N + 0, JsonClasses...>;
1610 return construct_value<T, Constructor>(
1611 parse_state,
1612 parse_value<cur_json_class_t,
1613 false,
1614 cur_json_class_t::expected_type>( parse_state ) );
1615 }
1616 case N + 1: {
1617 using cur_json_class_t =
1618 daw::traits::nth_element<N + 1, JsonClasses...>;
1619 return construct_value<T, Constructor>(
1620 parse_state,
1621 parse_value<cur_json_class_t,
1622 false,
1623 cur_json_class_t::expected_type>( parse_state ) );
1624 }
1625 default: {
1626 DAW_ASSUME( idx == N + 2 );
1627 using cur_json_class_t =
1628 daw::traits::nth_element<N + 2, JsonClasses...>;
1629 return construct_value<T, Constructor>(
1630 parse_state,
1631 parse_value<cur_json_class_t,
1632 false,
1633 cur_json_class_t::expected_type>( parse_state ) );
1634 }
1635 }
1636 } else if constexpr( sizeof...( JsonClasses ) == N + 2 ) {
1637 if( idx == N ) {
1638 using cur_json_class_t =
1639 daw::traits::nth_element<N + 0, JsonClasses...>;
1640 return construct_value<T, Constructor>(
1641 parse_state,
1642 parse_value<cur_json_class_t,
1643 false,
1644 cur_json_class_t::expected_type>( parse_state ) );
1645 }
1646 using cur_json_class_t =
1647 daw::traits::nth_element<N + 1, JsonClasses...>;
1648 return construct_value<T, Constructor>(
1649 parse_state,
1650 parse_value<cur_json_class_t,
1651 false,
1652 cur_json_class_t::expected_type>( parse_state ) );
1653 } else {
1654 using cur_json_class_t =
1655 daw::traits::nth_element<N + 0, JsonClasses...>;
1656 return construct_value<T, Constructor>(
1657 parse_state,
1658 parse_value<cur_json_class_t,
1659 false,
1660 cur_json_class_t::expected_type>( parse_state ) );
1661 }
1662 }
1663 } // namespace json_details
1664 } // namespace DAW_JSON_VER
1665} // namespace daw::json
#define daw_json_assert_weak(Bool,...)
Assert that Bool is true when in Checked Input mode If false pass rest of args to daw_json_error.
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
#define DAW_JSON_MAKE_REQ_TRAIT(Name,...)
#define DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT_NT(Name,...)
DAW_ATTRIB_NOINLINE void daw_json_error(bool b, ErrorReason reason)
typename json_data_contract< T >::type json_data_contract_trait_t
This trait gets us the mapping type from the contract.
JsonParseTypes
The tags used by the parser to determine what parser to call.
Customization point traits.
constexpr bool use_daw_json_exceptions_v
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20