• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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