23 namespace json_details {
24 template<
typename ParseState,
bool>
25 struct json_parse_array_iterator_base {
26 using iterator_category = std::input_iterator_tag;
27 using difference_type = std::ptrdiff_t;
28 static constexpr bool has_counter =
false;
30 ParseState *parse_state =
nullptr;
33 template<
typename ParseState>
34 struct json_parse_array_iterator_base<ParseState, true> {
35#if defined( DAW_JSON_HAS_CPP23_RANGE_CTOR )
36 using iterator_category = std::input_iterator_tag;
38 using iterator_category = std::random_access_iterator_tag;
40 using difference_type = std::ptrdiff_t;
41 static constexpr bool has_counter =
true;
43 ParseState *parse_state =
nullptr;
44 difference_type counter = 0;
46 explicit json_parse_array_iterator_base( ) =
default;
48 explicit constexpr json_parse_array_iterator_base(
49 daw::not_null<ParseState *> pd ) noexcept
51 , counter(
static_cast<difference_type
>( pd->counter ) ) {}
53 constexpr difference_type
54 operator-( json_parse_array_iterator_base
const &rhs )
const {
63 template<
typename JsonMember,
typename ParseState,
bool KnownBounds>
64 struct json_parse_array_iterator
65 : json_parse_array_iterator_base<
66 ParseState, can_be_random_iterator_v<KnownBounds>> {
69 json_parse_array_iterator_base<ParseState,
70 can_be_random_iterator_v<KnownBounds>>;
72 using iterator_category =
typename base::iterator_category;
73 using element_t =
typename JsonMember::json_element_t;
74 using value_type = json_result_t<element_t>;
75 using reference = value_type;
76 using pointer = arrow_proxy<value_type>;
77 using parse_state_t = ParseState;
78 using difference_type =
typename base::difference_type;
79 using size_type = std::size_t;
81 json_parse_array_iterator( ) =
default;
82#if defined( DAW_JSON_USE_FULL_DEBUG_ITERATORS )
85 json_parse_array_iterator( json_parse_array_iterator
const & ) =
87 json_parse_array_iterator &
88 operator=( json_parse_array_iterator
const & ) =
default;
89 json_parse_array_iterator( json_parse_array_iterator && ) =
default;
90 json_parse_array_iterator &
91 operator=( json_parse_array_iterator && ) =
default;
93 if constexpr( base::has_counter ) {
95 ErrorReason::AttemptToAccessPastEndOfValue );
101 constexpr explicit json_parse_array_iterator( parse_state_t &r,
102 std::size_t size_hint = 0 )
104 , m_size_hint( size_hint ) {
105 if( DAW_UNLIKELY( base::parse_state->front( ) ==
']' ) ) {
106 if constexpr( not KnownBounds ) {
108 base::parse_state->remove_prefix( );
109 base::parse_state->trim_left_checked( );
112 base::parse_state =
nullptr;
116 [[noreturn]] DAW_ATTRIB_NOINLINE value_type operator*( )
const {
122 DAW_ATTRIB_INLINE
constexpr value_type operator*( ) {
124 base::parse_state->has_more( ),
125 ErrorReason::UnexpectedEndOfData,
126 *base::parse_state );
128 return parse_value<element_t, false, element_t::expected_type>(
129 *base::parse_state );
132 DAW_ATTRIB_INLINE
constexpr json_parse_array_iterator &operator++( ) {
134 ErrorReason::UnexpectedEndOfData,
135 *base::parse_state );
136 base::parse_state->trim_left( );
139 base::parse_state->has_more( ) and
140 base::parse_state->is_at_next_array_element( ),
141 ErrorReason::UnexpectedEndOfData,
142 *base::parse_state );
144 base::parse_state->move_next_member_or_end( );
146 ErrorReason::UnexpectedEndOfData,
147 *base::parse_state );
148 if( base::parse_state->front( ) ==
']' ) {
149#if not defined( NDEBUG )
150 if constexpr( base::has_counter ) {
152 ErrorReason::AttemptToAccessPastEndOfValue,
153 *base::parse_state );
156 if constexpr( not KnownBounds ) {
158 base::parse_state->remove_prefix( );
159 base::parse_state->trim_left_checked( );
162 base::parse_state =
nullptr;
164#if not defined( NDEBUG )
165 if constexpr( base::has_counter ) {
167 ErrorReason::AttemptToAccessPastEndOfValue,
168 *base::parse_state );
176 DAW_ATTRIB_INLINE
constexpr void operator++(
int ) {
180 friend inline constexpr bool
181 operator==( json_parse_array_iterator
const &lhs,
182 json_parse_array_iterator
const &rhs ) {
183 return lhs.parse_state == rhs.parse_state;
186 friend inline constexpr bool
187 operator!=( json_parse_array_iterator
const &lhs,
188 json_parse_array_iterator
const &rhs ) {
189 return not( lhs == rhs );
194 [[nodiscard]]
constexpr std::size_t size_hint( )
const {
195 if( m_size_hint != 0 ) {
198 return ParseState::array_reserve_amount;
201 constexpr json_parse_array_iterator &begin( ) {
205 constexpr json_parse_array_iterator end( )
const {
210 std::size_t m_size_hint = 0;
213#if defined( DAW_JSON_HAS_CPP23_RANGE_CTOR )
217 struct json_parse_array_sized_end {};
222 template<
typename Iterator>
223 struct json_parse_array_counted_iterator {
224 using iterator_concept = std::input_iterator_tag;
225 using iterator_category = std::input_iterator_tag;
226 using value_type =
typename Iterator::value_type;
227 using reference =
typename Iterator::reference;
228 using difference_type = std::ptrdiff_t;
230 Iterator m_iterator{ };
231 difference_type m_remaining = 0;
233 json_parse_array_counted_iterator( ) =
default;
235 explicit constexpr json_parse_array_counted_iterator(
236 Iterator it, difference_type count )
237 : m_iterator( std::move( it ) )
238 , m_remaining( count ) {}
240 DAW_ATTRIB_INLINE
constexpr reference operator*( ) {
244 DAW_ATTRIB_INLINE
constexpr reference operator*( )
const {
248 DAW_ATTRIB_INLINE
constexpr json_parse_array_counted_iterator &
255 DAW_ATTRIB_INLINE
constexpr void operator++(
int ) {
259 friend constexpr bool
260 operator==( json_parse_array_counted_iterator
const &it,
261 json_parse_array_sized_end ) {
262 return it.m_iterator == Iterator( );
265 friend constexpr difference_type
266 operator-( json_parse_array_sized_end,
267 json_parse_array_counted_iterator
const &it ) {
268 return it.m_remaining;
271 friend constexpr difference_type
272 operator-( json_parse_array_counted_iterator
const &it,
273 json_parse_array_sized_end ) {
274 return -it.m_remaining;