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