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
11#include "version.h"
12
14#include "daw_json_assert.h"
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 DAW_ATTRIB_NONNULL( )
49 explicit constexpr json_parse_array_iterator_base(
50 ParseState *pd ) noexcept
51 : parse_state( pd )
52 , counter( static_cast<difference_type>( pd->counter ) ) {}
53
54 constexpr difference_type
55 operator-( json_parse_array_iterator_base const &rhs ) const {
56 // rhs is the iterator with the parser in it. We should know how many
57 // items are in play because we already counted them in the skip_array
58 // call.
59
60 return rhs.counter;
61 }
62 };
63
64 template<typename JsonMember, typename ParseState, bool KnownBounds>
65 struct json_parse_array_iterator
66 : json_parse_array_iterator_base<
67 ParseState, can_be_random_iterator_v<KnownBounds>> {
68
69 using base =
70 json_parse_array_iterator_base<ParseState,
71 can_be_random_iterator_v<KnownBounds>>;
72
73 using iterator_category = typename base::iterator_category;
74 using element_t = typename JsonMember::json_element_t;
75 using value_type = json_result_t<element_t>;
76 using reference = value_type;
77 using pointer = arrow_proxy<value_type>;
78 using parse_state_t = ParseState;
79 using difference_type = typename base::difference_type;
80 using size_type = std::size_t;
81
82 json_parse_array_iterator( ) = default;
83#if defined( DAW_JSON_USE_FULL_DEBUG_ITERATORS )
84 // This code requires C++ 20 to be useful in a constant expression as it
85 // requires a non-trivial destructor
86 json_parse_array_iterator( json_parse_array_iterator const & ) =
87 default;
88 json_parse_array_iterator &
89 operator=( json_parse_array_iterator const & ) = default;
90 json_parse_array_iterator( json_parse_array_iterator && ) = default;
91 json_parse_array_iterator &
92 operator=( json_parse_array_iterator && ) = default;
93 DAW_JSON_CPP20_CX_DTOR ~json_parse_array_iterator( ) {
94 if constexpr( base::has_counter ) {
95 daw_json_assert_weak( base::counter == 0,
96 ErrorReason::AttemptToAccessPastEndOfValue );
97 }
98 }
99#endif
100 constexpr explicit json_parse_array_iterator( parse_state_t &r )
101 : base{ &r } {
102 if( DAW_UNLIKELY( base::parse_state->front( ) == ']' ) ) {
103 if constexpr( not KnownBounds ) {
104 // Cleanup at end of value
105 base::parse_state->remove_prefix( );
106 base::parse_state->trim_left_checked( );
107 // Ensure we are equal to default
108 }
109 base::parse_state = nullptr;
110 }
111 }
112
113 [[noreturn]] DAW_ATTRIB_NOINLINE value_type operator*( ) const {
114 DAW_UNLIKELY_BRANCH
115 // This is hear to satisfy indirectly_readable
116 daw_json_error( ErrorReason::UnexpectedEndOfData );
117 }
118
119 DAW_ATTRIB_INLINE constexpr value_type operator*( ) {
120 daw_json_assert_weak( base::parse_state and
121 base::parse_state->has_more( ),
122 ErrorReason::UnexpectedEndOfData,
123 *base::parse_state );
124
125 return parse_value<element_t, false, element_t::expected_type>(
126 *base::parse_state );
127 }
128
129 DAW_ATTRIB_INLINE constexpr json_parse_array_iterator &operator++( ) {
130 daw_json_assert_weak( base::parse_state,
131 ErrorReason::UnexpectedEndOfData,
132 *base::parse_state );
133 base::parse_state->trim_left( );
134
136 base::parse_state->has_more( ) and
137 base::parse_state->is_at_next_array_element( ),
138 ErrorReason::UnexpectedEndOfData,
139 *base::parse_state );
140
141 base::parse_state->move_next_member_or_end( );
142 daw_json_assert_weak( base::parse_state->has_more( ),
143 ErrorReason::UnexpectedEndOfData,
144 *base::parse_state );
145 if( base::parse_state->front( ) == ']' ) {
146#if not defined( NDEBUG )
147 if constexpr( base::has_counter ) {
148 daw_json_assert_weak( base::counter == 0,
149 ErrorReason::AttemptToAccessPastEndOfValue,
150 *base::parse_state );
151 }
152#endif
153 if constexpr( not KnownBounds ) {
154 // Cleanup at end of value
155 base::parse_state->remove_prefix( );
156 base::parse_state->trim_left_checked( );
157 // Ensure we are equal to default
158 }
159 base::parse_state = nullptr;
160 } else {
161#if not defined( NDEBUG )
162 if constexpr( base::has_counter ) {
163 daw_json_assert_weak( base::counter > 0,
164 ErrorReason::AttemptToAccessPastEndOfValue,
165 *base::parse_state );
166 --base::counter;
167 }
168#endif
169 }
170 return *this;
171 }
172
173 DAW_ATTRIB_INLINE constexpr void operator++( int ) {
174 (void)operator++( );
175 }
176
177 friend inline constexpr bool
178 operator==( json_parse_array_iterator const &lhs,
179 json_parse_array_iterator const &rhs ) {
180 return lhs.parse_state == rhs.parse_state;
181 }
182
183 friend inline constexpr bool
184 operator!=( json_parse_array_iterator const &lhs,
185 json_parse_array_iterator const &rhs ) {
186 return not( lhs == rhs );
187 }
188
189 constexpr json_parse_array_iterator &begin( ) {
190 return *this;
191 }
192
193 constexpr json_parse_array_iterator end( ) const {
194 return { };
195 }
196 };
197 } // namespace json_details
198 } // namespace DAW_JSON_VER
199} // 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(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