39 namespace json_details {
40 template<
typename ParseState,
bool >
41 struct json_parse_array_sse42_iterator_base {
42 using iterator_category = std::input_iterator_tag;
43 using difference_type = std::ptrdiff_t;
44 static constexpr bool has_counter =
false;
46 ParseState *parse_state =
nullptr;
49 template<
typename ParseState>
50 struct json_parse_array_sse42_iterator_base<ParseState, true> {
51 using iterator_category = std::input_iterator_tag;
52 using difference_type = std::ptrdiff_t;
53 static constexpr bool has_counter =
true;
55 daw::not_null<ParseState *> parse_state;
56 difference_type counter = 0;
58 explicit constexpr json_parse_array_sse42_iterator_base(
59 daw::not_null<ParseState *> pd ) noexcept
61 , counter(
static_cast<difference_type
>( pd->counter ) ) {}
63 constexpr difference_type
64 operator-( json_parse_array_sse42_iterator_base
const &rhs )
const {
73 template<
typename JsonMember,
typename ParseState,
bool KnownBounds>
74 struct json_parse_array_sse42_iterator
75 : json_parse_array_sse42_iterator_base<
76 ParseState, can_be_random_iterator_v<KnownBounds>> {
78 using base = json_parse_array_sse42_iterator_base<
79 ParseState, can_be_random_iterator_v<KnownBounds>>;
81 using iterator_category =
typename base::iterator_category;
82 using element_t =
typename JsonMember::json_element_t;
83 using value_type = json_result_t<element_t>;
84 using reference = value_type;
85 using pointer = arrow_proxy<value_type>;
86 using parse_state_t = ParseState;
87 using difference_type =
typename base::difference_type;
88 using size_type = std::size_t;
90 json_parse_array_sse42_iterator( ) =
default;
91#if defined( DAW_JSON_USE_FULL_DEBUG_ITERATORS )
94 json_parse_array_sse42_iterator(
95 json_parse_array_sse42_iterator
const & ) =
default;
97 json_parse_array_sse42_iterator &
98 operator=( json_parse_array_sse42_iterator
const & ) =
default;
100 json_parse_array_sse42_iterator( json_parse_array_sse42_iterator && ) =
103 json_parse_array_sse42_iterator &
104 operator=( json_parse_array_sse42_iterator && ) =
default;
107 if constexpr( base::has_counter ) {
109 ErrorReason::AttemptToAccessPastEndOfValue );
116 std::uint32_t array_boundaries_mask = 0;
117 std::uint32_t whitespace_mask = 0;
120 static auto get_masks( daw::not_null<char const *> ptr ) {
121 static constexpr std::size_t sse_array_boundaries_sz = 2;
122 static auto const sse_array_boundaries = uload16_char_data_simd(
123 ( std::array<char, 16>{
',',
']' } ).data( ) );
124 static constexpr std::size_t sse_whitespace_sz = 4;
125 static auto const sse_whitespace = uload16_char_data_simd(
126 ( std::array<char, 16>{
' ',
'\t',
'\n',
'\r' } ).data( ) );
128 auto const text_chunk = uload16_char_data_simd( ptr );
129 auto const array_boundaries_mask_reg = _mm_cmpestrm(
130 sse_array_boundaries,
131 sse_array_boundaries_sz,
134 _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK );
135 auto const whitespace_mask_reg = _mm_cmpestrm(
140 _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK );
142 return masks_t{
static_cast<std::uint32_t
>(
143 _mm_extract_epi16( array_boundaries_mask_reg, 0 ) ),
144 static_cast<std::uint32_t
>(
145 _mm_extract_epi16( whitespace_mask_reg, 0 ) ) };
149 std::size_t m_first_offset = 0;
152 explicit json_parse_array_sse42_iterator( parse_state_t &r )
154 if( DAW_UNLIKELY( base::parse_state->front( ) ==
']' ) ) {
155 if constexpr( not KnownBounds ) {
157 base::parse_state->remove_prefix( );
158 base::parse_state->trim_left_checked( );
161 base::parse_state =
nullptr;
164 if( base::parse_state->size( ) < 16 ) {
167 m_masks = get_mask( base::parse_state->first );
168 if( m_masks.array_boundaries_mask != 0 ) {}
171 [[noreturn]] DAW_ATTRIB_NOINLINE value_type operator*( )
const {
177 DAW_ATTRIB_INLINE
constexpr value_type operator*( ) {
179 base::parse_state->has_more( ),
180 ErrorReason::UnexpectedEndOfData,
181 *base::parse_state );
183 return parse_value<element_t, false, element_t::expected_type>(
184 *base::parse_state );
187 DAW_ATTRIB_INLINE
constexpr json_parse_array_sse42_iterator &
190 ErrorReason::UnexpectedEndOfData,
191 *base::parse_state );
192 base::parse_state->trim_left( );
195 base::parse_state->has_more( ) and
196 base::parse_state->is_at_next_array_element( ),
197 ErrorReason::UnexpectedEndOfData,
198 *base::parse_state );
200 base::parse_state->move_next_member_or_end( );
202 ErrorReason::UnexpectedEndOfData,
203 *base::parse_state );
204 if( base::parse_state->front( ) ==
']' ) {
205#if not defined( NDEBUG )
206 if constexpr( base::has_counter ) {
208 ErrorReason::AttemptToAccessPastEndOfValue,
209 *base::parse_state );
212 if constexpr( not KnownBounds ) {
214 base::parse_state->remove_prefix( );
215 base::parse_state->trim_left_checked( );
218 base::parse_state =
nullptr;
220#if not defined( NDEBUG )
221 if constexpr( base::has_counter ) {
223 ErrorReason::AttemptToAccessPastEndOfValue,
224 *base::parse_state );
232 DAW_ATTRIB_INLINE
constexpr void operator++(
int ) {
236 friend inline constexpr bool
237 operator==( json_parse_array_sse42_iterator
const &lhs,
238 json_parse_array_sse42_iterator
const &rhs ) {
239 return lhs.parse_state == rhs.parse_state;
242 friend inline constexpr bool
243 operator!=( json_parse_array_sse42_iterator
const &lhs,
244 json_parse_array_sse42_iterator
const &rhs ) {
245 return not( lhs == rhs );
248 constexpr json_parse_array_sse42_iterator &begin( ) {
252 constexpr json_parse_array_sse42_iterator end( )
const {