WPILibC++ 2024.1.1-beta-4
iteration_proxy.h
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.2
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9#pragma once
10
11#include <cstddef> // size_t
12#include <iterator> // input_iterator_tag
13#include <string> // string, to_string
14#include <tuple> // tuple_size, get, tuple_element
15#include <utility> // move
16
17#if JSON_HAS_RANGES
18 #include <ranges> // enable_borrowed_range
19#endif
20
23#include <wpi/detail/value_t.h>
24
26namespace detail
27{
28
29template<typename string_type>
30void int_to_string( string_type& target, std::size_t value )
31{
32 // For ADL
33 using std::to_string;
34 target = to_string(value);
35}
36template<typename IteratorType> class iteration_proxy_value
37{
38 public:
39 using difference_type = std::ptrdiff_t;
43 using iterator_category = std::input_iterator_tag;
44 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
45
46 private:
47 /// the iterator
48 IteratorType anchor{};
49 /// an index for arrays (used to create key names)
50 std::size_t array_index = 0;
51 /// last stringified array index
52 mutable std::size_t array_index_last = 0;
53 /// a string representation of the array index
54 mutable string_type array_index_str = "0";
55 /// an empty string (to return a reference for primitive values)
56 string_type empty_str{};
57
58 public:
59 explicit iteration_proxy_value() = default;
60 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
61 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
62 && std::is_nothrow_default_constructible<string_type>::value)
63 : anchor(std::move(it))
64 , array_index(array_index_)
65 {}
66
69 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
71 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
72 && std::is_nothrow_move_constructible<string_type>::value) = default;
74 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
75 && std::is_nothrow_move_assignable<string_type>::value) = default;
77
78 /// dereference operator (needed for range-based for)
79 const iteration_proxy_value& operator*() const
80 {
81 return *this;
82 }
83
84 /// increment operator (needed for range-based for)
86 {
87 ++anchor;
88 ++array_index;
89
90 return *this;
91 }
92
93 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
94 {
95 auto tmp = iteration_proxy_value(anchor, array_index);
96 ++anchor;
97 ++array_index;
98 return tmp;
99 }
100
101 /// equality operator (needed for InputIterator)
103 {
104 return anchor == o.anchor;
105 }
106
107 /// inequality operator (needed for range-based for)
109 {
110 return anchor != o.anchor;
111 }
112
113 /// return key of the iterator
114 const string_type& key() const
115 {
116 JSON_ASSERT(anchor.m_object != nullptr);
117
118 switch (anchor.m_object->type())
119 {
120 // use integer array index as key
121 case value_t::array:
122 {
123 if (array_index != array_index_last)
124 {
125 int_to_string( array_index_str, array_index );
126 array_index_last = array_index;
127 }
128 return array_index_str;
129 }
130
131 // use key from the object
132 case value_t::object:
133 return anchor.key();
134
135 // use an empty key for all primitive types
136 case value_t::null:
137 case value_t::string:
138 case value_t::boolean:
142 case value_t::binary:
144 default:
145 return empty_str;
146 }
147 }
148
149 /// return value of the iterator
150 typename IteratorType::reference value() const
151 {
152 return anchor.value();
153 }
154};
155
156/// proxy class for the items() function
157template<typename IteratorType> class iteration_proxy
158{
159 private:
160 /// the container to iterate
161 typename IteratorType::pointer container = nullptr;
162
163 public:
164 explicit iteration_proxy() = default;
165
166 /// construct iteration proxy from a container
167 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
168 : container(&cont) {}
169
172 iteration_proxy(iteration_proxy&&) noexcept = default;
173 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
174 ~iteration_proxy() = default;
175
176 /// return iterator begin (needed for range-based for)
177 iteration_proxy_value<IteratorType> begin() const noexcept
178 {
179 return iteration_proxy_value<IteratorType>(container->begin());
180 }
181
182 /// return iterator end (needed for range-based for)
184 {
185 return iteration_proxy_value<IteratorType>(container->end());
186 }
187};
188
189// Structured Bindings Support
190// For further reference see https://blog.tartanllama.xyz/structured-bindings/
191// And see https://github.com/nlohmann/json/pull/1391
192template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
193auto get(const wpi::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
194{
195 return i.key();
196}
197// Structured Bindings Support
198// For further reference see https://blog.tartanllama.xyz/structured-bindings/
199// And see https://github.com/nlohmann/json/pull/1391
200template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
201auto get(const wpi::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
202{
203 return i.value();
204}
205
206} // namespace detail
208
209// The Addition to the STD Namespace is required to add
210// Structured Bindings Support to the iteration_proxy_value class
211// For further reference see https://blog.tartanllama.xyz/structured-bindings/
212// And see https://github.com/nlohmann/json/pull/1391
213namespace std
214{
215
216#if defined(__clang__)
217 // Fix: https://github.com/nlohmann/json/issues/1401
218 #pragma clang diagnostic push
219 #pragma clang diagnostic ignored "-Wmismatched-tags"
220#endif
221template<typename IteratorType>
222class tuple_size<::wpi::detail::iteration_proxy_value<IteratorType>>
223 : public std::integral_constant<std::size_t, 2> {};
224
225template<std::size_t N, typename IteratorType>
226class tuple_element<N, ::wpi::detail::iteration_proxy_value<IteratorType >>
227{
228 public:
229 using type = decltype(
230 get<N>(std::declval <
231 ::wpi::detail::iteration_proxy_value<IteratorType >> ()));
232};
233#if defined(__clang__)
234 #pragma clang diagnostic pop
235#endif
236
237} // namespace std
238
239#if JSON_HAS_RANGES
240 template <typename IteratorType>
241 inline constexpr bool ::std::ranges::enable_borrowed_range<::wpi::detail::iteration_proxy<IteratorType>> = true;
242#endif
#define WPI_JSON_NAMESPACE_END
Definition: abi_macros.h:59
#define WPI_JSON_NAMESPACE_BEGIN
Definition: abi_macros.h:53
Definition: iteration_proxy.h:37
iteration_proxy_value operator++(int) &
Definition: iteration_proxy.h:93
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition: iteration_proxy.h:102
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition: iteration_proxy.h:108
std::ptrdiff_t difference_type
Definition: iteration_proxy.h:39
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition: iteration_proxy.h:60
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition: iteration_proxy.h:85
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition: iteration_proxy.h:150
const string_type & key() const
return key of the iterator
Definition: iteration_proxy.h:114
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
std::input_iterator_tag iterator_category
Definition: iteration_proxy.h:43
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition: iteration_proxy.h:44
proxy class for the items() function
Definition: iteration_proxy.h:158
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition: iteration_proxy.h:183
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition: iteration_proxy.h:177
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition: iteration_proxy.h:167
iteration_proxy & operator=(iteration_proxy const &)=default
Definition: core.h:1238
decltype(get< N >(std::declval< ::wpi::detail::iteration_proxy_value< IteratorType > >())) type
Definition: iteration_proxy.h:231
#define JSON_ASSERT(x)
Definition: macro_scope.h:192
detail namespace with internal helper functions
Definition: ranges.h:23
auto get(const wpi::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: iteration_proxy.h:193
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
type
Definition: core.h:556
void int_to_string(string_type &target, std::size_t value)
Definition: iteration_proxy.h:30
Definition: array.h:89
std::string to_string(const T &t)
Definition: base.h:93