13#if defined( DAW_JSON_HAS_SIMD )
17 namespace json_details::simd_details {
18 template<
typename JsonMember,
19 std::size_t NumberSpanCacheBlocks =
20 ( JsonMember::expected_type == JsonParseTypes::Real ? 8U
22 typename CharT =
char,
auto... PolicyFlags>
23 class json_simd_number_block_iterator {
24 static_assert( NumberSpanCacheBlocks > 0 );
26 options::details::make_parse_flags<PolicyFlags...>( ).value>>;
27 using classifier_type =
28 simd_json_classifier<JsonBaseParseTypes::Number, CharT>;
29 using block_type = simd_json_block<JsonBaseParseTypes::Number, CharT>;
30 static constexpr auto number_type = JsonMember::expected_type;
31 static_assert( number_type == JsonParseTypes::Real or
32 number_type == JsonParseTypes::Signed or
33 number_type == JsonParseTypes::Unsigned );
34 using span_types = simd_number_span_types<number_type>;
35 using span_type =
typename span_types::span;
36 using pending_span_type =
typename span_types::pending_span;
37 static constexpr std::size_t number_span_capacity =
38 block_type::number_span_capacity * NumberSpanCacheBlocks;
40 struct raw_number_json_member : JsonMember {
41 using parse_to_t =
typename JsonMember::wrapped_type;
42 using constructor_t = default_constructor<parse_to_t>;
46 using json_member = JsonMember;
47 using value_type =
typename json_member::parse_to_t;
48 using reference = value_type;
49 using difference_type = std::ptrdiff_t;
50 using iterator_category = std::input_iterator_tag;
53 char const *m_first =
nullptr;
54 char const *m_last =
nullptr;
55 std::array<span_type, number_span_capacity> m_number_spans{ };
56 std::size_t m_value_index = 0;
57 std::size_t m_value_count = 0;
58 simd_json_classifier_state m_state{ };
59 simd_array_grammar_state m_grammar_state{ };
60 pending_span_type m_pending_number{ };
62 DAW_JSON_SIMD_CONSTEXPR
void fill_buffer( ) {
65 while( m_first !=
nullptr and m_first != m_last and
66 m_value_count + block_type::number_span_capacity <=
67 m_number_spans.size( ) ) {
68 auto const remaining =
static_cast<std::size_t
>( m_last - m_first );
69 auto const block = classifier_type::template classify_number<
71 not ParseState::is_unchecked_input>( m_first,
77 if constexpr( not ParseState::is_unchecked_input ) {
78 auto const unexpected_starts =
79 block.scalar_start & ~block.number_start;
80 if( unexpected_starts != 0 ) {
81 auto const lane =
static_cast<std::size_t
>(
82 daw::cxmath::count_trailing_zeros( unexpected_starts ) );
83 auto error_state = ParseState( block.data + lane, m_last );
85 true, ErrorReason::InvalidNumberStart, error_state );
87 if( block.invalid_number_characters != 0 ) {
89 static_cast<std::size_t
>( daw::cxmath::count_trailing_zeros(
90 block.invalid_number_characters ) );
91 auto error_state = ParseState( block.data + lane, m_last );
94 validate_array_events<ParseState>( block.data,
101 m_value_count += block.number_span_count;
102 if( block.array_end != 0 ) {
103 m_pending_number = { };
106 m_first +=
static_cast<std::ptrdiff_t
>( block.size );
109 if constexpr( not ParseState::is_unchecked_input ) {
110 if( m_first !=
nullptr and m_first == m_last ) {
111 validate_array_ended<ParseState>( m_last, m_grammar_state );
117 json_simd_number_block_iterator( ) =
default;
119 explicit DAW_JSON_SIMD_CONSTEXPR
120 json_simd_number_block_iterator( std::string_view document )
121 : m_first( document.data( ) )
122 , m_last(
std::next( document.data( ), static_cast<
std::ptrdiff_t>(
123 document.size( ) ) ) ) {
124 if( m_first != m_last ) {
125 auto parse_state = ParseState( m_first, m_last );
126 parse_state.trim_left( );
128 ErrorReason::InvalidArrayStart,
130 parse_state.remove_prefix( );
131 m_first = parse_state.data( );
132 m_grammar_state.started =
true;
137 explicit DAW_JSON_SIMD_CONSTEXPR
138 json_simd_number_block_iterator( std::string_view document,
139 daw::string_view start_path )
140 : json_simd_number_block_iterator(
141 find_array_range<ParseState>( document, start_path ) ) {}
143 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR reference operator*( )
const {
144 auto const &span = m_number_spans[m_value_index];
145 auto parse_state = [&] {
146 if constexpr( number_type == JsonParseTypes::Real ) {
147 return ParseState( span.first,
150 span.exponent_marker );
152 return ParseState( span.first, span.last );
156 json_details::parse_value<raw_number_json_member,
158 raw_number_json_member::expected_type>(
160 using constructor_t = json_constructor_t<json_member>;
162 daw::is_callable_v<constructor_t, bool>,
163 "Unable to construct value with the supplied arguments" );
164 return constructor_t{ }( value );
167 DAW_JSON_SIMD_CONSTEXPR json_simd_number_block_iterator &operator++( ) {
168 if( m_value_index < m_value_count ) {
171 if( m_value_index == m_value_count ) {
177 DAW_JSON_SIMD_CONSTEXPR
void operator++(
int ) {
181 [[nodiscard]]
explicit DAW_JSON_SIMD_CONSTEXPR
182 operator bool( ) const noexcept {
183 return m_value_index < m_value_count;
186 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR json_simd_number_block_iterator
191 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR
192 json_simd_number_block_iterator
static end( ) noexcept {
196 friend DAW_JSON_SIMD_CONSTEXPR
bool
197 operator==( json_simd_number_block_iterator
const &lhs,
198 json_simd_number_block_iterator
const &rhs )
noexcept {
199 auto const lhs_at_end = not lhs;
200 auto const rhs_at_end = not rhs;
202 if( lhs_at_end or rhs_at_end ) {
203 return lhs_at_end == rhs_at_end;
205 return lhs.m_number_spans[lhs.m_value_index].first ==
206 rhs.m_number_spans[rhs.m_value_index].first;
209 friend DAW_JSON_SIMD_CONSTEXPR
bool
210 operator!=( json_simd_number_block_iterator
const &lhs,
211 json_simd_number_block_iterator
const &rhs )
noexcept {
212 return not( lhs == rhs );
216 template<
typename JsonMember,
typename CharT,
auto... PolicyFlags>
217 class json_simd_block_iterator_number
218 :
public json_details::simd_details::json_simd_number_block_iterator<
220 ( JsonMember::expected_type == JsonParseTypes::Real ? 8U : 4U ),
221 CharT, PolicyFlags...> {
222 static_assert( JsonMember::underlying_json_type ==
223 JsonBaseParseTypes::Number );
225 json_details::simd_details::json_simd_number_block_iterator<
227 ( JsonMember::expected_type == JsonParseTypes::Real ? 8U : 4U ),
228 CharT, PolicyFlags...>;
#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.