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>
44 [[nodiscard]]
static constexpr UInt16
45 byte_from_nibbles( daw::not_null<char const *> &first ) {
46 auto const n0 = to_nibble(
static_cast<unsigned char>( *first++ ) );
47 auto const n1 = to_nibble(
static_cast<unsigned char>( *first++ ) );
48 if constexpr( is_unchecked_input ) {
51 return to_uint16( ( n0 << 4U ) | n1 );
54 static constexpr char u32toC( UInt32 value ) {
55 return static_cast<char>(
static_cast<unsigned char>( value ) );
58 template<
typename ParseState>
59 [[nodiscard]]
static constexpr daw::not_null<char *>
60 decode_utf16( ParseState &parse_state, daw::not_null<char *> it ) {
62 ErrorReason::UnexpectedEndOfData,
64 auto first = daw::not_null<char const *>( parse_state.first );
68 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
70 cp |= byte_from_nibbles<ParseState::is_unchecked_input>( first );
72 *it++ =
static_cast<char>(
static_cast<unsigned char>( cp ) );
73 parse_state.first = first;
78 if( 0xD800U <= cp and cp <= 0xDBFFU ) {
79 cp = ( cp - 0xD800U ) * 0x400U;
82 ( parse_state.last - first >= 5 ) and *first ==
'u',
83 ErrorReason::InvalidUTFEscape,
88 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
91 byte_from_nibbles<ParseState::is_unchecked_input>( first );
97 if( cp >= 0x10000U ) {
99 char const enc3 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
101 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
103 u32toC( ( ( cp >> 12U ) & 0b0011'1111U ) | 0b1000'0000U );
104 char const enc0 = u32toC( ( cp >> 18U ) | 0b1111'0000U );
109 parse_state.first = first;
115 char const enc2 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
117 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
118 char const enc0 = u32toC( ( cp >> 12U ) | 0b1110'0000U );
122 parse_state.first = first;
128 char const enc1 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
129 char const enc0 = u32toC( ( cp >> 6U ) | 0b1100'0000U );
132 parse_state.first = first;
136 template<
typename ParseState,
typename Appender>
137 static constexpr void decode_utf16( ParseState &parse_state,
139 auto first = daw::not_null<char const *>( parse_state.first );
143 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
145 cp |= byte_from_nibbles<ParseState::is_unchecked_input>( first );
148 parse_state.first = first;
151 if( 0xD800U <= cp and cp <= 0xDBFFU ) {
152 cp = ( cp - 0xD800U ) * 0x400U;
155 *first ==
'u', ErrorReason::InvalidUTFEscape, parse_state );
159 byte_from_nibbles<ParseState::is_unchecked_input>( first ) )
162 byte_from_nibbles<ParseState::is_unchecked_input>( first );
168 if( cp >= 0x10000U ) {
170 char const enc3 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
172 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
174 u32toC( ( ( cp >> 12U ) & 0b0011'1111U ) | 0b1000'0000U );
175 char const enc0 = u32toC( ( cp >> 18U ) | 0b1111'0000U );
180 parse_state.first = first;
185 char const enc2 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
187 u32toC( ( ( cp >> 6U ) & 0b0011'1111U ) | 0b1000'0000U );
188 char const enc0 = u32toC( ( cp >> 12U ) | 0b1110'0000U );
192 parse_state.first = first;
197 char const enc1 = u32toC( ( cp & 0b0011'1111U ) | 0b1000'0000U );
198 char const enc0 = u32toC( ( cp >> 6U ) | 0b1100'0000U );
201 parse_state.first = first;
204 namespace parse_tokens {
205 inline constexpr char escape_quotes[] =
"\\\"";
210 template<
bool AllowHighEight,
typename JsonMember,
bool KnownBounds,
212 [[nodiscard]]
constexpr auto
213 parse_string_known_stdstring( ParseState &parse_state ) {
214 using string_type = json_base_type_t<JsonMember>;
216 string_type( std::size( parse_state ) + 1,
218 parse_state.template get_allocator_for<char>( ) );
219 daw::not_null<char *> it = std::data( result );
221 bool const has_quote = parse_state.front( ) ==
'"';
223 parse_state.remove_prefix( );
226 if(
auto const first_slash =
227 static_cast<std::ptrdiff_t
>( parse_state.counter ) - 1;
229 it = daw::algorithm::copy_n( parse_state.first,
231 static_cast<std::size_t
>( first_slash ) )
233 parse_state.first += first_slash;
235 DAW_CPP23_STATIC_LOCAL
constexpr auto in_json_string =
237 if constexpr( not ParseState::is_unchecked_input ) {
238 if( not DAW_LIKELY( r.has_more( ) ) ) {
242 return DAW_LIKELY( r.front( ) !=
'"' );
245 while( in_json_string( parse_state ) ) {
247 daw::not_null<char const *> first = parse_state.first;
248 daw::not_null<char const *>
const last = parse_state.last;
250 if( not json_details::use_constexpr_exec_mode<
251 typename ParseState::exec_tag_t>( ) ) {
253 mem_move_to_next_of<( ParseState::is_unchecked_input or
254 ParseState::is_zero_terminated_string ),
255 typename ParseState::exec_tag_t,
257 '\\'>( first, last );
260 ErrorReason::UnexpectedEndOfData,
262 while( *first !=
'"' and *first !=
'\\' ) {
265 ErrorReason::UnexpectedEndOfData,
270 static_cast<std::ptrdiff_t
>( result.size( ) ) -
271 std::distance( result.data( ), it.get( ) ) >=
272 std::distance( parse_state.first, first.get( ) ),
273 ErrorReason::UnexpectedEndOfData );
274 it = daw::algorithm::copy(
275 parse_state.first, first.get( ), it.get( ) );
276 parse_state.first = first;
278 if( parse_state.front( ) ==
'\\' ) {
279 parse_state.remove_prefix( );
281 ErrorReason::InvalidUTFCodepoint,
283 switch( parse_state.front( ) ) {
286 parse_state.remove_prefix( );
290 parse_state.remove_prefix( );
294 parse_state.remove_prefix( );
298 parse_state.remove_prefix( );
302 parse_state.remove_prefix( );
305 it = decode_utf16( parse_state, it );
310 *it++ = parse_state.front( );
311 parse_state.remove_prefix( );
314 if constexpr( not AllowHighEight ) {
316 ( not parse_state.is_space_unchecked( ) ) &
317 (
static_cast<unsigned char>( parse_state.front( ) ) <=
319 ErrorReason::InvalidStringHighASCII,
322 *it++ = parse_state.front( );
323 parse_state.remove_prefix( );
327 parse_state.is_quotes_checked( ),
328 ErrorReason::InvalidString,
332 ErrorReason::UnexpectedEndOfData,
335 auto const sz =
static_cast<std::size_t
>(
336 std::distance( std::data( result ), it.get( ) ) );
338 std::size( result ) >= sz, ErrorReason::InvalidString, parse_state );
340 if constexpr( std::is_convertible_v<string_type,
341 json_result_t<JsonMember>> ) {
344 using constructor_t = json_constructor_t<JsonMember>;
345 construct_value<json_result_t<JsonMember>, constructor_t>(
346 parse_state, std::data( result ), daw::data_end( result ) );