Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : #include <algorithm> // copy
4 : : #include <ciso646> // or, and, not
5 : : #include <iterator> // begin, end
6 : : #include <string> // string
7 : : #include <tuple> // tuple, get
8 : : #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
9 : : #include <utility> // move, forward, declval, pair
10 : : #include <valarray> // valarray
11 : : #include <vector> // vector
12 : :
13 : : #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14 : : #include <nlohmann/detail/meta/cpp_future.hpp>
15 : : #include <nlohmann/detail/meta/type_traits.hpp>
16 : : #include <nlohmann/detail/value_t.hpp>
17 : :
18 : : namespace nlohmann
19 : : {
20 : : namespace detail
21 : : {
22 : : //////////////////
23 : : // constructors //
24 : : //////////////////
25 : :
26 : : template<value_t> struct external_constructor;
27 : :
28 : : template<>
29 : : struct external_constructor<value_t::boolean>
30 : : {
31 : : template<typename BasicJsonType>
32 : 0 : static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
33 : : {
34 : 0 : j.m_type = value_t::boolean;
35 : 0 : j.m_value = b;
36 : 0 : j.assert_invariant();
37 : 0 : }
38 : : };
39 : :
40 : : template<>
41 : : struct external_constructor<value_t::string>
42 : : {
43 : : template<typename BasicJsonType>
44 : 0 : static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
45 : : {
46 : 0 : j.m_type = value_t::string;
47 : 0 : j.m_value = s;
48 : 0 : j.assert_invariant();
49 : 0 : }
50 : :
51 : : template<typename BasicJsonType>
52 : 0 : static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
53 : : {
54 : 0 : j.m_type = value_t::string;
55 : 0 : j.m_value = std::move(s);
56 : 0 : j.assert_invariant();
57 : 0 : }
58 : :
59 : : template<typename BasicJsonType, typename CompatibleStringType,
60 : : enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
61 : : int> = 0>
62 : 159 : static void construct(BasicJsonType& j, const CompatibleStringType& str)
63 : : {
64 : 159 : j.m_type = value_t::string;
65 : 159 : j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
66 : 159 : j.assert_invariant();
67 : 159 : }
68 : : };
69 : :
70 : : template<>
71 : : struct external_constructor<value_t::number_float>
72 : : {
73 : : template<typename BasicJsonType>
74 : 5510 : static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
75 : : {
76 : 5510 : j.m_type = value_t::number_float;
77 : 5510 : j.m_value = val;
78 : 5510 : j.assert_invariant();
79 : 5510 : }
80 : : };
81 : :
82 : : template<>
83 : : struct external_constructor<value_t::number_unsigned>
84 : : {
85 : : template<typename BasicJsonType>
86 : 0 : static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
87 : : {
88 : 0 : j.m_type = value_t::number_unsigned;
89 : 0 : j.m_value = val;
90 : 0 : j.assert_invariant();
91 : 0 : }
92 : : };
93 : :
94 : : template<>
95 : : struct external_constructor<value_t::number_integer>
96 : : {
97 : : template<typename BasicJsonType>
98 : 0 : static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
99 : : {
100 : 0 : j.m_type = value_t::number_integer;
101 : 0 : j.m_value = val;
102 : 0 : j.assert_invariant();
103 : 0 : }
104 : : };
105 : :
106 : : template<>
107 : : struct external_constructor<value_t::array>
108 : : {
109 : : template<typename BasicJsonType>
110 : : static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
111 : : {
112 : : j.m_type = value_t::array;
113 : : j.m_value = arr;
114 : : j.assert_invariant();
115 : : }
116 : :
117 : : template<typename BasicJsonType>
118 : : static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
119 : : {
120 : : j.m_type = value_t::array;
121 : : j.m_value = std::move(arr);
122 : : j.assert_invariant();
123 : : }
124 : :
125 : : template<typename BasicJsonType, typename CompatibleArrayType,
126 : : enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
127 : : int> = 0>
128 : : static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
129 : : {
130 : : using std::begin;
131 : : using std::end;
132 : : j.m_type = value_t::array;
133 : : j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
134 : : j.assert_invariant();
135 : : }
136 : :
137 : : template<typename BasicJsonType>
138 : : static void construct(BasicJsonType& j, const std::vector<bool>& arr)
139 : : {
140 : : j.m_type = value_t::array;
141 : : j.m_value = value_t::array;
142 : : j.m_value.array->reserve(arr.size());
143 : : for (const bool x : arr)
144 : : {
145 : : j.m_value.array->push_back(x);
146 : : }
147 : : j.assert_invariant();
148 : : }
149 : :
150 : : template<typename BasicJsonType, typename T,
151 : : enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
152 : : static void construct(BasicJsonType& j, const std::valarray<T>& arr)
153 : : {
154 : : j.m_type = value_t::array;
155 : : j.m_value = value_t::array;
156 : : j.m_value.array->resize(arr.size());
157 : : std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
158 : : j.assert_invariant();
159 : : }
160 : : };
161 : :
162 : : template<>
163 : : struct external_constructor<value_t::object>
164 : : {
165 : : template<typename BasicJsonType>
166 : : static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
167 : : {
168 : : j.m_type = value_t::object;
169 : : j.m_value = obj;
170 : : j.assert_invariant();
171 : : }
172 : :
173 : : template<typename BasicJsonType>
174 : : static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
175 : : {
176 : : j.m_type = value_t::object;
177 : : j.m_value = std::move(obj);
178 : : j.assert_invariant();
179 : : }
180 : :
181 : : template<typename BasicJsonType, typename CompatibleObjectType,
182 : : enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
183 : : static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
184 : : {
185 : : using std::begin;
186 : : using std::end;
187 : :
188 : : j.m_type = value_t::object;
189 : : j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
190 : : j.assert_invariant();
191 : : }
192 : : };
193 : :
194 : : /////////////
195 : : // to_json //
196 : : /////////////
197 : :
198 : : template<typename BasicJsonType, typename T,
199 : : enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
200 : 0 : void to_json(BasicJsonType& j, T b) noexcept
201 : : {
202 : 0 : external_constructor<value_t::boolean>::construct(j, b);
203 : 0 : }
204 : :
205 : : template<typename BasicJsonType, typename CompatibleString,
206 : : enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
207 : 159 : void to_json(BasicJsonType& j, const CompatibleString& s)
208 : : {
209 : 159 : external_constructor<value_t::string>::construct(j, s);
210 : 159 : }
211 : :
212 : : template<typename BasicJsonType>
213 : 0 : void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
214 : : {
215 : 0 : external_constructor<value_t::string>::construct(j, std::move(s));
216 : 0 : }
217 : :
218 : : template<typename BasicJsonType, typename FloatType,
219 : : enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
220 : 5510 : void to_json(BasicJsonType& j, FloatType val) noexcept
221 : : {
222 : 5510 : external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
223 : 5510 : }
224 : :
225 : : template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
226 : : enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
227 : 0 : void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
228 : : {
229 : 0 : external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
230 : 0 : }
231 : :
232 : : template<typename BasicJsonType, typename CompatibleNumberIntegerType,
233 : : enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
234 : 0 : void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
235 : : {
236 : 0 : external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
237 : 0 : }
238 : :
239 : : template<typename BasicJsonType, typename EnumType,
240 : : enable_if_t<std::is_enum<EnumType>::value, int> = 0>
241 : : void to_json(BasicJsonType& j, EnumType e) noexcept
242 : : {
243 : : using underlying_type = typename std::underlying_type<EnumType>::type;
244 : : external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
245 : : }
246 : :
247 : : template<typename BasicJsonType>
248 : : void to_json(BasicJsonType& j, const std::vector<bool>& e)
249 : : {
250 : : external_constructor<value_t::array>::construct(j, e);
251 : : }
252 : :
253 : : template <typename BasicJsonType, typename CompatibleArrayType,
254 : : enable_if_t<is_compatible_array_type<BasicJsonType,
255 : : CompatibleArrayType>::value and
256 : : not is_compatible_object_type<
257 : : BasicJsonType, CompatibleArrayType>::value and
258 : : not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
259 : : not is_basic_json<CompatibleArrayType>::value,
260 : : int> = 0>
261 : : void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
262 : : {
263 : : external_constructor<value_t::array>::construct(j, arr);
264 : : }
265 : :
266 : : template<typename BasicJsonType, typename T,
267 : : enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
268 : : void to_json(BasicJsonType& j, const std::valarray<T>& arr)
269 : : {
270 : : external_constructor<value_t::array>::construct(j, std::move(arr));
271 : : }
272 : :
273 : : template<typename BasicJsonType>
274 : : void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
275 : : {
276 : : external_constructor<value_t::array>::construct(j, std::move(arr));
277 : : }
278 : :
279 : : template<typename BasicJsonType, typename CompatibleObjectType,
280 : : enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
281 : : void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
282 : : {
283 : : external_constructor<value_t::object>::construct(j, obj);
284 : : }
285 : :
286 : : template<typename BasicJsonType>
287 : : void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
288 : : {
289 : : external_constructor<value_t::object>::construct(j, std::move(obj));
290 : : }
291 : :
292 : : template <
293 : : typename BasicJsonType, typename T, std::size_t N,
294 : : enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
295 : : const T(&)[N]>::value,
296 : : int> = 0 >
297 : : void to_json(BasicJsonType& j, const T(&arr)[N])
298 : : {
299 : : external_constructor<value_t::array>::construct(j, arr);
300 : : }
301 : :
302 : : template<typename BasicJsonType, typename... Args>
303 : : void to_json(BasicJsonType& j, const std::pair<Args...>& p)
304 : : {
305 : : j = { p.first, p.second };
306 : : }
307 : :
308 : : // for https://github.com/nlohmann/json/pull/1134
309 : : template < typename BasicJsonType, typename T,
310 : : enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
311 : : void to_json(BasicJsonType& j, const T& b)
312 : : {
313 : : j = { {b.key(), b.value()} };
314 : : }
315 : :
316 : : template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
317 : : void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
318 : : {
319 : : j = { std::get<Idx>(t)... };
320 : : }
321 : :
322 : : template<typename BasicJsonType, typename... Args>
323 : : void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
324 : : {
325 : : to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
326 : : }
327 : :
328 : : struct to_json_fn
329 : : {
330 : : template<typename BasicJsonType, typename T>
331 : 5669 : auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
332 : : -> decltype(to_json(j, std::forward<T>(val)), void())
333 : : {
334 : 5669 : return to_json(j, std::forward<T>(val));
335 : : }
336 : : };
337 : : } // namespace detail
338 : :
339 : : /// namespace to hold default `to_json` function
340 : : namespace
341 : : {
342 : : constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
343 : : } // namespace
344 : : } // namespace nlohmann
|