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