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