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