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