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