DAW JSON Link
Loading...
Searching...
No Matches
daw_json_simd_iterator_number.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
12
13#if defined( DAW_JSON_HAS_SIMD )
14
15namespace daw::json {
16 inline namespace DAW_JSON_VER {
17 namespace json_details::simd_details {
18 template<typename JsonMember,
19 std::size_t NumberSpanCacheBlocks =
20 ( JsonMember::expected_type == JsonParseTypes::Real ? 8U
21 : 4U ),
22 typename CharT = char, auto... PolicyFlags>
23 class json_simd_number_block_iterator {
24 static_assert( NumberSpanCacheBlocks > 0 );
25 using ParseState = TryDefaultParsePolicy<BasicParsePolicy<
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;
39
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>;
43 };
44
45 public:
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;
51
52 private:
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{ };
61
62 DAW_JSON_SIMD_CONSTEXPR void fill_buffer( ) {
63 m_value_index = 0;
64 m_value_count = 0;
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<
70 number_type,
71 not ParseState::is_unchecked_input>( m_first,
72 remaining,
73 m_state,
74 m_number_spans,
75 m_pending_number,
76 m_value_count );
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 );
86 }
87 if( block.invalid_number_characters != 0 ) {
88 auto const lane =
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 );
92 daw_json_error( true, ErrorReason::InvalidNumber, error_state );
93 }
94 validate_array_events<ParseState>( block.data,
95 m_last,
96 block.number_start,
97 block.comma,
98 block.array_end,
99 m_grammar_state );
100 }
101 m_value_count += block.number_span_count;
102 if( block.array_end != 0 ) {
103 m_pending_number = { };
104 m_first = m_last;
105 } else {
106 m_first += static_cast<std::ptrdiff_t>( block.size );
107 }
108 }
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 );
112 }
113 }
114 }
115
116 public:
117 json_simd_number_block_iterator( ) = default;
118
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( );
127 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
128 ErrorReason::InvalidArrayStart,
129 parse_state );
130 parse_state.remove_prefix( );
131 m_first = parse_state.data( );
132 m_grammar_state.started = true;
133 }
134 fill_buffer( );
135 }
136
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 ) ) {}
142
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,
148 span.last,
149 span.decimal_point,
150 span.exponent_marker );
151 } else {
152 return ParseState( span.first, span.last );
153 }
154 }( );
155 auto value =
156 json_details::parse_value<raw_number_json_member,
157 true,
158 raw_number_json_member::expected_type>(
159 parse_state );
160 using constructor_t = json_constructor_t<json_member>;
161 static_assert(
162 daw::is_callable_v<constructor_t, bool>,
163 "Unable to construct value with the supplied arguments" );
164 return constructor_t{ }( value );
165 }
166
167 DAW_JSON_SIMD_CONSTEXPR json_simd_number_block_iterator &operator++( ) {
168 if( m_value_index < m_value_count ) {
169 ++m_value_index;
170 }
171 if( m_value_index == m_value_count ) {
172 fill_buffer( );
173 }
174 return *this;
175 }
176
177 DAW_JSON_SIMD_CONSTEXPR void operator++( int ) {
178 (void)operator++( );
179 }
180
181 [[nodiscard]] explicit DAW_JSON_SIMD_CONSTEXPR
182 operator bool( ) const noexcept {
183 return m_value_index < m_value_count;
184 }
185
186 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR json_simd_number_block_iterator
187 begin( ) const {
188 return *this;
189 }
190
191 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR
192 json_simd_number_block_iterator static end( ) noexcept {
193 return { };
194 }
195
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;
201
202 if( lhs_at_end or rhs_at_end ) {
203 return lhs_at_end == rhs_at_end;
204 }
205 return lhs.m_number_spans[lhs.m_value_index].first ==
206 rhs.m_number_spans[rhs.m_value_index].first;
207 }
208
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 );
213 }
214 };
215
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<
219 JsonMember,
220 ( JsonMember::expected_type == JsonParseTypes::Real ? 8U : 4U ),
221 CharT, PolicyFlags...> {
222 static_assert( JsonMember::underlying_json_type ==
223 JsonBaseParseTypes::Number );
224 using base =
225 json_details::simd_details::json_simd_number_block_iterator<
226 JsonMember,
227 ( JsonMember::expected_type == JsonParseTypes::Real ? 8U : 4U ),
228 CharT, PolicyFlags...>;
229
230 public:
231 using base::base;
232 };
233 } // namespace json_details::simd_details
234 } // namespace DAW_JSON_VER
235} // namespace daw::json
236
237#endif
#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)
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.
Definition version.h:20