Horizon
iteration_proxy.hpp
1 #pragma once
2 
3 #include <cstddef> // size_t
4 #include <iterator> // input_iterator_tag
5 #include <string> // string, to_string
6 #include <tuple> // tuple_size, get, tuple_element
7 #include <utility> // move
8 
9 #include <nlohmann/detail/meta/type_traits.hpp>
10 #include <nlohmann/detail/value_t.hpp>
11 
12 namespace nlohmann
13 {
14 namespace detail
15 {
16 template<typename string_type>
17 void int_to_string( string_type& target, std::size_t value )
18 {
19  // For ADL
20  using std::to_string;
21  target = to_string(value);
22 }
23 template<typename IteratorType> class iteration_proxy_value
24 {
25  public:
26  using difference_type = std::ptrdiff_t;
28  using pointer = value_type * ;
29  using reference = value_type & ;
30  using iterator_category = std::input_iterator_tag;
31  using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
32 
33  private:
35  IteratorType anchor;
37  std::size_t array_index = 0;
39  mutable std::size_t array_index_last = 0;
41  mutable string_type array_index_str = "0";
43  const string_type empty_str{};
44 
45  public:
46  explicit iteration_proxy_value(IteratorType it) noexcept
47  : anchor(std::move(it))
48  {}
49 
52  {
53  return *this;
54  }
55 
58  {
59  ++anchor;
60  ++array_index;
61 
62  return *this;
63  }
64 
66  bool operator==(const iteration_proxy_value& o) const
67  {
68  return anchor == o.anchor;
69  }
70 
72  bool operator!=(const iteration_proxy_value& o) const
73  {
74  return anchor != o.anchor;
75  }
76 
78  const string_type& key() const
79  {
80  JSON_ASSERT(anchor.m_object != nullptr);
81 
82  switch (anchor.m_object->type())
83  {
84  // use integer array index as key
85  case value_t::array:
86  {
87  if (array_index != array_index_last)
88  {
89  int_to_string( array_index_str, array_index );
90  array_index_last = array_index;
91  }
92  return array_index_str;
93  }
94 
95  // use key from the object
96  case value_t::object:
97  return anchor.key();
98 
99  // use an empty key for all primitive types
100  case value_t::null:
101  case value_t::string:
102  case value_t::boolean:
106  case value_t::binary:
107  case value_t::discarded:
108  default:
109  return empty_str;
110  }
111  }
112 
114  typename IteratorType::reference value() const
115  {
116  return anchor.value();
117  }
118 };
119 
121 template<typename IteratorType> class iteration_proxy
122 {
123  private:
125  typename IteratorType::reference container;
126 
127  public:
129  explicit iteration_proxy(typename IteratorType::reference cont) noexcept
130  : container(cont) {}
131 
134  {
135  return iteration_proxy_value<IteratorType>(container.begin());
136  }
137 
140  {
141  return iteration_proxy_value<IteratorType>(container.end());
142  }
143 };
144 // Structured Bindings Support
145 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
146 // And see https://github.com/nlohmann/json/pull/1391
147 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
148 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
149 {
150  return i.key();
151 }
152 // Structured Bindings Support
153 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
154 // And see https://github.com/nlohmann/json/pull/1391
155 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
156 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
157 {
158  return i.value();
159 }
160 } // namespace detail
161 } // namespace nlohmann
162 
163 // The Addition to the STD Namespace is required to add
164 // Structured Bindings Support to the iteration_proxy_value class
165 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
166 // And see https://github.com/nlohmann/json/pull/1391
167 namespace std
168 {
169 #if defined(__clang__)
170  // Fix: https://github.com/nlohmann/json/issues/1401
171  #pragma clang diagnostic push
172  #pragma clang diagnostic ignored "-Wmismatched-tags"
173 #endif
174 template<typename IteratorType>
175 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
176  : public std::integral_constant<std::size_t, 2> {};
177 
178 template<std::size_t N, typename IteratorType>
179 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
180 {
181  public:
182  using type = decltype(
183  get<N>(std::declval <
185 };
186 #if defined(__clang__)
187  #pragma clang diagnostic pop
188 #endif
189 } // namespace std
Definition: iteration_proxy.hpp:24
iteration_proxy_value & operator*()
dereference operator (needed for range-based for)
Definition: iteration_proxy.hpp:51
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition: iteration_proxy.hpp:72
IteratorType::reference value() const
return value of the iterator
Definition: iteration_proxy.hpp:114
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition: iteration_proxy.hpp:57
const string_type & key() const
return key of the iterator
Definition: iteration_proxy.hpp:78
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition: iteration_proxy.hpp:66
proxy class for the items() function
Definition: iteration_proxy.hpp:122
iteration_proxy_value< IteratorType > begin() noexcept
return iterator begin (needed for range-based for)
Definition: iteration_proxy.hpp:133
iteration_proxy_value< IteratorType > end() noexcept
return iterator end (needed for range-based for)
Definition: iteration_proxy.hpp:139
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition: iteration_proxy.hpp:129
@ number_integer
number value (signed integer)
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
namespace for Niels Lohmann
Definition: adl_serializer.hpp:12
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.hpp:8969