34 namespace json_details {
38 template<
typename ParseState>
39 [[nodiscard]] DAW_ATTRIB_FLATINLINE
static inline constexpr ParseState
40 skip_string_nq( ParseState &parse_state ) {
41 auto result = parse_state;
43 string_quote::string_quote_parser::parse_nq( parse_state );
46 ErrorReason::InvalidString, parse_state );
47 result.last = parse_state.first;
48 parse_state.remove_prefix( );
55 template<
bool KeepQuotes = false,
typename ParseState>
56 [[nodiscard]] DAW_ATTRIB_FLATINLINE
static inline constexpr ParseState
57 skip_string( ParseState &parse_state ) {
58 if( parse_state.empty( ) ) {
62 ErrorReason::InvalidString, parse_state );
63 parse_state.remove_prefix( );
66 ErrorReason::InvalidString, parse_state );
67 auto result = skip_string_nq( parse_state );
68 if constexpr( KeepQuotes ) {
75 template<
typename ParseState>
76 [[nodiscard]]
static inline constexpr ParseState
77 skip_true( ParseState &parse_state ) {
78 auto result = parse_state;
79 if constexpr( ( ParseState::is_zero_terminated_string or
80 ParseState::is_unchecked_input ) ) {
81 parse_state.remove_prefix( 4 );
83 parse_state.remove_prefix( );
85 ErrorReason::InvalidTrue, parse_state );
86 parse_state.remove_prefix( 3 );
88 result.last = parse_state.first;
89 parse_state.trim_left( );
91 parse_state.is_at_token_after_value( ),
92 ErrorReason::InvalidEndOfValue, parse_state );
93 result.counter =
static_cast<bool>( true );
97 template<
typename ParseState>
98 [[nodiscard]]
static inline constexpr ParseState
99 skip_false( ParseState &parse_state ) {
100 auto result = parse_state;
101 if constexpr( ( ParseState::is_zero_terminated_string or
102 ParseState::is_unchecked_input ) ) {
103 parse_state.remove_prefix( 5 );
105 parse_state.remove_prefix( );
107 ErrorReason::InvalidFalse, parse_state );
108 parse_state.remove_prefix( 4 );
110 result.last = parse_state.first;
111 parse_state.trim_left( );
113 parse_state.is_at_token_after_value( ),
114 ErrorReason::InvalidEndOfValue, parse_state );
115 result.counter =
static_cast<bool>( false );
119 template<
typename ParseState>
120 [[nodiscard]]
static inline constexpr ParseState
121 skip_null( ParseState &parse_state ) {
122 if constexpr( ( ParseState::is_zero_terminated_string or
123 ParseState::is_unchecked_input ) ) {
124 parse_state.remove_prefix( 4 );
126 parse_state.remove_prefix( );
128 ErrorReason::InvalidNull, parse_state );
129 parse_state.remove_prefix( 3 );
132 ErrorReason::UnexpectedEndOfData, parse_state );
133 parse_state.trim_left( );
135 parse_state.is_at_token_after_value( ),
136 ErrorReason::UnexpectedEndOfData, parse_state );
137 auto result = parse_state;
138 result.first =
nullptr;
139 result.last =
nullptr;
143 template<
bool skip_end_check,
typename CharT>
144 DAW_ATTRIB_NONNULL( )
145 DAW_ATTRIB_RET_NONNULL DAW_ATTRIB_FLATINLINE
146 [[nodiscard]]
static inline constexpr CharT *skip_digits(
147 CharT *first, CharT *
const last ) {
149 unsigned dig = parse_digit( *first );
152 if constexpr( not skip_end_check ) {
153 if( DAW_UNLIKELY( first >= last ) ) {
157 dig = parse_digit( *first );
167#if false and defined( DAW_CX_BIT_CAST )
169 ParseState::is_unchecked_input or
170 ParseState::is_zero_terminated_string )>
172 ParseState::is_zero_terminated_string )
173 [[nodiscard]]
static constexpr ParseState
174 skip_number( ParseState &parse_state ) {
175 using CharT =
typename ParseState::CharT;
177 auto result = parse_state;
178 CharT *first = parse_state.first;
179 CharT *
const last = parse_state.last;
181 if( *first ==
'-' ) {
185 first = count_digits( first, last );
187 CharT *decimal =
nullptr;
188 if( *first ==
'.' ) {
190 first = count_digits( first, last );
193 CharT *exp =
nullptr;
194 char const maybe_e = *first;
195 if( ( maybe_e ==
'e' ) | ( maybe_e ==
'E' ) ) {
197 char const maybe_sign = *first;
198 if( ( maybe_sign ==
'+' ) | ( maybe_sign ==
'-' ) ) {
201 first = count_digits( first, last );
206 parse_state.first = first;
208 result.class_first = decimal;
209 result.class_last = exp;
214 not( ParseState::is_unchecked_input or
215 ParseState::is_zero_terminated_string ) )>
217 ParseState::is_zero_terminated_string ) )
219 template<
typename ParseState>
221 [[nodiscard]]
static constexpr ParseState
222 skip_number( ParseState &parse_state ) {
223 using CharT =
typename ParseState::CharT;
225 ErrorReason::UnexpectedEndOfData, parse_state );
227 auto result = parse_state;
228 CharT *first = parse_state.first;
229 CharT *
const last = parse_state.last;
230 if constexpr( ParseState::allow_leading_zero_plus ) {
231 if( *first ==
'-' ) {
242 if( last - first > 1 ) {
244 not parse_policy_details::is_number( *std::next( first ) ),
245 ErrorReason::InvalidNumberStart, parse_state );
251 if( DAW_LIKELY( first < last ) ) {
254 skip_digits<( ParseState::is_zero_terminated_string or
255 ParseState::is_unchecked_input )>( first, last );
258 CharT *decimal =
nullptr;
259 if( ( ( ParseState::is_zero_terminated_string or
260 ParseState::is_unchecked_input ) or
262 ( *first ==
'.' ) ) {
265 if( DAW_LIKELY( first < last ) ) {
268 skip_digits<( ParseState::is_zero_terminated_string or
269 ParseState::is_unchecked_input )>( first, last );
272 CharT *exp =
nullptr;
275 if( ParseState::is_zero_terminated_string or first < last ) {
276 return parse_digit( *first );
281 if( ( dig == parsed_constants::e_char ) |
282 ( dig == parsed_constants::E_char ) ) {
287 auto r = parse_state;
291 dig = parse_digit( *first );
292 if( ( dig == parsed_constants::plus_char ) |
293 ( dig == parsed_constants::minus_char ) ) {
297 ErrorReason::InvalidNumber );
299 if( DAW_LIKELY( first < last ) ) {
302 skip_digits<( ParseState::is_zero_terminated_string or
303 ParseState::is_unchecked_input )>( first, last );
307 parse_state.first = first;
309 result.class_first = decimal;
310 result.class_last = exp;
320 template<
bool KeepInitialQuote = false,
typename ParseState>
321 [[nodiscard]] DAW_ATTRIB_NOINLINE
constexpr ParseState
322 skip_value( ParseState &parse_state ) {
324 ErrorReason::UnexpectedEndOfData, parse_state );
327 parse_state.counter = 0;
328 switch( parse_state.front( ) ) {
330 return skip_string<KeepInitialQuote>( parse_state );
332 return parse_state.skip_array( );
334 return parse_state.skip_class( );
336 return skip_true( parse_state );
338 return skip_false( parse_state );
340 return skip_null( parse_state );
352 return skip_number( parse_state );
355 if constexpr( ParseState::is_unchecked_input ) {
356 if( DAW_UNLIKELY( parse_state.front( ) ==
'\0' ) ) {
369 template<
typename JsonMember,
typename ParseState>
370 [[nodiscard]] DAW_ATTRIB_FLATINLINE
static inline constexpr ParseState
371 skip_known_value( ParseState &parse_state ) {
373 ErrorReason::UnexpectedEndOfData, parse_state );
374 if constexpr( JsonMember::expected_type == JsonParseTypes::Date or
375 JsonMember::expected_type == JsonParseTypes::StringRaw or
376 JsonMember::expected_type ==
377 JsonParseTypes::StringEscaped or
378 JsonMember::expected_type == JsonParseTypes::Custom ) {
381 ErrorReason::InvalidString, parse_state );
382 parse_state.remove_prefix( );
383 return json_details::skip_string_nq( parse_state );
384 }
else if constexpr( daw::is_any_of_v<
385 JsonMember::expected_type, JsonParseTypes::Real,
386 JsonParseTypes::Signed, JsonParseTypes::Unsigned,
387 JsonParseTypes::Bool, JsonParseTypes::Null> ) {
389 return skip_number( parse_state );
390 }
else if constexpr( JsonMember::expected_type ==
391 JsonParseTypes::Array ) {
393 ErrorReason::InvalidArrayStart, parse_state );
394 return parse_state.skip_array( );
395 }
else if constexpr( JsonMember::expected_type ==
396 JsonParseTypes::Class ) {
398 ErrorReason::InvalidClassStart, parse_state );
399 return parse_state.skip_class( );
401 return skip_value( parse_state );
405 template<
typename ParseState>
406 [[nodiscard]]
static inline constexpr ParseState
407 skip_literal( ParseState &parse_state ) {
409 ErrorReason::UnexpectedEndOfData, parse_state );
412 parse_state.counter = 0;
413 switch( parse_state.front( ) ) {
415 return skip_true( parse_state );
417 return skip_false( parse_state );
419 return skip_null( parse_state );
431 return skip_number( parse_state );
435 if constexpr( ParseState::is_unchecked_input ) {