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*( ) {
115 base::parse_state and base::parse_state->has_more( ),
116 ErrorReason::UnexpectedEndOfData, *base::parse_state );
117 auto key = parse_value<key_t, false, key_t::expected_type>(
118 *base::parse_state );
119 name::name_parser::trim_end_of_name( *base::parse_state );
120
121 return json_class_constructor<value_type,
123 std::move( key ),
124 parse_value<value_t, false, value_t::expected_type>(
125 *base::parse_state ) );
126 }
127
128 constexpr json_parse_kv_class_iterator &operator++( ) {
129 daw_json_assert_weak( base::parse_state,
130 ErrorReason::AttemptToAccessPastEndOfValue,
131 *base::parse_state );
132 base::parse_state->move_next_member_or_end( );
133 daw_json_assert_weak( base::parse_state->has_more( ),
134 ErrorReason::UnexpectedEndOfData,
135 *base::parse_state );
136 if( base::parse_state->front( ) == '}' ) {
137#if not defined( NDEBUG )
138 if constexpr( IsKnown ) {
139 if( base::parse_state ) {
140 daw_json_ensure( base::parse_state->counter == 0,
141 ErrorReason::AttemptToAccessPastEndOfValue,
142 *base::parse_state );
143 base::parse_state->counter--;
144 }
145 }
146#endif
147 // Cleanup at end of value
148 base::parse_state->remove_prefix( );
149 base::parse_state->trim_left_checked( );
150 // Ensure we are equal to default
151 base::parse_state = nullptr;
152 }
153#if not defined( NDEBUG )
154 if constexpr( IsKnown ) {
155 if( base::parse_state ) {
156 daw_json_ensure( base::parse_state->counter > 0,
157 ErrorReason::AttemptToAccessPastEndOfValue,
158 *base::parse_state );
159 base::parse_state->counter--;
160 }
161 }
162#endif
163 return *this;
164 }
165
166 DAW_ATTRIB_INLINE constexpr void operator++( int ) {
167 (void)operator++( );
168 }
169
170 friend constexpr bool
171 operator==( json_parse_kv_class_iterator const &lhs,
172 json_parse_kv_class_iterator const &rhs ) {
173 // using identity as equality
174 return lhs.parse_state == rhs.base::parse_state;
175 }
176
177 friend constexpr bool
178 operator!=( json_parse_kv_class_iterator const &lhs,
179 json_parse_kv_class_iterator const &rhs ) {
180 return not( lhs == rhs );
181 }
182 };
183 } // namespace json_details
184 } // namespace DAW_JSON_VER
185} // 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