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
99 constexpr explicit json_parse_array_iterator( parse_state_t &r )
100 : base{ &r } {
101 if( DAW_UNLIKELY( base::parse_state->front( ) == ']' ) ) {
102 if constexpr( not KnownBounds ) {
103 // Cleanup at end of value
104 base::parse_state->remove_prefix( );
105 base::parse_state->trim_left_checked( );
106 // Ensure we are equal to default
107 }
108 base::parse_state = nullptr;
109 }
110 }
111
112 [[noreturn]] DAW_ATTRIB_NOINLINE value_type operator*( ) const {
113 DAW_UNLIKELY_BRANCH
114 // This is hear to satisfy indirectly_readable
115 daw_json_error( true, ErrorReason::UnexpectedEndOfData );
116 }
117
118 DAW_ATTRIB_INLINE constexpr value_type operator*( ) {
119 daw_json_assert_weak( base::parse_state and
120 base::parse_state->has_more( ),
121 ErrorReason::UnexpectedEndOfData,
122 *base::parse_state );
123
124 return parse_value<element_t, false, element_t::expected_type>(
125 *base::parse_state );
126 }
127
128 DAW_ATTRIB_INLINE constexpr json_parse_array_iterator &operator++( ) {
129 daw_json_assert_weak( base::parse_state,
130 ErrorReason::UnexpectedEndOfData,
131 *base::parse_state );
132 base::parse_state->trim_left( );
133
135 base::parse_state->has_more( ) and
136 base::parse_state->is_at_next_array_element( ),
137 ErrorReason::UnexpectedEndOfData,
138 *base::parse_state );
139
140 base::parse_state->move_next_member_or_end( );
141 daw_json_assert_weak( base::parse_state->has_more( ),
142 ErrorReason::UnexpectedEndOfData,
143 *base::parse_state );
144 if( base::parse_state->front( ) == ']' ) {
145#if not defined( NDEBUG )
146 if constexpr( base::has_counter ) {
147 daw_json_assert_weak( base::counter == 0,
148 ErrorReason::AttemptToAccessPastEndOfValue,
149 *base::parse_state );
150 }
151#endif
152 if constexpr( not KnownBounds ) {
153 // Cleanup at end of value
154 base::parse_state->remove_prefix( );
155 base::parse_state->trim_left_checked( );
156 // Ensure we are equal to default
157 }
158 base::parse_state = nullptr;
159 } else {
160#if not defined( NDEBUG )
161 if constexpr( base::has_counter ) {
162 daw_json_assert_weak( base::counter > 0,
163 ErrorReason::AttemptToAccessPastEndOfValue,
164 *base::parse_state );
165 --base::counter;
166 }
167#endif
168 }
169 return *this;
170 }
171
172 DAW_ATTRIB_INLINE constexpr void operator++( int ) {
173 (void)operator++( );
174 }
175
176 friend inline constexpr bool
177 operator==( json_parse_array_iterator const &lhs,
178 json_parse_array_iterator const &rhs ) {
179 return lhs.parse_state == rhs.parse_state;
180 }
181
182 friend inline constexpr bool
183 operator!=( json_parse_array_iterator const &lhs,
184 json_parse_array_iterator const &rhs ) {
185 return not( lhs == rhs );
186 }
187
188 constexpr json_parse_array_iterator &begin( ) {
189 return *this;
190 }
191
192 constexpr json_parse_array_iterator end( ) const {
193 return { };
194 }
195 };
196 } // namespace json_details
197 } // namespace DAW_JSON_VER
198} // 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)
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20