DAW JSON Link
Loading...
Searching...
No Matches
daw_json_parse_kv_class_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"
15#include "daw_json_parse_name.h"
17#include "daw_json_traits.h"
18
19#include <daw/daw_move.h>
20
21#include <cstddef>
22#include <iterator>
23
24namespace daw::json {
25 inline namespace DAW_JSON_VER {
26 namespace json_details {
27 template<typename ParseState, bool>
28 struct json_parse_kv_class_iterator_base {
29 using iterator_category = std::input_iterator_tag;
30 using difference_type = std::ptrdiff_t;
31 ParseState *parse_state = nullptr;
32 };
33
34 template<typename ParseState>
35 struct json_parse_kv_class_iterator_base<ParseState, true> {
36#if defined( DAW_JSON_HAS_CPP23_RANGE_CTOR )
37 using iterator_category = std::input_iterator_tag;
38#else
39 // We have to lie so that std::distance uses O(1) instead of O(N)
40 using iterator_category = std::random_access_iterator_tag;
41#endif
42 using difference_type = std::ptrdiff_t;
43 ParseState *parse_state = nullptr;
44
45 constexpr difference_type
46 operator-( json_parse_kv_class_iterator_base const &rhs ) const {
47 if( rhs.parse_state ) {
48 return static_cast<difference_type>( rhs.parse_state->counter );
49 }
50 return 0;
51 }
52 };
53
54 namespace kv_class_iter_impl {
55 template<typename T>
56 using container_value_t = typename T::value_type;
57
58 template<typename JsonMember>
59 using default_value_type =
60 std::pair<typename JsonMember::json_key_t,
61 typename JsonMember::json_element_t>;
62
63 template<typename JsonMember, typename T>
64 using container_value_type_or =
65 daw::detected_or_t<default_value_type<JsonMember>, container_value_t,
66 T>;
67 } // namespace kv_class_iter_impl
68
69 template<typename JsonMember, typename ParseState, bool IsKnown>
70 struct json_parse_kv_class_iterator
71 : json_parse_kv_class_iterator_base<ParseState,
72 can_be_random_iterator_v<IsKnown>> {
73
74 using base =
75 json_parse_kv_class_iterator_base<ParseState,
76 can_be_random_iterator_v<IsKnown>>;
77 using iterator_category = typename base::iterator_category;
78 using element_t = typename JsonMember::json_element_t;
79 using member_container_type = json_base_type_t<JsonMember>;
80 using value_type =
81 kv_class_iter_impl::container_value_type_or<JsonMember,
82 member_container_type>;
83 using reference = value_type;
84 using pointer = arrow_proxy<value_type>;
85 using iterator_range_t = ParseState;
86 using difference_type = typename base::difference_type;
87
88 using key_t = typename JsonMember::json_key_t;
89 using value_t = typename JsonMember::json_element_t;
90
91 json_parse_kv_class_iterator( ) = default;
92
93 constexpr explicit json_parse_kv_class_iterator( iterator_range_t &r )
94 : base{ &r } {
95 daw_json_ensure( not IsKnown and not base::parse_state->empty( ),
96 ErrorReason::UnexpectedEndOfData );
97 if( base::parse_state->front( ) == '}' ) {
98 // Cleanup at end of value
99 if( not IsKnown ) {
100 base::parse_state->remove_prefix( );
101 base::parse_state->trim_left_checked( );
102 // Ensure we are equal to default
103 }
104 base::parse_state = nullptr;
105 }
106 }
107
108 [[noreturn]] DAW_ATTRIB_NOINLINE value_type operator*( ) const {
109 // This is hear to satisfy indirectly_readable
110 daw_json_error( ErrorReason::UnexpectedEndOfData );
111 }
112
113 constexpr value_type operator*( ) {
114 daw_json_assert_weak( base::parse_state and
115 base::parse_state->has_more( ),
116 ErrorReason::UnexpectedEndOfData,
117 *base::parse_state );
118 auto key = parse_value<key_t, false, key_t::expected_type>(
119 *base::parse_state );
120 name::name_parser::trim_end_of_name( *base::parse_state );
121
122 return json_class_constructor<value_type,
124 std::move( key ),
125 parse_value<value_t, false, value_t::expected_type>(
126 *base::parse_state ) );
127 }
128
129 constexpr json_parse_kv_class_iterator &operator++( ) {
130 daw_json_assert_weak( base::parse_state,
131 ErrorReason::AttemptToAccessPastEndOfValue,
132 *base::parse_state );
133 base::parse_state->move_next_member_or_end( );
134 daw_json_assert_weak( base::parse_state->has_more( ),
135 ErrorReason::UnexpectedEndOfData,
136 *base::parse_state );
137 if( base::parse_state->front( ) == '}' ) {
138#if not defined( NDEBUG )
139 if constexpr( IsKnown ) {
140 if( base::parse_state ) {
141 daw_json_ensure( base::parse_state->counter == 0,
142 ErrorReason::AttemptToAccessPastEndOfValue,
143 *base::parse_state );
144 base::parse_state->counter--;
145 }
146 }
147#endif
148 // Cleanup at end of value
149 base::parse_state->remove_prefix( );
150 base::parse_state->trim_left_checked( );
151 // Ensure we are equal to default
152 base::parse_state = nullptr;
153 }
154#if not defined( NDEBUG )
155 if constexpr( IsKnown ) {
156 if( base::parse_state ) {
157 daw_json_ensure( base::parse_state->counter > 0,
158 ErrorReason::AttemptToAccessPastEndOfValue,
159 *base::parse_state );
160 base::parse_state->counter--;
161 }
162 }
163#endif
164 return *this;
165 }
166
167 DAW_ATTRIB_INLINE constexpr void operator++( int ) {
168 (void)operator++( );
169 }
170
171 friend constexpr bool
172 operator==( json_parse_kv_class_iterator const &lhs,
173 json_parse_kv_class_iterator const &rhs ) {
174 // using identity as equality
175 return lhs.parse_state == rhs.base::parse_state;
176 }
177
178 friend constexpr bool
179 operator!=( json_parse_kv_class_iterator const &lhs,
180 json_parse_kv_class_iterator const &rhs ) {
181 return not( lhs == rhs );
182 }
183 };
184 } // namespace json_details
185 } // namespace DAW_JSON_VER
186} // 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_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
DAW_ATTRIB_NOINLINE void daw_json_error(ErrorReason reason)
Customization point traits.
Default Constructor for a type. It accounts for aggregate types and uses brace construction for them.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20