31 namespace json_details {
32 [[nodiscard]]
static constexpr UInt8 to_nibble(
unsigned char chr ) {
33 int const b =
static_cast<int>( chr );
34 int const maskLetter = ( (
'9' - b ) >> 31 );
35 int const maskSmall = ( (
'Z' - b ) >> 31 );
36 int const offset =
'0' + ( maskLetter & int(
'A' -
'0' - 10 ) ) +
37 ( maskSmall &
int(
'a' -
'A' ) );
38 auto const result =
static_cast<unsigned>( b - offset );
39 return to_uint8( result );
42 template<
bool is_unchecked_input>
43 [[nodiscard]]
static constexpr UInt16
44 byte_from_nibbles( daw::not_null<char const *> &first ) {
45 auto const n0 = to_nibble(
static_cast<unsigned char>( *first++ ) );
46 auto const n1 = to_nibble(
static_cast<unsigned char>( *first++ ) );
47 if constexpr( is_unchecked_input ) {
50 return to_uint16( ( n0 << 4U ) | n1 );
53 static constexpr char u32toC( UInt32 value ) {
54 return static_cast<char>(
static_cast<unsigned char>( value ) );
57 template<
typename ParseState>
58 [[nodiscard]]
static constexpr daw::not_null<char *>
59 decode_utf16( ParseState &parse_state, daw::not_null<char *> it ) {
61 ErrorReason::UnexpectedEndOfData,
63 auto first = daw::not_null<char const *>( parse_state.first );
67 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
69 cp |= byte_from_nibbles<ParseState::is_unchecked_input>( first );
71 *it++ =
static_cast<char>(
static_cast<unsigned char>( cp ) );
72 parse_state.first = first;
77 if( 0xD800U <= cp and cp <= 0xDBFFU ) {
78 cp = ( cp - 0xD800U ) * 0x400U;
81 ( parse_state.last - first >= 5 ) and *first ==
'u',
82 ErrorReason::InvalidUTFEscape,
87 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
90 byte_from_nibbles<ParseState::is_unchecked_input>( first );
96 if( cp >= 0x10000U ) {
98 char const enc3 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
100 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
102 u32toC( ( ( cp >> 12U ) & 0b0011'1111U ) | 0b1000'0000U );
103 char const enc0 = u32toC( ( cp >> 18U ) | 0b1111'0000U );
108 parse_state.first = first;
114 char const enc2 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
116 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
117 char const enc0 = u32toC( ( cp >> 12U ) | 0b1110'0000U );
121 parse_state.first = first;
127 char const enc1 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
128 char const enc0 = u32toC( ( cp >> 6U ) | 0b1100'0000U );
131 parse_state.first = first;
135 template<
typename ParseState,
typename Appender>
136 static constexpr void decode_utf16( ParseState &parse_state,
138 auto first = daw::not_null<char const *>( parse_state.first );
142 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
144 cp |= byte_from_nibbles<ParseState::is_unchecked_input>( first );
147 parse_state.first = first;
150 if( 0xD800U <= cp and cp <= 0xDBFFU ) {
151 cp = ( cp - 0xD800U ) * 0x400U;
154 *first ==
'u', ErrorReason::InvalidUTFEscape, parse_state );
158 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
161 byte_from_nibbles<ParseState::is_unchecked_input>( first );
167 if( cp >= 0x10000U ) {
169 char const enc3 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
171 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
173 u32toC( ( ( cp >> 12U ) & 0b0011'1111U ) | 0b1000'0000U );
174 char const enc0 = u32toC( ( cp >> 18U ) | 0b1111'0000U );
179 parse_state.first = first;
184 char const enc2 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
186 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
187 char const enc0 = u32toC( ( cp >> 12U ) | 0b1110'0000U );
191 parse_state.first = first;
196 char const enc1 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
197 char const enc0 = u32toC( ( cp >> 6U ) | 0b1100'0000U );
200 parse_state.first = first;
203 namespace parse_tokens {
204 inline constexpr char escape_quotes[] =
"\\\"";
209 template<
bool AllowHighEight,
typename JsonMember,
bool KnownBounds,
211 [[nodiscard]]
constexpr auto
212 parse_string_known_stdstring( ParseState &parse_state ) {
213 using string_type = json_base_type_t<JsonMember>;
215 string_type( std::size( parse_state ) + 1,
217 parse_state.template get_allocator_for<char>( ) );
218 daw::not_null<char *> it = std::data( result );
220 bool const has_quote = parse_state.front( ) ==
'"';
222 parse_state.remove_prefix( );
225 if(
auto const first_slash =
226 static_cast<std::ptrdiff_t
>( parse_state.counter ) - 1;
228 it = daw::algorithm::copy_n( parse_state.first,
230 static_cast<std::size_t
>( first_slash ) )
232 parse_state.first += first_slash;
234 DAW_CPP23_STATIC_LOCAL
constexpr auto in_json_string =
236 if constexpr( not ParseState::is_unchecked_input ) {
237 if( not DAW_LIKELY( r.has_more( ) ) ) {
241 return DAW_LIKELY( r.front( ) !=
'"' );
244 while( in_json_string( parse_state ) ) {
246 daw::not_null<char const *> first = parse_state.first;
247 daw::not_null<char const *>
const last = parse_state.last;
249 if( not json_details::use_constexpr_exec_mode<
250 typename ParseState::exec_tag_t>( ) ) {
252 mem_move_to_next_of<( ParseState::is_unchecked_input or
253 ParseState::is_zero_terminated_string ),
254 typename ParseState::exec_tag_t,
256 '\\'>( first, last );
259 ErrorReason::UnexpectedEndOfData,
261 while( *first !=
'"' and *first !=
'\\' ) {
264 ErrorReason::UnexpectedEndOfData,
269 static_cast<std::ptrdiff_t
>( result.size( ) ) -
270 std::distance( result.data( ), it.get( ) ) >=
271 std::distance( parse_state.first, first.get( ) ),
272 ErrorReason::UnexpectedEndOfData );
273 it = daw::algorithm::copy(
274 parse_state.first, first.get( ), it.get( ) );
275 parse_state.first = first;
277 if( parse_state.front( ) ==
'\\' ) {
278 parse_state.remove_prefix( );
280 ErrorReason::InvalidUTFCodepoint,
282 switch( parse_state.front( ) ) {
285 parse_state.remove_prefix( );
289 parse_state.remove_prefix( );
293 parse_state.remove_prefix( );
297 parse_state.remove_prefix( );
301 parse_state.remove_prefix( );
304 it = decode_utf16( parse_state, it );
309 *it++ = parse_state.front( );
310 parse_state.remove_prefix( );
313 if constexpr( not AllowHighEight ) {
315 ( not parse_state.is_space_unchecked( ) ) &
316 (
static_cast<unsigned char>( parse_state.front( ) ) <=
318 ErrorReason::InvalidStringHighASCII,
321 *it++ = parse_state.front( );
322 parse_state.remove_prefix( );
326 parse_state.is_quotes_checked( ),
327 ErrorReason::InvalidString,
331 ErrorReason::UnexpectedEndOfData,
334 auto const sz =
static_cast<std::size_t
>(
335 std::distance( std::data( result ), it.get( ) ) );
337 std::size( result ) >= sz, ErrorReason::InvalidString, parse_state );
339 if constexpr( std::is_convertible_v<string_type,
340 json_result_t<JsonMember>> ) {
343 using constructor_t = json_constructor_t<JsonMember>;
344 construct_value<json_result_t<JsonMember>, constructor_t>(
345 parse_state, std::data( result ), daw::data_end( result ) );