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