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_string {
20 static_assert( JsonMember::underlying_json_type ==
21 JsonBaseParseTypes::String );
23 options::details::make_parse_flags<PolicyFlags...>( ).value>>;
24 using classifier_type =
25 simd_json_classifier<JsonBaseParseTypes::String, CharT>;
28 using json_member = JsonMember;
29 using value_type =
typename json_member::parse_to_t;
30 using reference = value_type;
31 using difference_type = std::ptrdiff_t;
32 using iterator_category = std::input_iterator_tag;
35 char const *m_first =
nullptr;
36 char const *m_last =
nullptr;
37 char const *m_current =
nullptr;
38 char const *m_current_end =
nullptr;
39 char const *m_current_escape =
nullptr;
40 char const *m_block_data =
nullptr;
41 std::uint64_t m_value_starts = 0;
42 std::uint64_t m_string_ends = 0;
43 std::uint64_t m_escape_characters = 0;
44 simd_json_classifier_state m_state{ };
45 simd_array_grammar_state m_grammar_state{ };
47 [[nodiscard]]
constexpr bool classify_next_block( ) {
48 if( m_first ==
nullptr or m_first == m_last ) {
49 if constexpr( not ParseState::is_unchecked_input ) {
50 if( m_first !=
nullptr ) {
51 validate_array_ended<ParseState>( m_last, m_grammar_state );
57 auto const remaining =
static_cast<std::size_t
>( m_last - m_first );
58 auto const block = classifier_type::template classify_string<
59 not ParseState::is_unchecked_input>( m_first, remaining, m_state );
60 m_block_data = block.data;
61 m_value_starts = block.string_start;
62 m_string_ends = block.string_end;
63 m_escape_characters = block.escape_characters;
64 if constexpr( not ParseState::is_unchecked_input ) {
65 auto const unexpected_starts = block.scalar_start & ~m_value_starts;
66 if( unexpected_starts != 0 ) {
67 auto const lane =
static_cast<std::size_t
>(
68 daw::cxmath::count_trailing_zeros( unexpected_starts ) );
69 auto error_state = ParseState( block.data + lane, m_last );
72 validate_array_events<ParseState>( block.data,
79 if( block.array_end != 0 ) {
82 m_first +=
static_cast<std::ptrdiff_t
>( block.size );
87 constexpr void move_to_next_value( ) {
88 while( m_value_starts == 0 ) {
89 if( not classify_next_block( ) ) {
91 m_current_end =
nullptr;
92 m_current_escape =
nullptr;
97 auto const lane =
static_cast<std::size_t
>(
98 daw::cxmath::count_trailing_zeros( m_value_starts ) );
99 m_value_starts &= m_value_starts - 1U;
100 m_current = m_block_data + lane;
101 m_current_escape =
nullptr;
103 auto first_lane = lane + 1U;
105 if( m_string_ends != 0 ) {
106 auto const end_lane =
static_cast<std::size_t
>(
107 daw::cxmath::count_trailing_zeros( m_string_ends ) );
108 auto const escapes = m_escape_characters &
109 simd_details::low_bits( end_lane ) &
110 ~simd_details::low_bits( first_lane );
111 if( m_current_escape ==
nullptr and escapes != 0 ) {
113 m_block_data + daw::cxmath::count_trailing_zeros( escapes );
115 m_string_ends &= m_string_ends - 1U;
116 m_current_end = m_block_data + end_lane;
121 m_escape_characters & ~simd_details::low_bits( first_lane );
122 if( m_current_escape ==
nullptr and escapes != 0 ) {
124 m_block_data + daw::cxmath::count_trailing_zeros( escapes );
126 if( not classify_next_block( ) ) {
127 auto error_state = ParseState( m_current, m_last );
135 constexpr json_simd_block_iterator_string( ) =
default;
137 explicit constexpr json_simd_block_iterator_string(
138 std::string_view document )
139 : m_first( document.data( ) )
140 , m_last(
std::next( document.data( ), static_cast<
std::ptrdiff_t>(
141 document.size( ) ) ) ) {
142 if( m_first != m_last ) {
143 auto parse_state = ParseState( m_first, m_last );
144 parse_state.trim_left( );
146 ErrorReason::InvalidArrayStart,
148 parse_state.remove_prefix( );
149 m_first = parse_state.data( );
150 m_grammar_state.started =
true;
152 move_to_next_value( );
155 explicit constexpr json_simd_block_iterator_string(
156 std::string_view document, daw::string_view start_path )
157 : json_simd_block_iterator_string(
158 find_array_range<ParseState>( document, start_path ) ) {}
160 [[nodiscard]]
constexpr reference operator*( )
const {
161 auto parse_state = ParseState( m_current + 1, m_current_end );
162 parse_state.counter = m_current_escape ==
nullptr
163 ?
static_cast<std::size_t
>( -1 )
164 : static_cast<
std::size_t>(
165 m_current_escape - ( m_current + 1 ) );
166 return json_details::
167 parse_value<json_member, true, json_member::expected_type>(
171 constexpr json_simd_block_iterator_string &operator++( ) {
172 move_to_next_value( );
176 constexpr void operator++(
int ) {
180 [[nodiscard]]
constexpr explicit operator bool( ) const noexcept {
181 return m_current !=
nullptr;
184 [[nodiscard]]
constexpr json_simd_block_iterator_string begin( )
const {
188 [[nodiscard]]
constexpr json_simd_block_iterator_string
static end( ) noexcept {
192 friend constexpr bool
193 operator==( json_simd_block_iterator_string
const &lhs,
194 json_simd_block_iterator_string
const &rhs )
noexcept {
195 auto const lhs_at_end = lhs.m_current ==
nullptr;
196 auto const rhs_at_end = rhs.m_current ==
nullptr;
197 if( lhs_at_end or rhs_at_end ) {
198 return lhs_at_end == rhs_at_end;
200 return lhs.m_current == rhs.m_current;
203 friend constexpr bool
204 operator!=( json_simd_block_iterator_string
const &lhs,
205 json_simd_block_iterator_string
const &rhs )
noexcept {
206 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.