17#include <daw/daw_attributes.h>
18#include <daw/daw_cxmath.h>
19#include <daw/daw_is_constant_evaluated.h>
20#include <daw/daw_span.h>
26#if defined( DAW_JSON_HAS_SIMD )
29 namespace json_details {
30 namespace skip_bracketed_item_simd_details {
31 using simd_type = daw::simd::vec<char>;
32 static constexpr std::size_t block_size =
33 static_cast<std::size_t
>( simd_type::size( ) );
34 static_assert( block_size <= 64 );
36 [[nodiscard]]
constexpr std::uint64_t
37 low_bits( std::size_t count )
noexcept {
38 return count == 64 ?
~std::uint64_t{ 0 }
39 : ( std::uint64_t{ 1 } << count ) - 1;
42 [[nodiscard]]
constexpr std::uint64_t
43 prefix_xor( std::uint64_t bits )
noexcept {
53 [[nodiscard]]
constexpr bool last_bit( std::uint64_t bits,
54 std::size_t count )
noexcept {
56 ( ( bits >> ( count - 1U ) ) & std::uint64_t{ 1 } ) != 0;
60#if defined( DAW_JSON_HAS_STD_SIMD )
65 simd_type splat(
char value )
noexcept {
66 return simd_type( value );
69 template<
char... Values>
70 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR
auto one_of( simd_type value ) {
71 return ( ( value == splat( Values ) ) | ... );
74 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR simd_type
75 load(
char const *first, std::size_t count ) {
76 if( count == block_size ) {
77 return daw::simd::unchecked_load<simd_type>(
78 daw::span( first, block_size ) );
80 return daw::simd::partial_load<simd_type>(
81 daw::span( first, count ) );
87 template<SkipBracketedType BracketedType,
typename ParseState>
88 [[nodiscard]] DAW_ATTRIB_FLATTEN DAW_JSON_SIMD_CONSTEXPR ParseState
89 skip_bracketed_item_simd( ParseState &parse_state ) {
90 DAW_CPP23_STATIC_LOCAL
constexpr char primary_left =
91 BracketedType == SkipBracketedType::Class ?
'{' :
'[';
92 DAW_CPP23_STATIC_LOCAL
constexpr char primary_right =
93 BracketedType == SkipBracketedType::Class ?
'}' :
']';
94 DAW_CPP23_STATIC_LOCAL
constexpr char secondary_left =
95 BracketedType == SkipBracketedType::Class ?
'[' :
'{';
96 DAW_CPP23_STATIC_LOCAL
constexpr char secondary_right =
97 BracketedType == SkipBracketedType::Class ?
']' :
'}';
99 using namespace skip_bracketed_item_simd_details;
100 auto ptr_first = parse_state.first;
101 auto const ptr_last = parse_state.last;
102 if( DAW_UNLIKELY( ptr_first >= ptr_last ) ) {
106 auto result = parse_state;
107 std::size_t count = 0;
108 std::uint32_t primary_depth = 1;
109 std::uint32_t secondary_depth = 0;
110 bool in_string =
false;
111 bool escaped =
false;
113 if( *ptr_first == primary_left ) {
117 while( ptr_first < ptr_last ) {
118 auto const remaining =
119 static_cast<std::size_t
>( ptr_last - ptr_first );
120 auto const lane_count =
121 remaining < block_size ? remaining : block_size;
122 auto const input = load( ptr_first, lane_count );
123 auto const valid_bits = low_bits( lane_count );
124 auto const backslash_bits =
125 ( input == splat(
'\\' ) ).to_ullong( ) & valid_bits;
127 DAW_CPP23_STATIC_LOCAL
constexpr std::uint64_t odd_bits =
128 0xAAAAAAAAAAAAAAAAULL;
129 auto const previous_escaped = escaped ? std::uint64_t{ 1 } : 0;
130 auto const potential_escape = backslash_bits & ~previous_escaped;
131 auto const maybe_escaped = potential_escape << 1U;
132 auto const escape_and_terminal =
133 ( ( maybe_escaped | odd_bits ) - potential_escape ) ^ odd_bits;
134 auto const escaped_bits =
135 ( escape_and_terminal ^ ( backslash_bits | previous_escaped ) ) &
137 auto const escape_bits = escape_and_terminal & backslash_bits;
138 escaped = last_bit( escape_bits, lane_count );
140 auto const quote_bits =
141 ( input == splat(
'"' ) ).to_ullong( ) & ~escaped_bits & valid_bits;
142 auto const in_string_bits =
143 ( prefix_xor( quote_bits ) ^
144 ( in_string ? valid_bits : std::uint64_t{ 0 } ) ) &
146 in_string = last_bit( in_string_bits, lane_count );
148 auto events = one_of<
'{',
'}',
'[',
']',
','>( input ).to_ullong( ) &
149 ~( in_string_bits ^ quote_bits ) & ~escaped_bits &
151 while( events != 0 ) {
153 static_cast<std::size_t
>(
154 daw::cxmath::count_trailing_zeros(
static_cast<std::uint64_t
>( events ) ) );
155 switch( ptr_first[lane] ) {
157 if( ( primary_depth == 1 ) & ( secondary_depth == 0 ) ) {
166 if( primary_depth == 0 ) {
167 auto const end = ptr_first + lane + 1;
168 if constexpr( not ParseState::is_unchecked_input ) {
170 ErrorReason::InvalidBracketing,
174 result.counter = count;
175 parse_state.first = end;
182 case secondary_right:
188 events &= events - 1U;
190 ptr_first += lane_count;
193 if constexpr( not ParseState::is_unchecked_input ) {
195 not in_string, ErrorReason::UnexpectedEndOfData, parse_state );
197 ErrorReason::InvalidBracketing,
200 result.last = ptr_first;
201 result.counter = count;
202 parse_state.first = ptr_first;
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.