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 
8 #include <nlohmann/detail/meta/type_traits.hpp>
9 #include <nlohmann/detail/value_t.hpp>
10 
11 namespace nlohmann
12 {
13 namespace detail
14 {
15 template<typename string_type>
16 void int_to_string( string_type& target, std::size_t value )
17 {
18  // For ADL
19  using std::to_string;
20  target = to_string(value);
21 }
22 template<typename IteratorType> class iteration_proxy_value
23 {
24  public:
25  using difference_type = std::ptrdiff_t;
27  using pointer = value_type * ;
28  using reference = value_type & ;
29  using iterator_category = std::input_iterator_tag;
30  using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
31 
32  private:
34  IteratorType anchor;
36  std::size_t array_index = 0;
38  mutable std::size_t array_index_last = 0;
40  mutable string_type array_index_str = "0";
42  const string_type empty_str = "";
43 
44  public:
45  explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
46 
49  {
50  return *this;
51  }
52 
55  {
56  ++anchor;
57  ++array_index;
58 
59  return *this;
60  }
61 
63  bool operator==(const iteration_proxy_value& o) const
64  {
65  return anchor == o.anchor;
66  }
67 
69  bool operator!=(const iteration_proxy_value& o) const
70  {
71  return anchor != o.anchor;
72  }
73 
75  const string_type& key() const
76  {
77  JSON_ASSERT(anchor.m_object != nullptr);
78 
79  switch (anchor.m_object->type())
80  {
81  // use integer array index as key
82  case value_t::array:
83  {
84  if (array_index != array_index_last)
85  {
86  int_to_string( array_index_str, array_index );
87  array_index_last = array_index;
88  }
89  return array_index_str;
90  }
91 
92  // use key from the object
93  case value_t::object:
94  return anchor.key();
95 
96  // use an empty key for all primitive types
97  default:
98  return empty_str;
99  }
100  }
101 
103  typename IteratorType::reference value() const
104  {
105  return anchor.value();
106  }
107 };
108 
110 template<typename IteratorType> class iteration_proxy
111 {
112  private:
114  typename IteratorType::reference container;
115 
116  public:
118  explicit iteration_proxy(typename IteratorType::reference cont) noexcept
119  : container(cont) {}
120 
123  {
124  return iteration_proxy_value<IteratorType>(container.begin());
125  }
126 
129  {
130  return iteration_proxy_value<IteratorType>(container.end());
131  }
132 };
133 // Structured Bindings Support
134 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
135 // And see https://github.com/nlohmann/json/pull/1391
136 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
137 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
138 {
139  return i.key();
140 }
141 // Structured Bindings Support
142 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
143 // And see https://github.com/nlohmann/json/pull/1391
144 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
145 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
146 {
147  return i.value();
148 }
149 } // namespace detail
150 } // namespace nlohmann
151 
152 // The Addition to the STD Namespace is required to add
153 // Structured Bindings Support to the iteration_proxy_value class
154 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
155 // And see https://github.com/nlohmann/json/pull/1391
156 namespace std
157 {
158 #if defined(__clang__)
159  // Fix: https://github.com/nlohmann/json/issues/1401
160  #pragma clang diagnostic push
161  #pragma clang diagnostic ignored "-Wmismatched-tags"
162 #endif
163 template<typename IteratorType>
164 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
165  : public std::integral_constant<std::size_t, 2> {};
166 
167 template<std::size_t N, typename IteratorType>
168 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
169 {
170  public:
171  using type = decltype(
172  get<N>(std::declval <
174 };
175 #if defined(__clang__)
176  #pragma clang diagnostic pop
177 #endif
178 } // namespace std
Definition: iteration_proxy.hpp:23
iteration_proxy_value & operator*()
dereference operator (needed for range-based for)
Definition: iteration_proxy.hpp:48
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition: iteration_proxy.hpp:69
IteratorType::reference value() const
return value of the iterator
Definition: iteration_proxy.hpp:103
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition: iteration_proxy.hpp:54
const string_type & key() const
return key of the iterator
Definition: iteration_proxy.hpp:75
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition: iteration_proxy.hpp:63
proxy class for the items() function
Definition: iteration_proxy.hpp:111
iteration_proxy_value< IteratorType > begin() noexcept
return iterator begin (needed for range-based for)
Definition: iteration_proxy.hpp:122
iteration_proxy_value< IteratorType > end() noexcept
return iterator end (needed for range-based for)
Definition: iteration_proxy.hpp:128
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition: iteration_proxy.hpp:118
@ object
object (unordered set of name/value pairs)
@ array
array (ordered collection of values)
namespace for Niels Lohmann
Definition: adl_serializer.hpp:9
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:8684