DAW JSON Link
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 "daw_json_arrow_proxy.h"
12 #include "daw_json_assert.h"
14 
15 #include <ciso646>
16 
17 namespace daw::json::json_details {
18  template<typename... Args>
19  [[maybe_unused]] void test_map( std::map<Args...> const & );
20 
21  template<typename... Args>
22  [[maybe_unused]] void test_map( std::unordered_map<Args...> const & );
23  template<typename Range, bool>
24  struct json_parse_kv_class_iterator_base {
25  using iterator_category = std::input_iterator_tag;
26  using difference_type = std::ptrdiff_t;
27  Range *rng = nullptr;
28  };
29 
30  template<typename Range>
31  struct json_parse_kv_class_iterator_base<Range, true> {
32  // We have to lie so that std::distance uses O(1) instead of O(N)
33  using iterator_category = std::random_access_iterator_tag;
34  using difference_type = std::ptrdiff_t;
35  Range *rng = nullptr;
36 
37  constexpr difference_type
38  operator-( json_parse_kv_class_iterator_base const &rhs ) const {
39  if( rhs.rng ) {
40  return static_cast<difference_type>( rhs.rng->counter );
41  }
42  return 0;
43  }
44  };
45 
46  template<typename JsonMember, typename Range, bool KnownBounds>
47  struct json_parse_kv_class_iterator
48  : json_parse_kv_class_iterator_base<Range, can_random_v<KnownBounds>> {
49 
50  using base =
51  json_parse_kv_class_iterator_base<Range, can_random_v<KnownBounds>>;
52  using iterator_category = typename base::iterator_category;
53  using element_t = typename JsonMember::json_element_t;
54  using member_container_type = typename JsonMember::base_type;
55  using value_type = typename member_container_type::value_type;
56  using reference = value_type;
57  using pointer = arrow_proxy<value_type>;
58  using iterator_range_t = Range;
59  using difference_type = typename base::difference_type;
60 
61  using key_t = typename JsonMember::json_key_t;
62  using value_t = typename JsonMember::json_element_t;
63 
64  inline constexpr json_parse_kv_class_iterator( ) = default;
65 
66  inline constexpr explicit json_parse_kv_class_iterator(
67  iterator_range_t &r )
68  : base{ &r } {
69  if( base::rng->front( ) == '}' ) {
70  // Cleanup at end of value
71  if( not KnownBounds ) {
72  base::rng->remove_prefix( );
73  base::rng->trim_left_checked( );
74  // Ensure we are equal to default
75  }
76  base::rng = nullptr;
77  }
78  }
79 
80  inline constexpr value_type operator*( ) {
81  daw_json_assert_weak( base::rng and base::rng->has_more( ),
82  ErrorReason::UnexpectedEndOfData, *base::rng );
83  auto key =
84  parse_value<key_t>( ParseTag<key_t::expected_type>{ }, *base::rng );
85  name::name_parser::trim_end_of_name( *base::rng );
86  return json_class_constructor<value_type>(
87  std::move( key ), parse_value<value_t>(
88  ParseTag<value_t::expected_type>{ }, *base::rng ) );
89  }
90 
91  inline constexpr json_parse_kv_class_iterator &operator++( ) {
93  base::rng, ErrorReason::AttemptToAccessPastEndOfValue, *base::rng );
94  base::rng->clean_tail( );
95  daw_json_assert_weak( base::rng->has_more( ),
96  ErrorReason::UnexpectedEndOfData, *base::rng );
97  if( base::rng->front( ) == '}' ) {
98 #ifndef NDEBUG
99  if constexpr( KnownBounds ) {
100  if( base::rng ) {
101  daw_json_assert( base::rng->counter > 0,
102  ErrorReason::AttemptToAccessPastEndOfValue,
103  *base::rng );
104  base::rng->counter--;
105  }
106  }
107 #endif
108  if constexpr( not KnownBounds ) {
109  // Cleanup at end of value
110  base::rng->remove_prefix( );
111  base::rng->trim_left_checked( );
112  // Ensure we are equal to default
113  }
114  base::rng = nullptr;
115  }
116 #ifndef NDEBUG
117  if constexpr( KnownBounds ) {
118  if( base::rng ) {
119  daw_json_assert( base::rng->counter > 0,
120  ErrorReason::AttemptToAccessPastEndOfValue,
121  *base::rng );
122  base::rng->counter--;
123  }
124  }
125 #endif
126  return *this;
127  }
128 
129  inline constexpr json_parse_kv_class_iterator operator++( int ) {
130  auto result = *this;
131  (void)this->operator++( );
132  return result;
133  }
134 
135  inline constexpr bool
136  operator==( json_parse_kv_class_iterator const &rhs ) const {
137  // using identity as equality
138  return base::rng == rhs.base::rng;
139  }
140 
141  inline constexpr bool
142  operator!=( json_parse_kv_class_iterator const &rhs ) const {
143  // using identity as equality
144  return base::rng != rhs.base::rng;
145  }
146  };
147 } // namespace daw::json::json_details
daw_json_assert
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:196
daw_json_assert_weak
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:206
daw_json_parse_value_fwd.h
daw_json_arrow_proxy.h
daw_json_assert.h