DAW JSON Link
Loading...
Searching...
No Matches
daw_json_parse_array_iterator.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
16
17#include <daw/daw_attributes.h>
18
19#include <type_traits>
20
21namespace daw::json {
22 inline namespace DAW_JSON_VER {
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;
29
30 ParseState *parse_state = nullptr;
31 };
32
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;
37#else
38 using iterator_category = std::random_access_iterator_tag;
39#endif
40 using difference_type = std::ptrdiff_t;
41 static constexpr bool has_counter = true;
42
43 ParseState *parse_state = nullptr;
44 difference_type counter = 0;
45
46 explicit json_parse_array_iterator_base( ) = default;
47
48 explicit constexpr json_parse_array_iterator_base(
49 daw::not_null<ParseState *> pd ) noexcept
50 : parse_state( pd )
51 , counter( static_cast<difference_type>( pd->counter ) ) {}
52
53 constexpr difference_type
54 operator-( json_parse_array_iterator_base const &rhs ) const {
55 // rhs is the iterator with the parser in it. We should know how many
56 // items are in play because we already counted them in the skip_array
57 // call.
58
59 return rhs.counter;
60 }
61 };
62
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>> {
67
68 using base =
69 json_parse_array_iterator_base<ParseState,
70 can_be_random_iterator_v<KnownBounds>>;
71
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;
80
81 json_parse_array_iterator( ) = default;
82#if defined( DAW_JSON_USE_FULL_DEBUG_ITERATORS )
83 // This code requires C++ 20 to be useful in a constant expression as it
84 // requires a non-trivial destructor
85 json_parse_array_iterator( json_parse_array_iterator const & ) =
86 default;
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;
92 DAW_JSON_CPP20_CX_DTOR ~json_parse_array_iterator( ) {
93 if constexpr( base::has_counter ) {
94 daw_json_assert_weak( base::counter == 0,
95 ErrorReason::AttemptToAccessPastEndOfValue );
96 }
97 }
98#endif
101 constexpr explicit json_parse_array_iterator( parse_state_t &r,
102 std::size_t size_hint = 0 )
103 : base{ &r }
104 , m_size_hint( size_hint ) {
105 if( DAW_UNLIKELY( base::parse_state->front( ) == ']' ) ) {
106 if constexpr( not KnownBounds ) {
107 // Cleanup at end of value
108 base::parse_state->remove_prefix( );
109 base::parse_state->trim_left_checked( );
110 // Ensure we are equal to default
111 }
112 base::parse_state = nullptr;
113 }
114 }
115
116 [[noreturn]] DAW_ATTRIB_NOINLINE value_type operator*( ) const {
117 DAW_UNLIKELY_BRANCH
118 // This is hear to satisfy indirectly_readable
119 daw_json_error( true, ErrorReason::UnexpectedEndOfData );
120 }
121
122 DAW_ATTRIB_INLINE constexpr value_type operator*( ) {
123 daw_json_assert_weak( base::parse_state and
124 base::parse_state->has_more( ),
125 ErrorReason::UnexpectedEndOfData,
126 *base::parse_state );
127
128 return parse_value<element_t, false, element_t::expected_type>(
129 *base::parse_state );
130 }
131
132 DAW_ATTRIB_INLINE constexpr json_parse_array_iterator &operator++( ) {
133 daw_json_assert_weak( base::parse_state,
134 ErrorReason::UnexpectedEndOfData,
135 *base::parse_state );
136 base::parse_state->trim_left( );
137
139 base::parse_state->has_more( ) and
140 base::parse_state->is_at_next_array_element( ),
141 ErrorReason::UnexpectedEndOfData,
142 *base::parse_state );
143
144 base::parse_state->move_next_member_or_end( );
145 daw_json_assert_weak( base::parse_state->has_more( ),
146 ErrorReason::UnexpectedEndOfData,
147 *base::parse_state );
148 if( base::parse_state->front( ) == ']' ) {
149#if not defined( NDEBUG )
150 if constexpr( base::has_counter ) {
151 daw_json_assert_weak( base::counter == 0,
152 ErrorReason::AttemptToAccessPastEndOfValue,
153 *base::parse_state );
154 }
155#endif
156 if constexpr( not KnownBounds ) {
157 // Cleanup at end of value
158 base::parse_state->remove_prefix( );
159 base::parse_state->trim_left_checked( );
160 // Ensure we are equal to default
161 }
162 base::parse_state = nullptr;
163 } else {
164#if not defined( NDEBUG )
165 if constexpr( base::has_counter ) {
166 daw_json_assert_weak( base::counter > 0,
167 ErrorReason::AttemptToAccessPastEndOfValue,
168 *base::parse_state );
169 --base::counter;
170 }
171#endif
172 }
173 return *this;
174 }
175
176 DAW_ATTRIB_INLINE constexpr void operator++( int ) {
177 (void)operator++( );
178 }
179
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;
184 }
185
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 );
190 }
191
194 [[nodiscard]] constexpr std::size_t size_hint( ) const {
195 if( m_size_hint != 0 ) {
196 return m_size_hint;
197 }
198 return ParseState::array_reserve_amount;
199 }
200
201 constexpr json_parse_array_iterator &begin( ) {
202 return *this;
203 }
204
205 constexpr json_parse_array_iterator end( ) const {
206 return { };
207 }
208
209 private:
210 std::size_t m_size_hint = 0;
211 };
212
213#if defined( DAW_JSON_HAS_CPP23_RANGE_CTOR )
217 struct json_parse_array_sized_end {};
218
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;
229
230 Iterator m_iterator{ };
231 difference_type m_remaining = 0;
232
233 json_parse_array_counted_iterator( ) = default;
234
235 explicit constexpr json_parse_array_counted_iterator(
236 Iterator it, difference_type count )
237 : m_iterator( std::move( it ) )
238 , m_remaining( count ) {}
239
240 DAW_ATTRIB_INLINE constexpr reference operator*( ) {
241 return *m_iterator;
242 }
243
244 DAW_ATTRIB_INLINE constexpr reference operator*( ) const {
245 return *m_iterator;
246 }
247
248 DAW_ATTRIB_INLINE constexpr json_parse_array_counted_iterator &
249 operator++( ) {
250 ++m_iterator;
251 --m_remaining;
252 return *this;
253 }
254
255 DAW_ATTRIB_INLINE constexpr void operator++( int ) {
256 (void)operator++( );
257 }
258
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( );
263 }
264
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;
269 }
270
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;
275 }
276 };
277#endif
278 } // namespace json_details
279 } // namespace DAW_JSON_VER
280} // namespace daw::json
#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.
#define DAW_JSON_CPP20_CX_DTOR
DAW_ATTRIB_NOINLINE void daw_json_error(bool b, ErrorReason reason)
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20