DAW JSON Link
daw_json_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 "daw_json_link.h"
13 
14 #include <daw/daw_algorithm.h>
15 #include <daw/daw_array.h>
16 #include <daw/daw_bounded_string.h>
17 #include <daw/daw_cxmath.h>
18 #include <daw/daw_exception.h>
19 #include <daw/daw_parser_helper_sv.h>
20 #include <daw/daw_scope_guard.h>
21 #include <daw/daw_traits.h>
22 #include <daw/daw_utility.h>
23 #include <daw/iterator/daw_back_inserter.h>
24 
25 #include <array>
26 #include <chrono>
27 #include <cstdlib>
28 #include <iterator>
29 #include <limits>
30 #include <string>
31 #include <string_view>
32 #include <tuple>
33 
34 namespace daw::json {
35 
36  /***
37  * Iterator for iterating over JSON array's
38  * @tparam JsonElement type under underlying element in array. If
39  * heterogenous, a basic_json_value_iterator may be more appropriate
40  * @tparam ParsePolicy Parsing policy type
41  */
42  template<typename JsonElement,
43  typename ParsePolicy = NoCommentSkippingPolicyChecked>
45 
46  template<typename String>
47  static inline constexpr ParsePolicy
48  get_range( String &&data, std::string_view member_path ) {
49  auto [is_found, result] = json_details::find_range<ParsePolicy>(
50  std::forward<String>( data ),
51  { member_path.data( ), member_path.size( ) } );
52  daw_json_assert( is_found, ErrorReason::JSONPathNotFound );
53  daw_json_assert( result.front( ) == '[', ErrorReason::InvalidArrayStart,
54  result );
55  return result;
56  }
57 
58  public:
59  using element_type =
60  json_details::unnamed_default_type_mapping<JsonElement>;
61  static_assert( not std::is_same_v<element_type, void>,
62  "Unknown JsonElement type." );
63  using value_type = typename element_type::parse_to_t;
65  using pointer = json_details::arrow_proxy<value_type>;
66  using difference_type = std::ptrdiff_t;
67  // Can do forward iteration and be stored
68  using iterator_category = std::input_iterator_tag;
69 
70  private:
71  using Range = ParsePolicy;
72  Range m_state = Range( );
73  /***
74  * This lets us fastpath and just skip n characters as we have already
75  * parsed them
76  */
77  mutable char const *m_can_skip = nullptr;
78 
79  public:
80  inline constexpr json_array_iterator( ) = default;
81 
82  template<typename String,
83  daw::enable_when_t<not std::is_same_v<
84  json_array_iterator, daw::remove_cvref_t<String>>> = nullptr>
85  inline constexpr explicit json_array_iterator( String &&jd )
86  : m_state(
87  ParsePolicy( std::data( jd ), std::data( jd ) + std::size( jd ) ) ) {
88 
89  static_assert(
90  daw::traits::is_string_view_like_v<daw::remove_cvref_t<String>>,
91  "StringRaw must be like a string_view" );
92  m_state.trim_left( );
94  ErrorReason::InvalidArrayStart, m_state );
95 
96  m_state.remove_prefix( );
97  m_state.trim_left( );
98  }
99 
100  template<typename String,
101  daw::enable_when_t<not std::is_same_v<
102  json_array_iterator, daw::remove_cvref_t<String>>> = nullptr>
103  inline constexpr explicit json_array_iterator( String &&jd,
104  std::string_view start_path )
105  : m_state( get_range( std::forward<String>( jd ), start_path ) ) {
106 
107  static_assert(
108  daw::traits::is_string_view_like_v<daw::remove_cvref_t<String>>,
109  "StringRaw must be like a string_view" );
110  m_state.trim_left( );
112  ErrorReason::InvalidArrayStart, m_state );
113 
114  m_state.remove_prefix( );
115  m_state.trim_left( );
116  }
117 
118  /***
119  * Parse the current element
120  * @pre good( ) returns true
121  * @return The parsed result of ParseElement
122  */
123  [[nodiscard]] inline constexpr value_type operator*( ) const {
124  daw_json_assert_weak( m_state.has_more( ) and m_state.front( ) != ']',
125  ErrorReason::UnexpectedEndOfData, m_state );
126 
127  auto tmp = m_state;
128 
129  if constexpr( json_details::is_guaranteed_rvo_v<ParsePolicy> ) {
130  auto const ae = daw::on_exit_success( [&] { m_can_skip = tmp.first; } );
131  return json_details::parse_value<element_type>(
133  } else {
134  auto result = json_details::parse_value<element_type>(
136 
137  m_can_skip = tmp.first;
138  return result;
139  }
140  }
141 
142  /***
143  * A dereferenable value proxy holding the result of operator*
144  * This is for compatability with the Iterator concepts and should be
145  * avoided
146  * @pre good( ) returns true
147  * @return an arrow_proxy of the operator* result
148  */
149  [[nodiscard]] inline pointer operator->( ) const {
150  return pointer{ operator*( ) };
151  }
152 
153  /***
154  * Move the parse state to the next element
155  * @return iterator after moving
156  */
157  inline constexpr json_array_iterator &operator++( ) {
158  daw_json_assert_weak( m_state.has_more( ) and m_state.front( ) != ']',
159  ErrorReason::UnexpectedEndOfData, m_state );
160  if( m_can_skip ) {
161  m_state.first = m_can_skip;
162  m_can_skip = nullptr;
163  } else {
164  (void)json_details::skip_known_value<element_type>( m_state );
165  }
166  m_state.clean_tail( );
167  return *this;
168  }
169 
170  /***
171  * Move the parse state to the next element
172  * @return iterator prior to moving
173  */
174  inline constexpr json_array_iterator operator++( int ) {
175  auto tmp = *this;
176  (void)operator++( );
177  return tmp;
178  }
179 
180  /***
181  * Is it ok to dereference itereator
182  * @return true when there is parse data available
183  */
184  [[nodiscard]] inline constexpr bool good( ) const {
185  return not m_state.is_null( ) and m_state.has_more( ) and
186  m_state.front( ) != ']';
187  }
188 
189  /***
190  * Are we good( )
191  * @return result of good( )
192  */
193  [[nodiscard]] explicit inline constexpr operator bool( ) const {
194  return good( );
195  }
196 
197  /***
198  * Compare rhs for equivilence
199  * @param rhs Another json_array_iterator
200  * @return true when equivilent to rhs
201  */
202  [[nodiscard]] inline constexpr bool
203  operator==( json_array_iterator const &rhs ) const {
204  if( not( *this ) ) {
205  return not rhs;
206  }
207  if( not rhs ) {
208  return false;
209  }
210  return ( m_state.first == rhs.m_state.first );
211  }
212 
213  /***
214  * Check if the other iterator is not equivilent
215  * @param rhs another json_array_iterator
216  * @return true when rhs is not equivilent
217  */
218  [[nodiscard]] inline constexpr bool
219  operator!=( json_array_iterator const &rhs ) const {
220  if( not( *this ) ) {
221  return static_cast<bool>( rhs );
222  }
223  if( not rhs ) {
224  return true;
225  }
226  return m_state.first != rhs.m_state.first;
227  }
228  };
229 
230  /***
231  * A range of json_array_iterators
232  * @tparam JsonElement Type of each element in array
233  * @tparam ParsePolicy parsing policy type
234  */
235  template<typename JsonElement,
236  typename ParsePolicy = NoCommentSkippingPolicyChecked>
239 
240  private:
241  iterator m_first{ };
242  iterator m_last{ };
243 
244  public:
245  constexpr json_array_range( ) = default;
246 
247  template<typename String,
248  daw::enable_when_t<not std::is_same_v<
249  json_array_range, daw::remove_cvref_t<String>>> = nullptr>
250  constexpr explicit json_array_range( String &&jd )
251  : m_first( std::forward<String>( jd ) ) {}
252 
253  template<typename String,
254  daw::enable_when_t<not std::is_same_v<
255  json_array_range, daw::remove_cvref_t<String>>> = nullptr>
256  constexpr explicit json_array_range( String &&jd,
257  std::string_view start_path )
258  : m_first( std::forward<String>( jd ), start_path ) {}
259 
260  /***
261  * @return first item in range
262  */
263  [[nodiscard]] inline constexpr iterator begin( ) {
264  return m_first;
265  }
266 
267  /***
268  * @return one past last item in range
269  */
270  [[nodiscard]] inline constexpr iterator end( ) {
271  return m_last;
272  }
273 
274  /***
275  * Are there any elements in range
276  * @return true when begin( ) == end( )
277  */
278  [[nodiscard]] inline constexpr bool empty( ) const {
279  return m_first == m_last;
280  }
281  };
282 } // namespace daw::json
daw::json::json_array_range
Definition: daw_json_iterator.h:237
daw::json::BasicParsePolicy::trim_left
constexpr void trim_left()
Definition: daw_json_parse_policy.h:412
daw_json_assert
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:196
daw::json
Definition: daw_json_event_parser.h:17
daw_json_assert_weak
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:206
daw::json::json_array_iterator< JsonElement, NoCommentSkippingPolicyChecked >::value_type
typename element_type::parse_to_t value_type
Definition: daw_json_iterator.h:63
daw::json::json_array_iterator< JsonElement, NoCommentSkippingPolicyChecked >::element_type
json_details::unnamed_default_type_mapping< JsonElement > element_type
Definition: daw_json_iterator.h:60
daw::json::json_array_iterator< JsonElement, NoCommentSkippingPolicyChecked >::reference
value_type reference
Definition: daw_json_iterator.h:64
daw::json::BasicParsePolicy::is_opening_bracket_checked
constexpr bool is_opening_bracket_checked() const
Definition: daw_json_parse_policy.h:391
daw::json::BasicParsePolicy::has_more
constexpr DAW_ATTRIBUTE_FLATTEN bool has_more() const
Definition: daw_json_parse_policy.h:270
daw::json::json_array_iterator::operator*
constexpr value_type operator*() const
Definition: daw_json_iterator.h:123
daw::json::json_array_range::iterator
json_array_iterator< JsonElement, ParsePolicy > iterator
Definition: daw_json_iterator.h:238
daw::json::BasicParsePolicy::clean_tail
constexpr DAW_ATTRIBUTE_FLATTEN void clean_tail()
Definition: daw_json_parse_policy.h:459
daw::json::BasicParsePolicy::first
iterator first
Definition: daw_json_parse_policy.h:121
daw::json::json_array_iterator::good
constexpr bool good() const
Definition: daw_json_iterator.h:184
daw::json::json_array_iterator::json_array_iterator
constexpr json_array_iterator()=default
daw::json::BasicParsePolicy::is_null
constexpr bool is_null() const
Definition: daw_json_parse_policy.h:333
daw::json::json_array_range::end
constexpr iterator end()
Definition: daw_json_iterator.h:270
daw::json::json_array_iterator< JsonElement, NoCommentSkippingPolicyChecked >::difference_type
std::ptrdiff_t difference_type
Definition: daw_json_iterator.h:66
daw::json::json_array_range::json_array_range
constexpr json_array_range(String &&jd, std::string_view start_path)
Definition: daw_json_iterator.h:256
daw::json::json_array_range::begin
constexpr iterator begin()
Definition: daw_json_iterator.h:263
daw::json::json_array_range::json_array_range
constexpr json_array_range()=default
daw::json::json_array_iterator::operator->
pointer operator->() const
Definition: daw_json_iterator.h:149
daw::json::NoCommentSkippingPolicyChecked
BasicParsePolicy< false, NoCommentSkippingPolicy, default_exec_tag, false > NoCommentSkippingPolicyChecked
Definition: daw_json_parse_policy.h:511
daw::json::json_array_iterator
Definition: daw_json_iterator.h:44
daw::json::json_array_range::empty
constexpr bool empty() const
Definition: daw_json_iterator.h:278
daw::json::json_array_iterator< JsonElement, NoCommentSkippingPolicyChecked >::pointer
json_details::arrow_proxy< value_type > pointer
Definition: daw_json_iterator.h:65
daw::json::json_array_iterator::json_array_iterator
constexpr json_array_iterator(String &&jd)
Definition: daw_json_iterator.h:85
daw::json::json_array_iterator::operator==
constexpr bool operator==(json_array_iterator const &rhs) const
Definition: daw_json_iterator.h:203
daw::json::json_array_iterator< JsonElement, NoCommentSkippingPolicyChecked >::iterator_category
std::input_iterator_tag iterator_category
Definition: daw_json_iterator.h:68
daw::json::json_array_iterator::json_array_iterator
constexpr json_array_iterator(String &&jd, std::string_view start_path)
Definition: daw_json_iterator.h:103
daw::json::ParseTag
std::integral_constant< JsonParseTypes, v > ParseTag
Definition: daw_json_parse_common.h:495
daw::json::json_array_range::json_array_range
constexpr json_array_range(String &&jd)
Definition: daw_json_iterator.h:250
daw::json::json_array_iterator::operator++
constexpr json_array_iterator operator++(int)
Definition: daw_json_iterator.h:174
daw::json::json_array_iterator::operator++
constexpr json_array_iterator & operator++()
Definition: daw_json_iterator.h:157
daw::json::BasicParsePolicy
Definition: daw_json_parse_policy.h:107
daw::json::BasicParsePolicy::remove_prefix
constexpr DAW_ATTRIBUTE_FLATTEN void remove_prefix()
Definition: daw_json_parse_policy.h:337
daw::json::BasicParsePolicy::front
constexpr DAW_ATTRIBUTE_FLATTEN char front() const
Definition: daw_json_parse_policy.h:325
daw::json::json_array_iterator::operator!=
constexpr bool operator!=(json_array_iterator const &rhs) const
Definition: daw_json_iterator.h:219