DAW JSON Link
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 
13 #include "daw_json_arrow_proxy.h"
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 
21 namespace 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
49  json_parse_kv_array_iterator_base( 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*( ) {
108  base::parse_state and base::parse_state->has_more( ),
109  ErrorReason::UnexpectedEndOfData, *base::parse_state );
110 
111  return get_pair(
112  parse_value<json_class_type, false, JsonParseTypes::Class>(
113  *base::parse_state ) );
114  }
115 
116  DAW_ATTRIB_INLINE constexpr json_parse_kv_array_iterator &
117  operator++( ) {
118  daw_json_assert_weak( base::parse_state,
119  ErrorReason::UnexpectedEndOfData );
120  base::parse_state->trim_left( );
121 
123  base::parse_state->has_more( ) and
124  base::parse_state->is_at_next_array_element( ),
125  ErrorReason::UnexpectedEndOfData, *base::parse_state );
126 
127  base::parse_state->move_next_member_or_end( );
128  daw_json_assert_weak( base::parse_state->has_more( ),
129  ErrorReason::UnexpectedEndOfData );
130  if( DAW_UNLIKELY( base::parse_state->front( ) == ']' ) ) {
131 #if not defined( NDEBUG )
132  if constexpr( base::has_counter ) {
133  daw_json_assert_weak( base::counter == 0,
134  ErrorReason::UnexpectedEndOfData );
135  }
136 #endif
137  if constexpr( not KnownBounds ) {
138  // Cleanup at end of value
139  base::parse_state->remove_prefix( );
140  base::parse_state->trim_left_checked( );
141  // Ensure we are equal to default
142  }
143  base::parse_state = nullptr;
144  }
145 #if not defined( NDEBUG )
146  if constexpr( base::has_counter ) {
147  daw_json_assert_weak( base::counter > 0,
148  ErrorReason::UnexpectedEndOfData );
149  --base::counter;
150  }
151 #endif
152  return *this;
153  }
154 
155  DAW_ATTRIB_INLINE constexpr void operator++( int ) {
156  (void)operator++( );
157  }
158 
159  friend constexpr bool
160  operator==( json_parse_kv_array_iterator const &lhs,
161  json_parse_kv_array_iterator const &rhs ) {
162  return lhs.parse_state == rhs.parse_state;
163  }
164 
165  friend constexpr bool
166  operator!=( json_parse_kv_array_iterator const &lhs,
167  json_parse_kv_array_iterator const &rhs ) {
168  return not( lhs == rhs );
169  }
170  };
171  } // namespace json_details
172  } // namespace DAW_JSON_VER
173 } // 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:25