14#include <daw/daw_attributes.h>
15#include <daw/daw_cpp_feature_check.h>
16#include <daw/daw_cxmath.h>
17#include <daw/daw_do_n.h>
18#include <daw/daw_likely.h>
19#include <daw/daw_uint_buffer.h>
20#include <daw/daw_unreachable.h>
22#if defined( DAW_ALLOW_SSE42 )
40 namespace json_details {
41 DAW_ATTRIB_INLINE
inline constexpr bool
43 if( *( ptr - 1 ) !=
'\\' ) {
46 if( ( ptr - min_ptr ) < 2 ) {
49 return *( ptr - 2 ) !=
'\\';
52#if defined( DAW_ALLOW_SSE42 )
54 alignas( 16 )
bool values[256] = { };
56 constexpr bool operator[](
char idx )
const {
57 return values[
static_cast<unsigned char>( idx )];
61 template<
char... keys>
62 static constexpr inline key_table_t key_table = [] {
63 auto result = key_table_t{ };
64 (void)( ( result.values[
static_cast<unsigned char>( keys )] = true ) |
71#if DAW_HAS_BUILTIN( __builtin_ffs )
72 return __builtin_ffs(
static_cast<int>( value ) ) - 1;
73#elif defined( _MSC_VER )
75 _BitScanForward( &index,
static_cast<int>( value ) );
76 return static_cast<std::ptrdiff_t
>( index );
78 std::ptrdiff_t result = 0;
82 while( ( value & 1 ) == 0 ) {
90#if defined( DAW_ALLOW_SSE42 )
91 DAW_ATTRIB_INLINE
inline __m128i
92 set_reverse(
char c0,
char c1 = 0,
char c2 = 0,
char c3 = 0,
char c4 = 0,
93 char c5 = 0,
char c6 = 0,
char c7 = 0,
char c8 = 0,
94 char c9 = 0,
char c10 = 0,
char c11 = 0,
char c12 = 0,
95 char c13 = 0,
char c14 = 0,
char c15 = 0 ) {
96 return _mm_set_epi8( c15, c14, c13, c12, c11, c10, c9, c8, c7, c6, c5,
100 DAW_ATTRIB_INLINE
inline __m128i uload16_char_data( sse42_exec_tag,
102 return _mm_loadu_si128(
reinterpret_cast<__m128i
const *
>( ptr ) );
105 DAW_ATTRIB_INLINE
inline __m128i load16_char_data( sse42_exec_tag,
107 return _mm_load_si128(
reinterpret_cast<__m128i
const *
>( ptr ) );
111 DAW_ATTRIB_INLINE
inline UInt32 mem_find_eq( sse42_exec_tag,
113 __m128i
const keys = _mm_set1_epi8( k );
114 __m128i
const found = _mm_cmpeq_epi8( block, keys );
115 return to_uint32( _mm_movemask_epi8( found ) );
118 template<
unsigned char k>
119 DAW_ATTRIB_INLINE
inline UInt32 mem_find_gt( sse42_exec_tag,
121 static __m128i
const keys = _mm_set1_epi8( k );
122 __m128i
const found = _mm_cmpgt_epi8( block, keys );
123 return to_uint32( _mm_movemask_epi8( found ) );
126 template<
bool is_unchecked_input,
char... keys,
typename CharT>
129 CharT *
const last ) {
131 while( last - first >= 16 ) {
132 auto const val0 = uload16_char_data( tag, first );
133 auto const key_positions = ( mem_find_eq<keys>( tag, val0 ) | ... );
134 if( key_positions != 0 ) {
140 auto const max_pos = last - first;
141 memcpy( &val1, first,
static_cast<std::size_t
>( max_pos ) );
142 auto const key_positions = ( mem_find_eq<keys>( tag, val1 ) | ... );
143 if( key_positions != 0 ) {
145 if( offset >= max_pos ) {
148 return first + offset;
153 template<
bool is_unchecked_input,
char... keys,
typename CharT>
154 DAW_ATTRIB_INLINE
inline CharT *
155 mem_move_to_next_not_of( sse42_exec_tag tag, CharT *first, CharT *last ) {
156 using keys_len = daw::constant<static_cast<int>(
sizeof...( keys ) )>;
157 using compare_mode = daw::constant<static_cast<int>(
158 _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_NEGATIVE_POLARITY )>;
159 static_assert( keys_len::value <= 16 );
161 __m128i
const a = set_reverse( keys... );
163 while( last - first >= 16 ) {
164 auto const b = uload16_char_data( tag, first );
166 _mm_cmpestri( a, keys_len::value, b, 16, compare_mode::value );
173 auto const max_pos = last - first;
175 _mm_cmpestri( a, keys_len::vlaue, b, 16, compare_mode::value );
176 if( result < max_pos ) {
177 return first + result;
182 template<
typename U32>
183 DAW_ATTRIB_INLINE
inline bool add_overflow( U32 value1, U32 value2,
185 static_assert(
sizeof( U32 ) <=
sizeof(
unsigned long long ) );
186 static_assert(
sizeof( U32 ) == 4 );
187#if( defined( __GNUC__ ) and __GNUC__ >= 8 ) or defined( __clang__ ) or \
188 ( DAW_HAS_BUILTIN( __builtin_uadd_overflow ) and \
189 DAW_HAS_BUILTIN( __builtin_uaddl_overflow ) and \
190 DAW_HAS_BUILTIN( __builtin_uaddll_overflow ) )
191 if constexpr(
sizeof( unsigned ) ==
sizeof( U32 ) ) {
192 return __builtin_uadd_overflow(
193 static_cast<unsigned>( value1 ),
static_cast<unsigned>( value2 ),
194 reinterpret_cast<unsigned *
>( &result ) );
195 }
else if constexpr(
sizeof(
unsigned long ) ==
sizeof( U32 ) ) {
196 return __builtin_uaddl_overflow(
197 static_cast<unsigned long>( value1 ),
198 static_cast<unsigned long>( value2 ),
199 reinterpret_cast<unsigned long *
>( &result ) );
201 return __builtin_uaddll_overflow(
202 static_cast<unsigned long long>( value1 ),
203 static_cast<unsigned long long>( value2 ),
204 reinterpret_cast<unsigned long long *
>( &result ) );
207 return _addcarry_u32( 0,
static_cast<std::uint32_t
>( value1 ),
208 static_cast<std::uint32_t
>( value2 ),
209 reinterpret_cast<std::uint32_t *
>( &result ) );
215 DAW_ATTRIB_INLINE
inline constexpr UInt32
216 find_escaped_branchless( constexpr_exec_tag, UInt32 &prev_escaped,
217 UInt32 backslashes ) {
218 backslashes &= ~prev_escaped;
219 UInt32 follow_escape = ( backslashes << 1 ) | prev_escaped;
220 using even_bits = daw::constant<0x5555'5555_u32>;
222 UInt32
const odd_seq_start =
223 backslashes & ( ~even_bits::value ) & ( ~follow_escape );
224 UInt32 seq_start_on_even_bits = 0_u32;
226 auto r = odd_seq_start + backslashes;
227 seq_start_on_even_bits = 0x0000'FFFF_u32 & r;
231 UInt32 invert_mask = seq_start_on_even_bits << 1U;
233 return ( even_bits::value ^ invert_mask ) & follow_escape;
236 DAW_ATTRIB_INLINE
inline UInt32 prefix_xor( sse42_exec_tag,
238 __m128i
const all_ones = _mm_set1_epi8(
'\xFF' );
239 __m128i
const result = _mm_clmulepi64_si128(
240 _mm_set_epi32( 0, 0, 0,
static_cast<std::int32_t
>( bitmask ) ),
242 return to_uint32( _mm_cvtsi128_si32( result ) );
245 template<
bool is_unchecked_input,
typename CharT>
248 CharT *
const last ) {
249 UInt32 prev_escapes = 0_u32;
250 while( last - first >= 16 ) {
251 auto const val0 = uload16_char_data( tag, first );
252 UInt32
const backslashes = mem_find_eq<'\\'>( tag, val0 );
253 UInt32
const escaped =
254 find_escaped_branchless( tag, prev_escapes, backslashes );
255 UInt32
const quotes = mem_find_eq<
'"'>( tag, val0 ) & ( ~escaped );
256 UInt32
const in_string = prefix_xor( tag, quotes );
257 if( in_string != 0 ) {
263 if constexpr( is_unchecked_input ) {
264 while( *first !=
'"' ) {
265 while( not key_table<'"', '\\'>[*first] ) {
268 if( *first ==
'"' ) {
274 while( DAW_LIKELY( first < last ) and *first !=
'"' ) {
275 while( DAW_LIKELY( first < last ) and
276 not key_table<
'"',
'\\'>[*first] ) {
279 if( first >= last ) {
282 if( *first ==
'"' ) {
288 return ( is_unchecked_input or DAW_LIKELY( first < last ) ) ? first
292 template<
bool is_unchecked_input,
typename CharT>
296 std::ptrdiff_t &first_escape ) {
297 CharT *
const first_first = first;
298 UInt32 prev_escapes = 0_u32;
299 while( last - first >= 16 ) {
300 auto const val0 = uload16_char_data( tag, first );
301 UInt32
const backslashes = mem_find_eq<'\\'>( tag, val0 );
302 if( ( backslashes != 0 ) & ( first_escape < 0 ) ) {
305 UInt32
const escaped =
306 find_escaped_branchless( tag, prev_escapes, backslashes );
307 UInt32
const quotes = mem_find_eq<
'"'>( tag, val0 ) & ( ~escaped );
308 UInt32
const in_string = prefix_xor( tag, quotes );
309 if( in_string != 0 ) {
315 if constexpr( is_unchecked_input ) {
316 while( *first !=
'"' ) {
317 while( not key_table<'"', '\\'>[*first] ) {
320 if( *first ==
'"' ) {
323 if( first_escape < 0 ) {
324 first_escape = first_first - first;
329 while( DAW_LIKELY( first < last ) and *first !=
'"' ) {
330 while( DAW_LIKELY( first < last ) and
331 not key_table<
'"',
'\\'>[*first] ) {
334 if( first >= last ) {
337 if( *first ==
'"' ) {
340 if( first_escape < 0 ) {
341 first_escape = first_first - first;
346 return ( is_unchecked_input or DAW_LIKELY( first < last ) ) ? first
351 template<
bool is_unchecked_input,
char... keys,
typename CharT>
352 DAW_ATTRIB_INLINE
inline CharT *
354 if constexpr(
sizeof...( keys ) == 1 ) {
355 char const key[]{ keys... };
356 auto *ptr =
reinterpret_cast<CharT *
>( std::memchr(
357 first, key[0],
static_cast<std::size_t
>( last - first ) ) );
358 if( ptr ==
nullptr ) {
363 constexpr auto eq = [](
char l,
char r ) {
return l == r; };
364 while( is_unchecked_input or first < last ) {
365 char const c = *first;
366 if( ( eq( c, keys ) | ... ) ) {
376 bool is_unchecked_input,
typename ExecTag,
typename CharT,
377 std::enable_if_t<std::is_base_of<runtime_exec_tag, ExecTag>::value,
378 std::nullptr_t> =
nullptr>
379 DAW_ATTRIB_INLINE
inline CharT *
386 bool is_unchecked_input,
typename ExecTag,
typename CharT,
387 std::enable_if_t<std::is_base_of<runtime_exec_tag, ExecTag>::value,
388 std::nullptr_t> =
nullptr>
389 DAW_ATTRIB_INLINE
inline CharT *
391 CharT *
const last ) {
392 if constexpr( not is_unchecked_input ) {
397 while( is_unchecked_input or first < last ) {
402 if constexpr( is_unchecked_input ) {
405 first +=
static_cast<int>(
static_cast<bool>( last - first ) );
416 template<
bool is_unchecked_input,
typename CharT>
417 DAW_ATTRIB_INLINE
inline CharT *
420 std::ptrdiff_t &first_escape ) {
421 CharT *
const first_first = first;
422 if constexpr( not is_unchecked_input ) {
427 while( is_unchecked_input or first < last ) {
432 if( first_escape < 0 ) {
433 first_escape = first_first - first;
435 if constexpr( is_unchecked_input ) {
438 first +=
static_cast<int>(
static_cast<bool>( last - first ) );
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:179
constexpr DAW_ATTRIB_INLINE bool is_escaped(char const *ptr, char const *min_ptr)
Definition: daw_not_const_ex_functions.h:42
std::ptrdiff_t find_lsb_set(runtime_exec_tag, UInt32 value)
Definition: daw_not_const_ex_functions.h:70
DAW_ATTRIB_INLINE CharT * mem_skip_until_end_of_string(ExecTag const &tag, CharT *first, CharT *const last)
Definition: daw_not_const_ex_functions.h:390
DAW_ATTRIB_INLINE CharT * mem_skip_string(ExecTag const &tag, CharT *first, CharT *const last)
Definition: daw_not_const_ex_functions.h:380
DAW_ATTRIB_INLINE CharT * mem_move_to_next_of(runtime_exec_tag, CharT *first, CharT *last)
Definition: daw_not_const_ex_functions.h:353
Definition: daw_from_json.h:22
Definition: daw_json_exec_modes.h:28
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition: version.h:16