DAW JSON Link
Loading...
Searching...
No Matches
daw_json_parse_kv_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#include "daw_json_traits.h"
17
18#include <daw/daw_attributes.h>
19#include <daw/daw_move.h>
20
21namespace daw::json {
22 inline namespace DAW_JSON_VER {
23 namespace json_details {
24 template<typename ParseState, bool>
25 struct json_parse_kv_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 ParseState *parse_state = nullptr;
30 };
31
32 template<typename ParseState>
33 struct json_parse_kv_array_iterator_base<ParseState, true> {
34#if defined( DAW_JSON_HAS_CPP23_RANGE_CTOR )
35 using iterator_category = std::input_iterator_tag;
36#else
37 // We have to lie so that std::distance uses O(1) instead of O(N)
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 ParseState *parse_state = nullptr;
43 difference_type counter = 0;
44
45 explicit json_parse_kv_array_iterator_base( ) = default;
46
47 DAW_ATTRIB_NONNULL( )
48 explicit constexpr json_parse_kv_array_iterator_base(
49 ParseState *pd ) noexcept
50 : parse_state( pd )
51 , counter( static_cast<difference_type>( pd->counter ) ) {}
52
53 constexpr difference_type
54 operator-( json_parse_kv_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 return rhs.counter;
59 }
60 };
61
62 template<typename JsonMember, typename ParseState, bool KnownBounds>
63 struct json_parse_kv_array_iterator final
64 : json_parse_kv_array_iterator_base<
65 ParseState, can_be_random_iterator_v<KnownBounds>> {
66
67 using base = json_parse_kv_array_iterator_base<
68 ParseState, can_be_random_iterator_v<KnownBounds>>;
69 using iterator_category = typename base::iterator_category;
70 using json_key_t = typename JsonMember::json_key_t;
71 using json_element_t = typename JsonMember::json_value_t;
72 using value_type = std::pair<json_result_t<json_key_t> const,
73 json_result_t<json_element_t>>;
74 using reference = value_type;
75 using pointer = arrow_proxy<value_type>;
76 using parse_state_t = ParseState;
77 using difference_type = typename base::difference_type;
78
79 using json_class_type = typename JsonMember::json_class_t;
80 explicit json_parse_kv_array_iterator( ) = default;
81
82 explicit constexpr json_parse_kv_array_iterator( parse_state_t &r )
83 : base{ &r } {
84 if( DAW_UNLIKELY( base::parse_state->front( ) == ']' ) ) {
85 if constexpr( not KnownBounds ) {
86 // Cleanup at end of value
87 base::parse_state->remove_prefix( );
88 base::parse_state->trim_left_checked( );
89 // Ensure we are equal to default
90 }
91 base::parse_state = nullptr;
92 }
93 }
94
95 static constexpr value_type
96 get_pair( json_result_t<json_class_type> &&v ) {
97 return value_type( std::get<0>( std::move( v.members ) ),
98 std::get<1>( std::move( v.members ) ) );
99 }
100
101 DAW_ATTRIB_NOINLINE value_type operator*( ) const {
102 // This is hear to satisfy indirectly_readable
103 daw_json_error( ErrorReason::UnexpectedEndOfData );
104 }
105
106 DAW_ATTRIB_INLINE constexpr value_type operator*( ) {
107 daw_json_assert_weak( base::parse_state and
108 base::parse_state->has_more( ),
109 ErrorReason::UnexpectedEndOfData,
110 *base::parse_state );
111
112 return get_pair(
113 parse_value<json_class_type, false, JsonParseTypes::Class>(
114 *base::parse_state ) );
115 }
116
117 DAW_ATTRIB_INLINE constexpr json_parse_kv_array_iterator &
118 operator++( ) {
119 daw_json_assert_weak( base::parse_state,
120 ErrorReason::UnexpectedEndOfData );
121 base::parse_state->trim_left( );
122
124 base::parse_state->has_more( ) and
125 base::parse_state->is_at_next_array_element( ),
126 ErrorReason::UnexpectedEndOfData,
127 *base::parse_state );
128
129 base::parse_state->move_next_member_or_end( );
130 daw_json_assert_weak( base::parse_state->has_more( ),
131 ErrorReason::UnexpectedEndOfData );
132 if( DAW_UNLIKELY( base::parse_state->front( ) == ']' ) ) {
133#if not defined( NDEBUG )
134 if constexpr( base::has_counter ) {
135 daw_json_assert_weak( base::counter == 0,
136 ErrorReason::UnexpectedEndOfData );
137 }
138#endif
139 if constexpr( not KnownBounds ) {
140 // Cleanup at end of value
141 base::parse_state->remove_prefix( );
142 base::parse_state->trim_left_checked( );
143 // Ensure we are equal to default
144 }
145 base::parse_state = nullptr;
146 }
147#if not defined( NDEBUG )
148 if constexpr( base::has_counter ) {
149 daw_json_assert_weak( base::counter > 0,
150 ErrorReason::UnexpectedEndOfData );
151 --base::counter;
152 }
153#endif
154 return *this;
155 }
156
157 DAW_ATTRIB_INLINE constexpr void operator++( int ) {
158 (void)operator++( );
159 }
160
161 friend constexpr bool
162 operator==( json_parse_kv_array_iterator const &lhs,
163 json_parse_kv_array_iterator const &rhs ) {
164 return lhs.parse_state == rhs.parse_state;
165 }
166
167 friend constexpr bool
168 operator!=( json_parse_kv_array_iterator const &lhs,
169 json_parse_kv_array_iterator const &rhs ) {
170 return not( lhs == rhs );
171 }
172 };
173 } // namespace json_details
174 } // namespace DAW_JSON_VER
175} // 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.
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