DAW JSON Link
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 
42 namespace 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>(
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>(
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.
constexpr bool is_pinned_type_v
Is the type pinned in memory and unable to be copied/moved after construction(e.g....
std::bool_constant< is_zero_terminated_string_v< T > > is_zero_terminated_string
LiteralAsStringOpt
Controls the ability to parse numbers that are encoded as strings.
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:25