13#if defined( DAW_JSON_HAS_SIMD )
17 namespace json_details::simd_details {
18 template<
typename JsonMember,
typename CharT,
auto... PolicyFlags>
19 class json_simd_block_iterator_bool {
20 static_assert( JsonMember::underlying_json_type ==
21 JsonBaseParseTypes::Bool );
23 options::details::make_parse_flags<PolicyFlags...>( ).value>>;
24 using classifier_type =
25 simd_json_classifier<JsonBaseParseTypes::Bool, CharT>;
26 using block_type = simd_json_block<JsonBaseParseTypes::Bool, CharT>;
29 using json_member = JsonMember;
30 using value_type =
typename json_member::parse_to_t;
31 using reference = value_type;
32 using difference_type = std::ptrdiff_t;
33 using iterator_category = std::input_iterator_tag;
36 static constexpr std::size_t boolean_cache_words = 4U;
37 static constexpr std::size_t boolean_cache_capacity =
38 boolean_cache_words * 64U;
40 char const *m_first =
nullptr;
41 char const *m_last =
nullptr;
42 std::array<std::uint64_t, boolean_cache_words> m_boolean_values{ };
43 std::size_t m_value_index = 0;
44 std::size_t m_value_count = 0;
45 simd_json_classifier_state m_state{ };
46 simd_array_grammar_state m_grammar_state{ };
48 constexpr void append_boolean_values( std::uint64_t values,
50 auto const word = m_value_count / 64U;
51 auto const shift = m_value_count % 64U;
52 m_boolean_values[word] |= values << shift;
53 if( shift != 0U and shift + count > 64U ) {
54 m_boolean_values[word + 1U] = values >> ( 64U - shift );
56 m_value_count += count;
59 constexpr void validate_boolean(
char const *first,
bool value )
const {
60 if constexpr( not ParseState::is_unchecked_input ) {
61 auto parse_state = ParseState( first, m_last );
64 ErrorReason::InvalidLiteral,
66 parse_state.remove_prefix( 4 );
69 ErrorReason::InvalidLiteral,
71 parse_state.remove_prefix( 5 );
73 parse_state.trim_left( );
75 not parse_state.has_more( ) or
76 parse_policy_details::at_end_of_item( parse_state.front( ) ),
77 ErrorReason::InvalidEndOfValue,
82 constexpr void fill_buffer( ) {
83 m_boolean_values = { };
90 while( m_first !=
nullptr and m_first != m_last and
91 m_value_count + block_type::block_size <=
92 boolean_cache_capacity ) {
93 auto const remaining =
static_cast<std::size_t
>( m_last - m_first );
94 auto const block = classifier_type::template classify_bool<
95 not ParseState::is_unchecked_input>(
96 m_first, remaining, m_state );
97 if constexpr( not ParseState::is_unchecked_input ) {
98 auto const unexpected_starts =
99 block.scalar_start & ~block.boolean_start;
100 if( unexpected_starts != 0 ) {
101 auto const lane =
static_cast<std::size_t
>(
102 daw::cxmath::count_trailing_zeros( unexpected_starts ) );
103 auto error_state = ParseState( block.data + lane, m_last );
105 true, ErrorReason::InvalidLiteral, error_state );
107 validate_array_events<ParseState>( block.data,
115 auto const starts = block.boolean_start;
116 auto const block_value_count =
117 static_cast<std::size_t
>( daw::cxmath::popcount( starts ) );
119 if constexpr( not ParseState::is_unchecked_input ) {
120 auto validation_starts = starts;
121 auto values = block.boolean_values;
122 for( std::size_t n = 0;
n < block_value_count; ++
n ) {
123 auto const lane =
static_cast<std::size_t
>(
124 daw::cxmath::count_trailing_zeros( validation_starts ) );
125 validate_boolean( block.data + lane,
126 ( values & std::uint64_t{ 1 } ) != 0 );
127 validation_starts &= validation_starts - 1U;
132 append_boolean_values( block.boolean_values, block_value_count );
133 if( block.array_end != 0 ) {
136 m_first +=
static_cast<std::ptrdiff_t
>( block.size );
139 if constexpr( not ParseState::is_unchecked_input ) {
140 if( m_first !=
nullptr and m_first == m_last ) {
141 validate_array_ended<ParseState>( m_last, m_grammar_state );
147 constexpr json_simd_block_iterator_bool( ) =
default;
149 explicit constexpr json_simd_block_iterator_bool(
150 std::string_view document )
151 : m_first( document.data( ) )
152 , m_last(
std::next( document.data( ), static_cast<
std::ptrdiff_t>(
153 document.size( ) ) ) ) {
154 if( m_first != m_last ) {
155 auto parse_state = ParseState( m_first, m_last );
156 parse_state.trim_left( );
158 ErrorReason::InvalidArrayStart,
160 parse_state.remove_prefix( );
161 m_first = parse_state.data( );
162 m_grammar_state.started =
true;
167 explicit constexpr json_simd_block_iterator_bool(
168 std::string_view document, daw::string_view start_path )
169 : json_simd_block_iterator_bool(
170 find_array_range<ParseState>( document, start_path ) ) {}
172 [[nodiscard]]
constexpr reference operator*( )
const {
174 json_member::literal_as_string ==
175 options::LiteralAsStringOpt::Never,
176 "SIMD boolean iteration does not support literals encoded as "
178 auto const word = m_value_index / 64U;
179 auto const shift = m_value_index % 64U;
181 ( ( m_boolean_values[word] >> shift ) & std::uint64_t{ 1 } ) != 0;
182 using constructor_t = json_constructor_t<json_member>;
184 daw::is_callable_v<constructor_t, bool>,
185 "Unable to construct value with the supplied arguments" );
186 return constructor_t{ }( value );
189 constexpr json_simd_block_iterator_bool &operator++( ) {
190 if( m_value_index < m_value_count ) {
193 if( m_value_index == m_value_count ) {
199 constexpr void operator++(
int ) {
203 [[nodiscard]]
constexpr explicit operator bool( ) const noexcept {
204 return m_value_index < m_value_count;
207 [[nodiscard]]
constexpr json_simd_block_iterator_bool begin( )
const {
211 [[nodiscard]]
constexpr json_simd_block_iterator_bool
static end( ) noexcept {
215 friend constexpr bool
216 operator==( json_simd_block_iterator_bool
const &lhs,
217 json_simd_block_iterator_bool
const &rhs )
noexcept {
218 auto const lhs_at_end = not lhs;
219 auto const rhs_at_end = not rhs;
220 if( lhs_at_end or rhs_at_end ) {
221 return lhs_at_end == rhs_at_end;
223 return lhs.m_first == rhs.m_first and
224 lhs.m_value_index == rhs.m_value_index and
225 lhs.m_value_count == rhs.m_value_count;
228 friend constexpr bool
229 operator!=( json_simd_block_iterator_bool
const &lhs,
230 json_simd_block_iterator_bool
const &rhs )
noexcept {
231 return not( lhs == rhs );
#define daw_json_assert_weak(Bool,...)
Assert that Bool is true when in Checked Input mode If false pass rest of args to daw_json_error.
DAW_ATTRIB_NOINLINE void daw_json_error(bool b, ErrorReason reason)
BasicParsePolicy() -> BasicParsePolicy<>
daw::conditional_t< ParsePolicy::is_default_parse_policy, DefaultParsePolicy, ParsePolicy > TryDefaultParsePolicy
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.