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 "daw_json_assert.h"
15 #include "daw_json_parse_name.h"
16 #include "daw_json_parse_real.h"
22 
23 #include <ciso646>
24 #include <cstddef>
25 #include <cstdint>
26 #include <iterator>
27 #include <tuple>
28 
29 namespace daw::json::json_details {
30  template<LiteralAsStringOpt literal_as_string, bool KnownBounds = false,
31  typename Range>
32  DAW_ATTRIBUTE_FLATTEN inline constexpr void
33  skip_quote_when_literal_as_string( Range &rng ) {
34  if constexpr( literal_as_string == LiteralAsStringOpt::Always ) {
35  daw_json_assert_weak( rng.is_quotes_checked( ),
36  ErrorReason::InvalidNumberUnexpectedQuoting, rng );
37  rng.remove_prefix( );
38  if constexpr( KnownBounds ) {
39  rng.last = std::prev( rng.last );
40  }
41  } else if constexpr( literal_as_string == LiteralAsStringOpt::Maybe ) {
42  daw_json_assert_weak( rng.has_more( ), ErrorReason::UnexpectedEndOfData,
43  rng );
44  if( rng.front( ) == '"' ) {
45  rng.remove_prefix( );
46  if constexpr( KnownBounds ) {
47  rng.last = std::prev( rng.last );
48  }
49  }
50  }
51  }
52 
53  template<typename JsonMember, bool KnownBounds, typename Range>
54  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
55  parse_value( ParseTag<JsonParseTypes::Real>, Range &rng ) {
56  using constructor_t = typename JsonMember::constructor_t;
57  using element_t = typename JsonMember::base_type;
58 
59  if constexpr( KnownBounds ) {
60  return construct_value<json_result<JsonMember>>(
61  constructor_t{ }, rng, parse_real<element_t, true>( rng ) );
62  } else {
63  daw_json_assert_weak( rng.has_more( ), ErrorReason::UnexpectedEndOfData,
64  rng );
65  if constexpr( JsonMember::literal_as_string !=
66  LiteralAsStringOpt::Never ) {
67  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
68  }
70  parse_policy_details::is_number_start( rng.front( ) ),
71  ErrorReason::InvalidNumberStart, rng );
72 
73  // TODO allow for guaranteed copy elision
74  auto result = construct_value<json_result<JsonMember>>(
75  constructor_t{ }, rng, parse_real<element_t, false>( rng ) );
76  if constexpr( JsonMember::literal_as_string !=
77  LiteralAsStringOpt::Never ) {
78  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
79  }
81  parse_policy_details::at_end_of_item( rng.front( ) ),
82  ErrorReason::InvalidEndOfValue, rng );
83  return result;
84  }
85  }
86 
87  template<typename JsonMember, bool KnownBounds, typename Range>
88  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
89  parse_value( ParseTag<JsonParseTypes::Signed>, Range &rng ) {
90  using constructor_t = typename JsonMember::constructor_t;
91  using element_t = typename JsonMember::base_type;
92  static_assert( daw::is_signed_v<element_t>, "Expected signed type" );
93  if constexpr( KnownBounds ) {
95  parse_policy_details::is_number_start( rng.front( ) ),
96  ErrorReason::InvalidNumberStart, rng );
97  } else {
98  daw_json_assert_weak( rng.has_more( ), ErrorReason::UnexpectedEndOfData,
99  rng );
100  if constexpr( JsonMember::literal_as_string !=
101  LiteralAsStringOpt::Never ) {
102  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
103  }
105  parse_policy_details::is_number_start( rng.front( ) ),
106  ErrorReason::InvalidNumberStart, rng );
107  }
108  element_t sign = 1;
109  if( rng.front( ) == '-' ) {
110  rng.remove_prefix( );
111  sign = -1;
112  }
113 
114  if constexpr( KnownBounds ) {
115 
116  return construct_value<json_result<JsonMember>>(
117  constructor_t{ }, rng,
118  sign * unsigned_parser<element_t, JsonMember::range_check, KnownBounds>(
119  Range::exec_tag, rng ) );
120  } else {
121  auto result = construct_value<json_result<JsonMember>>(
122  constructor_t{ }, rng,
123  sign * unsigned_parser<element_t, JsonMember::range_check, KnownBounds>(
124  Range::exec_tag, rng ) );
125  if constexpr( JsonMember::literal_as_string !=
126  LiteralAsStringOpt::Never ) {
127  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
128  }
129  rng.trim_left( );
131  parse_policy_details::at_end_of_item( rng.front( ) ),
132  ErrorReason::InvalidEndOfValue, rng );
133  return result;
134  }
135  }
136 
137  template<typename JsonMember, bool KnownBounds, typename Range>
138  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
139  parse_value( ParseTag<JsonParseTypes::Unsigned>, Range &rng ) {
140  using constructor_t = typename JsonMember::constructor_t;
141  using element_t = typename JsonMember::base_type;
142 
143  if constexpr( KnownBounds ) {
144  if constexpr( JsonMember::literal_as_string !=
145  LiteralAsStringOpt::Never ) {
146  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
147  }
149  ErrorReason::InvalidNumber, rng );
150  return construct_value<json_result<JsonMember>>(
151  constructor_t{ }, rng,
152  unsigned_parser<element_t, JsonMember::range_check, KnownBounds>(
153  Range::exec_tag, rng ) );
154  } else {
155  daw_json_assert_weak( rng.has_more( ), ErrorReason::UnexpectedEndOfData,
156  rng );
157  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
159  ErrorReason::InvalidNumber, rng );
160  auto result = construct_value<json_result<JsonMember>>(
161  constructor_t{ }, rng,
162  unsigned_parser<element_t, JsonMember::range_check, KnownBounds>(
163  Range::exec_tag, rng ) );
164  if constexpr( JsonMember::literal_as_string !=
165  LiteralAsStringOpt::Never ) {
166  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
167  }
169  parse_policy_details::at_end_of_item( rng.front( ) ),
170  ErrorReason::InvalidEndOfValue, rng );
171  return result;
172  }
173  }
174 
175  template<typename JsonMember, bool KnownBounds, typename Range>
176  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
177  parse_value( ParseTag<JsonParseTypes::Null>, Range &rng ) {
178 
179  using constructor_t = typename JsonMember::constructor_t;
180  if constexpr( KnownBounds ) {
181  if( rng.is_null( ) ) {
182  return construct_value<json_result<JsonMember>>( constructor_t{ },
183  rng );
184  }
185  return parse_value<JsonMember, true>(
186  ParseTag<JsonMember::base_expected_type>{ }, rng );
187  } else if constexpr( Range::is_unchecked_input ) {
188  if( not rng.has_more( ) ) {
189  return construct_value<json_result<JsonMember>>( constructor_t{ },
190  rng );
191  } else if( rng.front( ) == 'n' ) {
192  rng.remove_prefix( 4 );
193  rng.trim_left_unchecked( );
194  rng.remove_prefix( );
195  return construct_value<json_result<JsonMember>>( constructor_t{ },
196  rng );
197  }
198  return parse_value<JsonMember>(
199  ParseTag<JsonMember::base_expected_type>{ }, rng );
200  } else {
201  if( rng.starts_with( "null" ) ) {
202  rng.remove_prefix( 4 );
204  parse_policy_details::at_end_of_item( rng.front( ) ),
205  ErrorReason::InvalidLiteral, rng );
206  rng.trim_left_checked( );
207  return construct_value<json_result<JsonMember>>( constructor_t{ },
208  rng );
209  }
210  return parse_value<JsonMember>(
211  ParseTag<JsonMember::base_expected_type>{ }, rng );
212  }
213  }
214 
215  template<typename JsonMember, bool KnownBounds, typename Range>
216  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
217  parse_value( ParseTag<JsonParseTypes::Bool>, Range &rng ) {
218  daw_json_assert_weak( rng.size( ) >= 4, ErrorReason::InvalidLiteral, rng );
219 
220  using constructor_t = typename JsonMember::constructor_t;
221 
222  if constexpr( KnownBounds ) {
223  // We have already checked if it is a true/false
224  if constexpr( Range::is_unchecked_input ) {
225  return rng.front( ) == 't';
226  } else {
227  switch( rng.front( ) ) {
228  case 't':
229  return construct_value<json_result<JsonMember>>( constructor_t{ },
230  rng, true );
231  case 'f':
232  return construct_value<json_result<JsonMember>>( constructor_t{ },
233  rng, false );
234  }
235  daw_json_error( ErrorReason::InvalidLiteral, rng );
236  }
237  } else {
238  if constexpr( JsonMember::literal_as_string !=
239  LiteralAsStringOpt::Never ) {
240  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
241  }
242  bool result = false;
243  if constexpr( Range::is_unchecked_input ) {
244  if( rng.front( ) == 't' ) /* true */ {
245  result = true;
246  rng.remove_prefix( 4 );
247  } else /* false */ {
248  rng.remove_prefix( 5 );
249  }
250  } else {
251  if( rng.starts_with( "true" ) ) {
252  rng.remove_prefix( 4 );
253  result = true;
254  } else if( rng.starts_with( "false" ) ) {
255  rng.remove_prefix( 5 );
256  } else {
257  daw_json_error( ErrorReason::InvalidLiteral, rng );
258  }
259  }
260  if constexpr( JsonMember::literal_as_string !=
261  LiteralAsStringOpt::Never ) {
262  skip_quote_when_literal_as_string<JsonMember::literal_as_string>( rng );
263  }
264  rng.trim_left( );
266  parse_policy_details::at_end_of_item( rng.front( ) ),
267  ErrorReason::InvalidEndOfValue, rng );
268  return construct_value<json_result<JsonMember>>( constructor_t{ }, rng,
269  result );
270  }
271  }
272 
273  template<typename JsonMember, bool KnownBounds, typename Range>
274  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
275  parse_value( ParseTag<JsonParseTypes::StringRaw>, Range &rng ) {
276 
277  using constructor_t = typename JsonMember::constructor_t;
278  if constexpr( KnownBounds ) {
279  if constexpr( JsonMember::empty_is_null == JsonNullable::Nullable ) {
280  if( rng.empty( ) ) {
281  return construct_value<json_result<JsonMember>>( constructor_t{ },
282  rng );
283  }
284  }
285  return construct_value<json_result<JsonMember>>( constructor_t{ }, rng,
286  rng.first, rng.size( ) );
287  } else {
288  if constexpr( JsonMember::allow_escape_character ==
289  AllowEscapeCharacter::Allow ) {
290  auto const str = skip_string( rng );
291  if constexpr( JsonMember::empty_is_null == JsonNullable::Nullable ) {
292  if( str.empty( ) ) {
293  return construct_value<json_result<JsonMember>>( constructor_t{ },
294  rng );
295  }
296  }
297  return construct_value<json_result<JsonMember>>(
298  constructor_t{ }, rng, str.first, str.size( ) );
299  } else {
300  rng.remove_prefix( );
301 
302  char const *const first = rng.first;
303  rng.template move_to_next_of<'"'>( );
304  char const *const last = rng.first;
305  rng.remove_prefix( );
306  if constexpr( JsonMember::empty_is_null == JsonNullable::Nullable ) {
307  if( first == last ) {
308  return construct_value<json_result<JsonMember>>( constructor_t{ },
309  rng );
310  }
311  return construct_value<json_result<JsonMember>>(
312  constructor_t{ }, rng, first,
313  static_cast<std::size_t>( last - first ) );
314  } else {
315  return construct_value<json_result<JsonMember>>(
316  constructor_t{ }, rng, first,
317  static_cast<std::size_t>( last - first ) );
318  }
319  }
320  }
321  }
322 
323  /***
324  * We know that we are constructing a std::string or
325  * std::optional<std::string> We can take advantage of this and reduce the
326  * allocator time by presizing the string up front and then using a
327  * pointer to the data( ).
328  */
329  template<typename JsonMember>
330  struct can_parse_to_stdstring_fast
331  : std::disjunction<
332  can_single_allocation_string<json_result<JsonMember>>,
333  can_single_allocation_string<json_base_type<JsonMember>>> {};
334 
335  template<typename JsonMember, bool KnownBounds, typename Range>
336  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
337  parse_value( ParseTag<JsonParseTypes::StringEscaped>, Range &rng ) {
338  using constructor_t = typename JsonMember::constructor_t;
339  if constexpr( can_parse_to_stdstring_fast<JsonMember>::value ) {
340  constexpr bool AllowHighEightbits =
341  JsonMember::eight_bit_mode != EightBitModes::DisallowHigh;
342  auto rng2 = KnownBounds ? rng : skip_string( rng );
343  // FIXME this needs std::string, fix
344  if( not AllowHighEightbits or needs_slow_path( rng2 ) ) {
345  // There are escapes in the string
346  return parse_string_known_stdstring<AllowHighEightbits, JsonMember,
347  true>( rng2 );
348  }
349  // There are no escapes in the string, we can just use the ptr/size ctor
350  return construct_value<json_result<JsonMember>>(
351  constructor_t{ }, rng, rng2.first,
352  rng2.first + static_cast<std::ptrdiff_t>( rng2.size( ) ) );
353  } else {
354  auto rng2 = KnownBounds ? rng : skip_string( rng );
355  constexpr bool AllowHighEightbits =
356  JsonMember::eight_bit_mode != EightBitModes::DisallowHigh;
357  if( not AllowHighEightbits or needs_slow_path( rng2 ) ) {
358  // There are escapes in the string
359  return parse_string_known_stdstring<AllowHighEightbits,
360  json_result<JsonMember>, true>(
361  rng2 );
362  }
363  // There are no escapes in the string, we can just use the ptr/size ctor
364  return construct_value<json_result<JsonMember>>(
365  constructor_t{ }, rng, rng2.first,
366  rng2.first + static_cast<std::ptrdiff_t>( rng2.size( ) ) );
367  }
368  }
369 
370  template<typename JsonMember, bool KnownBounds, typename Range>
371  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
372  parse_value( ParseTag<JsonParseTypes::Date>, Range &rng ) {
373 
374  daw_json_assert_weak( rng.has_more( ), ErrorReason::UnexpectedEndOfData,
375  rng );
376  auto str = skip_string( rng );
377  using constructor_t = typename JsonMember::constructor_t;
378  return construct_value<json_result<JsonMember>>( constructor_t{ }, rng,
379  str.first, str.size( ) );
380  }
381 
382  template<typename JsonMember, bool KnownBounds, typename Range>
383  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
384  parse_value( ParseTag<JsonParseTypes::Custom>, Range &rng ) {
385 
386  if( ( ( rng.front( ) != '"' ) & ( rng.class_first != nullptr ) ) &
387  ( ( rng.first > rng.class_first ) and
388  ( *std::prev( rng.first ) == '"' ) ) ) {
389  rng.first = std::prev( rng.first );
390  }
391  auto const str = skip_value( rng );
392 
393  using constructor_t = typename JsonMember::from_converter_t;
394  return construct_value<json_result<JsonMember>>(
395  constructor_t{ }, rng, std::string_view( str.first, str.size( ) ) );
396  }
397 
398  template<typename JsonMember, bool KnownBounds, typename Range>
399  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
400  parse_value( ParseTag<JsonParseTypes::Class>, Range &rng ) {
401 
402  using element_t = typename JsonMember::base_type;
403  daw_json_assert_weak( rng.has_more( ), ErrorReason::UnexpectedEndOfData,
404  rng );
405 
406  if constexpr( is_guaranteed_rvo_v<Range> ) {
407  // This relies on non-trivial dtor's being allowed. So C++20 constexpr or
408  // not in a constant expression. It does allow for construction of
409  // classes without move/copy special members
410  if constexpr( not KnownBounds ) {
411  auto const oe =
412  daw::on_exit_success( [&] { rng.trim_left_checked( ); } );
413  return json_data_contract_trait_t<element_t>::template parse_to_class<
414  element_t>( rng );
415  } else {
416  return json_data_contract_trait_t<element_t>::template parse_to_class<
417  element_t>( rng );
418  }
419  } else {
420  if constexpr( KnownBounds ) {
421  return json_data_contract_trait_t<element_t>::template parse_to_class<
422  element_t>( rng );
423  } else {
424  auto result = json_data_contract_trait_t<
425  element_t>::template parse_to_class<element_t>( rng );
426  // TODO: make trim_left
427  rng.trim_left_checked( );
428  return result;
429  }
430  }
431  }
432 
441  template<typename JsonMember, bool KnownBounds, typename Range>
442  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
443  parse_value( ParseTag<JsonParseTypes::KeyValue>, Range &rng ) {
444 
445  static_assert( JsonMember::expected_type == JsonParseTypes::KeyValue,
446  "Expected a json_key_value" );
447  daw_json_assert_weak( rng.is_opening_brace_checked( ),
448  ErrorReason::ExpectedKeyValueToStartWithBrace, rng );
449 
450  rng.remove_prefix( );
451  // We are inside a KV map, we can expected a quoted name next
452  rng.template move_to_next_of<'"'>( );
453 
454  using iter_t = json_parse_kv_class_iterator<JsonMember, Range, KnownBounds>;
455  using constructor_t = typename JsonMember::constructor_t;
456  return construct_value<json_result<JsonMember>>( constructor_t{ }, rng,
457  iter_t( rng ), iter_t( ) );
458  }
459 
468  template<typename JsonMember, bool KnownBounds, typename Range>
469  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
470  parse_value( ParseTag<JsonParseTypes::KeyValueArray>, Range &rng ) {
471 
472  static_assert( JsonMember::expected_type == JsonParseTypes::KeyValueArray,
473  "Expected a json_key_value" );
474  daw_json_assert_weak( rng.is_opening_bracket_checked( ),
475  ErrorReason::ExpectedKeyValueArrayToStartWithBracket,
476  rng );
477 
478  rng.remove_prefix( );
479 
480  using iter_t = json_parse_kv_array_iterator<JsonMember, Range, KnownBounds>;
481  using constructor_t = typename JsonMember::constructor_t;
482  return construct_value<json_result<JsonMember>>( constructor_t{ }, rng,
483  iter_t( rng ), iter_t( ) );
484  }
485 
486  template<typename JsonMember, bool KnownBounds, typename Range>
487  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
488  parse_value( ParseTag<JsonParseTypes::Array>, Range &rng ) {
489  rng.trim_left( );
490  daw_json_assert_weak( rng.is_opening_bracket_checked( ),
491  ErrorReason::InvalidArrayStart, rng );
492  rng.remove_prefix( );
493  rng.trim_left_unchecked( );
494 
495  using iterator_t =
496  json_parse_array_iterator<JsonMember, Range, KnownBounds>;
497  return construct_value<json_result<JsonMember>>(
498  typename JsonMember::constructor_t{ }, rng, iterator_t( rng ),
499  iterator_t( ) );
500  }
501 
502  template<JsonBaseParseTypes BPT, typename JsonMembers, typename Range>
503  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMembers>
504  parse_variant_value( Range &rng ) {
505 
506  using element_t = typename JsonMembers::json_elements;
507  constexpr std::size_t idx =
508  element_t::base_map[static_cast<int_fast8_t>( BPT )];
509 
510  if constexpr( idx < std::tuple_size_v<typename element_t::element_map_t> ) {
511  using JsonMember =
512  std::tuple_element_t<idx, typename element_t::element_map_t>;
513  return parse_value<JsonMember>(
514  ParseTag<JsonMember::base_expected_type>{ }, rng );
515  } else {
516  daw_json_error( ErrorReason::UnexpectedJSONVariantType );
517  }
518  }
519 
520  template<typename JsonMember, bool KnownBounds, typename Range>
521  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
522  parse_value( ParseTag<JsonParseTypes::Variant>, Range &rng ) {
523 
524  switch( rng.front( ) ) {
525  case '{':
526  return parse_variant_value<JsonBaseParseTypes::Class, JsonMember>( rng );
527  case '[':
528  return parse_variant_value<JsonBaseParseTypes::Array, JsonMember>( rng );
529  case 't':
530  case 'f':
531  return parse_variant_value<JsonBaseParseTypes::Bool, JsonMember>( rng );
532  case '"':
533  return parse_variant_value<JsonBaseParseTypes::String, JsonMember>( rng );
534  case '0':
535  case '1':
536  case '2':
537  case '3':
538  case '4':
539  case '5':
540  case '6':
541  case '7':
542  case '8':
543  case '9':
544  case '+':
545  case '-':
546  return parse_variant_value<JsonBaseParseTypes::Number, JsonMember>( rng );
547  }
548  if constexpr( Range::is_unchecked_input ) {
549  DAW_UNREACHABLE( );
550  } else {
551  daw_json_error( ErrorReason::InvalidStartOfValue, rng );
552  }
553  }
554 
555  template<typename Result, typename TypeList, std::size_t pos = 0,
556  typename Range>
557  constexpr Result parse_visit( std::size_t idx, Range &rng ) {
558  if( idx == pos ) {
559  using JsonMember = std::tuple_element_t<pos, TypeList>;
560  return { parse_value<JsonMember>( ParseTag<JsonMember::expected_type>{ },
561  rng ) };
562  }
563  if constexpr( pos + 1 < std::tuple_size_v<TypeList> ) {
564  return parse_visit<Result, TypeList, pos + 1>( idx, rng );
565  } else {
566  daw_json_error( ErrorReason::MissingMemberNameOrEndOfClass, rng );
567  }
568  }
569 
570  template<typename JsonMember, bool KnownBounds, typename Range>
571  [[nodiscard, maybe_unused]] inline constexpr json_result<JsonMember>
572  parse_value( ParseTag<JsonParseTypes::VariantTagged>, Range &rng ) {
573 
574  using tag_member = typename JsonMember::tag_member;
575  auto [is_found, rng2] = find_range<Range>(
576  daw::string_view( rng.class_first, static_cast<std::size_t>(
577  rng.last - rng.class_first ) ),
578  tag_member::name );
579 
580  daw_json_assert( is_found, ErrorReason::TagMemberNotFound, rng );
581  auto index = typename JsonMember::switcher{ }(
582  parse_value<tag_member>( ParseTag<tag_member::expected_type>{ }, rng2 ) );
583 
584  return parse_visit<json_result<JsonMember>,
585  typename JsonMember::json_elements::element_map_t>(
586  index, rng );
587  }
588 
589  template<typename JsonMember, bool KnownBounds, typename Range>
590  constexpr json_result<JsonMember>
591  parse_value( ParseTag<JsonParseTypes::Unknown>, Range &rng ) {
592  using constructor_t = typename JsonMember::constructor_t;
593  if constexpr( KnownBounds ) {
594  return construct_value<json_result<JsonMember>>( constructor_t{ }, rng,
595  rng.first, rng.size( ) );
596  } else {
597  auto value_rng = skip_value( rng );
598  return construct_value<json_result<JsonMember>>(
599  constructor_t{ }, rng, value_rng.first, value_rng.size( ) );
600  }
601  }
602 
603  template<std::size_t N, typename JsonClass, bool KnownBounds,
604  typename... JsonClasses, typename Range>
605  constexpr JsonClass parse_nth_class( std::size_t idx, Range &rng ) {
606  if constexpr( sizeof...( JsonClasses ) >= N + 8 ) {
607  switch( idx ) {
608  case N + 0:
609  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
610  ParseTag<JsonParseTypes::Class>{ }, rng );
611  case N + 1:
612  return parse_value<daw::traits::nth_element<N + 1, JsonClasses...>>(
613  ParseTag<JsonParseTypes::Class>{ }, rng );
614  case N + 2:
615  return parse_value<daw::traits::nth_element<N + 2, JsonClasses...>>(
616  ParseTag<JsonParseTypes::Class>{ }, rng );
617  case N + 3:
618  return parse_value<daw::traits::nth_element<N + 3, JsonClasses...>>(
619  ParseTag<JsonParseTypes::Class>{ }, rng );
620  case N + 4:
621  return parse_value<daw::traits::nth_element<N + 4, JsonClasses...>>(
622  ParseTag<JsonParseTypes::Class>{ }, rng );
623  case N + 5:
624  return parse_value<daw::traits::nth_element<N + 5, JsonClasses...>>(
625  ParseTag<JsonParseTypes::Class>{ }, rng );
626  case N + 6:
627  return parse_value<daw::traits::nth_element<N + 6, JsonClasses...>>(
628  ParseTag<JsonParseTypes::Class>{ }, rng );
629  case N + 7:
630  return parse_value<daw::traits::nth_element<N + 7, JsonClasses...>>(
631  ParseTag<JsonParseTypes::Class>{ }, rng );
632  default:
633  if constexpr( sizeof...( JsonClasses ) > N + 7 ) {
634  return parse_nth_class<N + 8, JsonClass, KnownBounds, JsonClasses...>(
635  idx, rng );
636  } else {
637  DAW_UNREACHABLE( );
638  DAW_UNREACHABLE( );
639  }
640  }
641  } else if constexpr( sizeof...( JsonClasses ) == N + 7 ) {
642  switch( idx ) {
643  case N + 0:
644  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
645  ParseTag<JsonParseTypes::Class>{ }, rng );
646  case N + 1:
647  return parse_value<daw::traits::nth_element<N + 1, JsonClasses...>>(
648  ParseTag<JsonParseTypes::Class>{ }, rng );
649  case N + 2:
650  return parse_value<daw::traits::nth_element<N + 2, JsonClasses...>>(
651  ParseTag<JsonParseTypes::Class>{ }, rng );
652  case N + 3:
653  return parse_value<daw::traits::nth_element<N + 3, JsonClasses...>>(
654  ParseTag<JsonParseTypes::Class>{ }, rng );
655  case N + 4:
656  return parse_value<daw::traits::nth_element<N + 4, JsonClasses...>>(
657  ParseTag<JsonParseTypes::Class>{ }, rng );
658  case N + 5:
659  return parse_value<daw::traits::nth_element<N + 5, JsonClasses...>>(
660  ParseTag<JsonParseTypes::Class>{ }, rng );
661  case N + 6:
662  return parse_value<daw::traits::nth_element<N + 6, JsonClasses...>>(
663  ParseTag<JsonParseTypes::Class>{ }, rng );
664  default:
665  DAW_UNREACHABLE( );
666  }
667  } else if constexpr( sizeof...( JsonClasses ) == N + 6 ) {
668  switch( idx ) {
669  case N + 0:
670  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
671  ParseTag<JsonParseTypes::Class>{ }, rng );
672  case N + 1:
673  return parse_value<daw::traits::nth_element<N + 1, JsonClasses...>>(
674  ParseTag<JsonParseTypes::Class>{ }, rng );
675  case N + 2:
676  return parse_value<daw::traits::nth_element<N + 2, JsonClasses...>>(
677  ParseTag<JsonParseTypes::Class>{ }, rng );
678  case N + 3:
679  return parse_value<daw::traits::nth_element<N + 3, JsonClasses...>>(
680  ParseTag<JsonParseTypes::Class>{ }, rng );
681  case N + 4:
682  return parse_value<daw::traits::nth_element<N + 4, JsonClasses...>>(
683  ParseTag<JsonParseTypes::Class>{ }, rng );
684  case N + 5:
685  return parse_value<daw::traits::nth_element<N + 5, JsonClasses...>>(
686  ParseTag<JsonParseTypes::Class>{ }, rng );
687  default:
688  DAW_UNREACHABLE( );
689  }
690  } else if constexpr( sizeof...( JsonClasses ) == N + 5 ) {
691  switch( idx ) {
692  case N + 0:
693  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
694  ParseTag<JsonParseTypes::Class>{ }, rng );
695  case N + 1:
696  return parse_value<daw::traits::nth_element<N + 1, JsonClasses...>>(
697  ParseTag<JsonParseTypes::Class>{ }, rng );
698  case N + 2:
699  return parse_value<daw::traits::nth_element<N + 2, JsonClasses...>>(
700  ParseTag<JsonParseTypes::Class>{ }, rng );
701  case N + 3:
702  return parse_value<daw::traits::nth_element<N + 3, JsonClasses...>>(
703  ParseTag<JsonParseTypes::Class>{ }, rng );
704  case N + 4:
705  return parse_value<daw::traits::nth_element<N + 4, JsonClasses...>>(
706  ParseTag<JsonParseTypes::Class>{ }, rng );
707  default:
708  DAW_UNREACHABLE( );
709  }
710  } else if constexpr( sizeof...( JsonClasses ) == N + 4 ) {
711  switch( idx ) {
712  case N + 0:
713  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
714  ParseTag<JsonParseTypes::Class>{ }, rng );
715  case N + 1:
716  return parse_value<daw::traits::nth_element<N + 1, JsonClasses...>>(
717  ParseTag<JsonParseTypes::Class>{ }, rng );
718  case N + 2:
719  return parse_value<daw::traits::nth_element<N + 2, JsonClasses...>>(
720  ParseTag<JsonParseTypes::Class>{ }, rng );
721  case N + 3:
722  return parse_value<daw::traits::nth_element<N + 3, JsonClasses...>>(
723  ParseTag<JsonParseTypes::Class>{ }, rng );
724  default:
725  DAW_UNREACHABLE( );
726  }
727  } else if constexpr( sizeof...( JsonClasses ) == N + 3 ) {
728  switch( idx ) {
729  case N + 0:
730  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
731  ParseTag<JsonParseTypes::Class>{ }, rng );
732  case N + 1:
733  return parse_value<daw::traits::nth_element<N + 1, JsonClasses...>>(
734  ParseTag<JsonParseTypes::Class>{ }, rng );
735  case N + 2:
736  return parse_value<daw::traits::nth_element<N + 2, JsonClasses...>>(
737  ParseTag<JsonParseTypes::Class>{ }, rng );
738  default:
739  DAW_UNREACHABLE( );
740  }
741  } else if constexpr( sizeof...( JsonClasses ) == N + 2 ) {
742  if( idx == N ) {
743  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
744  ParseTag<JsonParseTypes::Class>{ }, rng );
745  } else {
746  return parse_value<daw::traits::nth_element<N + 1, JsonClasses...>>(
747  ParseTag<JsonParseTypes::Class>{ }, rng );
748  }
749  } else {
750  return parse_value<daw::traits::nth_element<N + 0, JsonClasses...>>(
751  ParseTag<JsonParseTypes::Class>{ }, rng );
752  }
753  }
754 } // namespace daw::json::json_details
daw_json_parse_kv_class_iterator.h
daw_json_parse_kv_array_iterator.h
daw_json_assert
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:196
daw_json_assert_weak
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:206
daw_json_parse_value_fwd.h
daw::json::parse_utils::is_number
constexpr bool is_number(char c)
Definition: daw_json_parse_iso8601_utils.h:45
daw_json_parse_unsigned_int.h
daw_json_parse_std_string.h
daw_json_error
static DAW_JSON_NOINLINE void daw_json_error(daw::json::ErrorReason reason)
Definition: daw_json_assert.h:59
daw::json::LiteralAsStringOpt
LiteralAsStringOpt
Definition: daw_json_parse_common.h:503
daw_json_parse_real.h
daw::json::JsonNullable::Never
@ Never
daw_json_assert.h
daw_json_parse_array_iterator.h
daw_json_parse_string_need_slow.h
daw_json_parse_name.h
daw::json::LiteralAsStringOpt::Never
@ Never
daw_json_parse_string_quote.h