0d3e555d84b23bef97cdd92a56edb068ed2ae05f
[o-du/phy.git] / fhi_lib / test / common / json.hpp
1 /*\r
2     __ _____ _____ _____\r
3  __|  |   __|     |   | |  JSON for Modern C++\r
4 |  |  |__   |  |  | | | |  version 2.1.1\r
5 |_____|_____|_____|_|___|  https://github.com/nlohmann/json\r
6 \r
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.\r
8 Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.\r
9 \r
10 Permission is hereby  granted, free of charge, to any  person obtaining a copy\r
11 of this software and associated  documentation files (the "Software"), to deal\r
12 in the Software  without restriction, including without  limitation the rights\r
13 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell\r
14 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is\r
15 furnished to do so, subject to the following conditions:\r
16 \r
17 The above copyright notice and this permission notice shall be included in all\r
18 copies or substantial portions of the Software.\r
19 \r
20 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR\r
21 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,\r
22 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE\r
23 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER\r
24 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE\r
26 SOFTWARE.\r
27 */\r
28 \r
29 #ifndef NLOHMANN_JSON_HPP\r
30 #define NLOHMANN_JSON_HPP\r
31 \r
32 #include <algorithm> // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform\r
33 #include <array> // array\r
34 #include <cassert> // assert\r
35 #include <cctype> // isdigit\r
36 #include <ciso646> // and, not, or\r
37 #include <cmath> // isfinite, labs, ldexp, signbit\r
38 #include <cstddef> // nullptr_t, ptrdiff_t, size_t\r
39 #include <cstdint> // int64_t, uint64_t\r
40 #include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull\r
41 #include <cstring> // strlen\r
42 #include <forward_list> // forward_list\r
43 #include <functional> // function, hash, less\r
44 #include <initializer_list> // initializer_list\r
45 #include <iomanip> // setw\r
46 #include <iostream> // istream, ostream\r
47 #include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator\r
48 #include <limits> // numeric_limits\r
49 #include <locale> // locale\r
50 #include <map> // map\r
51 #include <memory> // addressof, allocator, allocator_traits, unique_ptr\r
52 #include <numeric> // accumulate\r
53 #include <sstream> // stringstream\r
54 #include <stdexcept> // domain_error, invalid_argument, out_of_range\r
55 #include <string> // getline, stoi, string, to_string\r
56 #include <type_traits> // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type\r
57 #include <utility> // declval, forward, make_pair, move, pair, swap\r
58 #include <vector> // vector\r
59 \r
60 // allow for portable deprecation warnings\r
61 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\r
62     #define JSON_DEPRECATED __attribute__((deprecated))\r
63 #elif defined(_MSC_VER)\r
64     #define JSON_DEPRECATED __declspec(deprecated)\r
65 #else\r
66     #define JSON_DEPRECATED\r
67 #endif\r
68 \r
69 // allow to disable exceptions\r
70 #if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS)\r
71     #define JSON_THROW(exception) throw exception\r
72     #define JSON_TRY try\r
73     #define JSON_CATCH(exception) catch(exception)\r
74 #else\r
75     #define JSON_THROW(exception) std::abort()\r
76     #define JSON_TRY if(true)\r
77     #define JSON_CATCH(exception) if(false)\r
78 #endif\r
79 \r
80 /*!\r
81 @brief namespace for Niels Lohmann\r
82 @see https://github.com/nlohmann\r
83 @since version 1.0.0\r
84 */\r
85 namespace nlohmann\r
86 {\r
87 \r
88 /*!\r
89 @brief unnamed namespace with internal helper functions\r
90 \r
91 This namespace collects some functions that could not be defined inside the\r
92 @ref basic_json class.\r
93 \r
94 @since version 2.1.0\r
95 */\r
96 namespace detail\r
97 {\r
98 ///////////////////////////\r
99 // JSON type enumeration //\r
100 ///////////////////////////\r
101 \r
102 /*!\r
103 @brief the JSON type enumeration\r
104 \r
105 This enumeration collects the different JSON types. It is internally used to\r
106 distinguish the stored values, and the functions @ref basic_json::is_null(),\r
107 @ref basic_json::is_object(), @ref basic_json::is_array(),\r
108 @ref basic_json::is_string(), @ref basic_json::is_boolean(),\r
109 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),\r
110 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),\r
111 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and\r
112 @ref basic_json::is_structured() rely on it.\r
113 \r
114 @note There are three enumeration entries (number_integer, number_unsigned, and\r
115 number_float), because the library distinguishes these three types for numbers:\r
116 @ref basic_json::number_unsigned_t is used for unsigned integers,\r
117 @ref basic_json::number_integer_t is used for signed integers, and\r
118 @ref basic_json::number_float_t is used for floating-point numbers or to\r
119 approximate integers which do not fit in the limits of their respective type.\r
120 \r
121 @sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON\r
122 value with the default value for a given type\r
123 \r
124 @since version 1.0.0\r
125 */\r
126 enum class value_t : uint8_t\r
127 {\r
128     null,            ///< null value\r
129     object,          ///< object (unordered set of name/value pairs)\r
130     array,           ///< array (ordered collection of values)\r
131     string,          ///< string value\r
132     boolean,         ///< boolean value\r
133     number_integer,  ///< number value (signed integer)\r
134     number_unsigned, ///< number value (unsigned integer)\r
135     number_float,    ///< number value (floating-point)\r
136     discarded        ///< discarded by the the parser callback function\r
137 };\r
138 \r
139 /*!\r
140 @brief comparison operator for JSON types\r
141 \r
142 Returns an ordering that is similar to Python:\r
143 - order: null < boolean < number < object < array < string\r
144 - furthermore, each type is not smaller than itself\r
145 \r
146 @since version 1.0.0\r
147 */\r
148 inline bool operator<(const value_t lhs, const value_t rhs) noexcept\r
149 {\r
150     static constexpr std::array<uint8_t, 8> order = {{\r
151             0, // null\r
152             3, // object\r
153             4, // array\r
154             5, // string\r
155             1, // boolean\r
156             2, // integer\r
157             2, // unsigned\r
158             2, // float\r
159         }\r
160     };\r
161 \r
162     // discarded values are not comparable\r
163     if (lhs == value_t::discarded or rhs == value_t::discarded)\r
164     {\r
165         return false;\r
166     }\r
167 \r
168     return order[static_cast<std::size_t>(lhs)] <\r
169            order[static_cast<std::size_t>(rhs)];\r
170 }\r
171 \r
172 \r
173 /////////////\r
174 // helpers //\r
175 /////////////\r
176 \r
177 // alias templates to reduce boilerplate\r
178 template<bool B, typename T = void>\r
179 using enable_if_t = typename std::enable_if<B, T>::type;\r
180 \r
181 template<typename T>\r
182 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;\r
183 \r
184 // taken from http://stackoverflow.com/a/26936864/266378\r
185 template<typename T>\r
186 using is_unscoped_enum =\r
187     std::integral_constant<bool, std::is_convertible<T, int>::value and\r
188     std::is_enum<T>::value>;\r
189 \r
190 /*\r
191 Implementation of two C++17 constructs: conjunction, negation. This is needed\r
192 to avoid evaluating all the traits in a condition\r
193 \r
194 For example: not std::is_same<void, T>::value and has_value_type<T>::value\r
195 will not compile when T = void (on MSVC at least). Whereas\r
196 conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will\r
197 stop evaluating if negation<...>::value == false\r
198 \r
199 Please note that those constructs must be used with caution, since symbols can\r
200 become very long quickly (which can slow down compilation and cause MSVC\r
201 internal compiler errors). Only use it when you have to (see example ahead).\r
202 */\r
203 template<class...> struct conjunction : std::true_type {};\r
204 template<class B1> struct conjunction<B1> : B1 {};\r
205 template<class B1, class... Bn>\r
206 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};\r
207 \r
208 template<class B> struct negation : std::integral_constant < bool, !B::value > {};\r
209 \r
210 // dispatch utility (taken from ranges-v3)\r
211 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};\r
212 template<> struct priority_tag<0> {};\r
213 \r
214 \r
215 //////////////////\r
216 // constructors //\r
217 //////////////////\r
218 \r
219 template<value_t> struct external_constructor;\r
220 \r
221 template<>\r
222 struct external_constructor<value_t::boolean>\r
223 {\r
224     template<typename BasicJsonType>\r
225     static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept\r
226     {\r
227         j.m_type = value_t::boolean;\r
228         j.m_value = b;\r
229         j.assert_invariant();\r
230     }\r
231 };\r
232 \r
233 template<>\r
234 struct external_constructor<value_t::string>\r
235 {\r
236     template<typename BasicJsonType>\r
237     static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)\r
238     {\r
239         j.m_type = value_t::string;\r
240         j.m_value = s;\r
241         j.assert_invariant();\r
242     }\r
243 };\r
244 \r
245 template<>\r
246 struct external_constructor<value_t::number_float>\r
247 {\r
248     template<typename BasicJsonType>\r
249     static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept\r
250     {\r
251         // replace infinity and NAN by null\r
252         if (not std::isfinite(val))\r
253         {\r
254             j = BasicJsonType{};\r
255         }\r
256         else\r
257         {\r
258             j.m_type = value_t::number_float;\r
259             j.m_value = val;\r
260         }\r
261         j.assert_invariant();\r
262     }\r
263 };\r
264 \r
265 template<>\r
266 struct external_constructor<value_t::number_unsigned>\r
267 {\r
268     template<typename BasicJsonType>\r
269     static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept\r
270     {\r
271         j.m_type = value_t::number_unsigned;\r
272         j.m_value = val;\r
273         j.assert_invariant();\r
274     }\r
275 };\r
276 \r
277 template<>\r
278 struct external_constructor<value_t::number_integer>\r
279 {\r
280     template<typename BasicJsonType>\r
281     static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept\r
282     {\r
283         j.m_type = value_t::number_integer;\r
284         j.m_value = val;\r
285         j.assert_invariant();\r
286     }\r
287 };\r
288 \r
289 template<>\r
290 struct external_constructor<value_t::array>\r
291 {\r
292     template<typename BasicJsonType>\r
293     static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)\r
294     {\r
295         j.m_type = value_t::array;\r
296         j.m_value = arr;\r
297         j.assert_invariant();\r
298     }\r
299 \r
300     template<typename BasicJsonType, typename CompatibleArrayType,\r
301              enable_if_t<not std::is_same<CompatibleArrayType,\r
302                                           typename BasicJsonType::array_t>::value,\r
303                          int> = 0>\r
304     static void construct(BasicJsonType& j, const CompatibleArrayType& arr)\r
305     {\r
306         using std::begin;\r
307         using std::end;\r
308         j.m_type = value_t::array;\r
309         j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));\r
310         j.assert_invariant();\r
311     }\r
312 };\r
313 \r
314 template<>\r
315 struct external_constructor<value_t::object>\r
316 {\r
317     template<typename BasicJsonType>\r
318     static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)\r
319     {\r
320         j.m_type = value_t::object;\r
321         j.m_value = obj;\r
322         j.assert_invariant();\r
323     }\r
324 \r
325     template<typename BasicJsonType, typename CompatibleObjectType,\r
326              enable_if_t<not std::is_same<CompatibleObjectType,\r
327                                           typename BasicJsonType::object_t>::value,\r
328                          int> = 0>\r
329     static void construct(BasicJsonType& j, const CompatibleObjectType& obj)\r
330     {\r
331         using std::begin;\r
332         using std::end;\r
333 \r
334         j.m_type = value_t::object;\r
335         j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));\r
336         j.assert_invariant();\r
337     }\r
338 };\r
339 \r
340 \r
341 ////////////////////////\r
342 // has_/is_ functions //\r
343 ////////////////////////\r
344 \r
345 /*!\r
346 @brief Helper to determine whether there's a key_type for T.\r
347 \r
348 This helper is used to tell associative containers apart from other containers\r
349 such as sequence containers. For instance, `std::map` passes the test as it\r
350 contains a `mapped_type`, whereas `std::vector` fails the test.\r
351 \r
352 @sa http://stackoverflow.com/a/7728728/266378\r
353 @since version 1.0.0, overworked in version 2.0.6\r
354 */\r
355 #define NLOHMANN_JSON_HAS_HELPER(type)                                        \\r
356     template<typename T> struct has_##type {                                  \\r
357     private:                                                                  \\r
358         template<typename U, typename = typename U::type>                     \\r
359         static int detect(U &&);                                              \\r
360         static void detect(...);                                              \\r
361     public:                                                                   \\r
362         static constexpr bool value =                                         \\r
363                 std::is_integral<decltype(detect(std::declval<T>()))>::value; \\r
364     }\r
365 \r
366 NLOHMANN_JSON_HAS_HELPER(mapped_type);\r
367 NLOHMANN_JSON_HAS_HELPER(key_type);\r
368 NLOHMANN_JSON_HAS_HELPER(value_type);\r
369 NLOHMANN_JSON_HAS_HELPER(iterator);\r
370 \r
371 #undef NLOHMANN_JSON_HAS_HELPER\r
372 \r
373 \r
374 template<bool B, class RealType, class CompatibleObjectType>\r
375 struct is_compatible_object_type_impl : std::false_type {};\r
376 \r
377 template<class RealType, class CompatibleObjectType>\r
378 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>\r
379 {\r
380     static constexpr auto value =\r
381         std::is_constructible<typename RealType::key_type,\r
382         typename CompatibleObjectType::key_type>::value and\r
383         std::is_constructible<typename RealType::mapped_type,\r
384         typename CompatibleObjectType::mapped_type>::value;\r
385 };\r
386 \r
387 template<class BasicJsonType, class CompatibleObjectType>\r
388 struct is_compatible_object_type\r
389 {\r
390     static auto constexpr value = is_compatible_object_type_impl <\r
391                                   conjunction<negation<std::is_same<void, CompatibleObjectType>>,\r
392                                   has_mapped_type<CompatibleObjectType>,\r
393                                   has_key_type<CompatibleObjectType>>::value,\r
394                                   typename BasicJsonType::object_t, CompatibleObjectType >::value;\r
395 };\r
396 \r
397 template<typename BasicJsonType, typename T>\r
398 struct is_basic_json_nested_type\r
399 {\r
400     static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or\r
401                                   std::is_same<T, typename BasicJsonType::const_iterator>::value or\r
402                                   std::is_same<T, typename BasicJsonType::reverse_iterator>::value or\r
403                                   std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value or\r
404                                   std::is_same<T, typename BasicJsonType::json_pointer>::value;\r
405 };\r
406 \r
407 template<class BasicJsonType, class CompatibleArrayType>\r
408 struct is_compatible_array_type\r
409 {\r
410     static auto constexpr value =\r
411         conjunction<negation<std::is_same<void, CompatibleArrayType>>,\r
412         negation<is_compatible_object_type<\r
413         BasicJsonType, CompatibleArrayType>>,\r
414         negation<std::is_constructible<typename BasicJsonType::string_t,\r
415         CompatibleArrayType>>,\r
416         negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,\r
417         has_value_type<CompatibleArrayType>,\r
418         has_iterator<CompatibleArrayType>>::value;\r
419 };\r
420 \r
421 template<bool, typename, typename>\r
422 struct is_compatible_integer_type_impl : std::false_type {};\r
423 \r
424 template<typename RealIntegerType, typename CompatibleNumberIntegerType>\r
425 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>\r
426 {\r
427     // is there an assert somewhere on overflows?\r
428     using RealLimits = std::numeric_limits<RealIntegerType>;\r
429     using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;\r
430 \r
431     static constexpr auto value =\r
432         std::is_constructible<RealIntegerType,\r
433         CompatibleNumberIntegerType>::value and\r
434         CompatibleLimits::is_integer and\r
435         RealLimits::is_signed == CompatibleLimits::is_signed;\r
436 };\r
437 \r
438 template<typename RealIntegerType, typename CompatibleNumberIntegerType>\r
439 struct is_compatible_integer_type\r
440 {\r
441     static constexpr auto value =\r
442         is_compatible_integer_type_impl <\r
443         std::is_integral<CompatibleNumberIntegerType>::value and\r
444         not std::is_same<bool, CompatibleNumberIntegerType>::value,\r
445         RealIntegerType, CompatibleNumberIntegerType > ::value;\r
446 };\r
447 \r
448 \r
449 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists\r
450 template<typename BasicJsonType, typename T>\r
451 struct has_from_json\r
452 {\r
453   private:\r
454     // also check the return type of from_json\r
455     template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(\r
456                  std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>\r
457     static int detect(U&&);\r
458     static void detect(...);\r
459 \r
460   public:\r
461     static constexpr bool value = std::is_integral<decltype(\r
462                                       detect(std::declval<typename BasicJsonType::template json_serializer<T, void > >()))>::value;\r
463 };\r
464 \r
465 // This trait checks if JSONSerializer<T>::from_json(json const&) exists\r
466 // this overload is used for non-default-constructible user-defined-types\r
467 template<typename BasicJsonType, typename T>\r
468 struct has_non_default_from_json\r
469 {\r
470   private:\r
471     template <\r
472         typename U,\r
473         typename = enable_if_t<std::is_same<\r
474                                    T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>\r
475     static int detect(U&&);\r
476     static void detect(...);\r
477 \r
478   public:\r
479     static constexpr bool value = std::is_integral<decltype(detect(\r
480                                       std::declval<typename BasicJsonType::template json_serializer<T, void> >()))>::value;\r
481 };\r
482 \r
483 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists\r
484 template<typename BasicJsonType, typename T>\r
485 struct has_to_json\r
486 {\r
487   private:\r
488     template<typename U, typename = decltype(uncvref_t<U>::to_json(\r
489                  std::declval<BasicJsonType&>(), std::declval<T>()))>\r
490     static int detect(U&&);\r
491     static void detect(...);\r
492 \r
493   public:\r
494     static constexpr bool value = std::is_integral<decltype(detect(\r
495                                       std::declval<typename BasicJsonType::template json_serializer<T, void> >()))>::value;\r
496 };\r
497 \r
498 \r
499 /////////////\r
500 // to_json //\r
501 /////////////\r
502 \r
503 template<typename BasicJsonType, typename T, enable_if_t<\r
504              std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>\r
505 void to_json(BasicJsonType& j, T b) noexcept\r
506 {\r
507     external_constructor<value_t::boolean>::construct(j, b);\r
508 }\r
509 \r
510 template<typename BasicJsonType, typename CompatibleString,\r
511          enable_if_t<std::is_constructible<typename BasicJsonType::string_t,\r
512                      CompatibleString>::value, int> = 0>\r
513 void to_json(BasicJsonType& j, const CompatibleString& s)\r
514 {\r
515     external_constructor<value_t::string>::construct(j, s);\r
516 }\r
517 \r
518 template<typename BasicJsonType, typename FloatType,\r
519          enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>\r
520 void to_json(BasicJsonType& j, FloatType val) noexcept\r
521 {\r
522     external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));\r
523 }\r
524 \r
525 template <\r
526     typename BasicJsonType, typename CompatibleNumberUnsignedType,\r
527     enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,\r
528                 CompatibleNumberUnsignedType>::value, int> = 0 >\r
529 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept\r
530 {\r
531     external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));\r
532 }\r
533 \r
534 template <\r
535     typename BasicJsonType, typename CompatibleNumberIntegerType,\r
536     enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t,\r
537                 CompatibleNumberIntegerType>::value, int> = 0 >\r
538 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept\r
539 {\r
540     external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));\r
541 }\r
542 \r
543 template<typename BasicJsonType, typename UnscopedEnumType,\r
544          enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>\r
545 void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept\r
546 {\r
547     external_constructor<value_t::number_integer>::construct(j, e);\r
548 }\r
549 \r
550 template <\r
551     typename BasicJsonType, typename CompatibleArrayType,\r
552     enable_if_t <\r
553         is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or\r
554         std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,\r
555         int > = 0 >\r
556 void to_json(BasicJsonType& j, const  CompatibleArrayType& arr)\r
557 {\r
558     external_constructor<value_t::array>::construct(j, arr);\r
559 }\r
560 \r
561 template <\r
562     typename BasicJsonType, typename CompatibleObjectType,\r
563     enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,\r
564                 int> = 0 >\r
565 void to_json(BasicJsonType& j, const  CompatibleObjectType& arr)\r
566 {\r
567     external_constructor<value_t::object>::construct(j, arr);\r
568 }\r
569 \r
570 \r
571 ///////////////\r
572 // from_json //\r
573 ///////////////\r
574 \r
575 // overloads for basic_json template parameters\r
576 template<typename BasicJsonType, typename ArithmeticType,\r
577          enable_if_t<std::is_arithmetic<ArithmeticType>::value and\r
578                      not std::is_same<ArithmeticType,\r
579                                       typename BasicJsonType::boolean_t>::value,\r
580                      int> = 0>\r
581 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)\r
582 {\r
583     switch (static_cast<value_t>(j))\r
584     {\r
585         case value_t::number_unsigned:\r
586         {\r
587             val = static_cast<ArithmeticType>(\r
588                       *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());\r
589             break;\r
590         }\r
591         case value_t::number_integer:\r
592         {\r
593             val = static_cast<ArithmeticType>(\r
594                       *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());\r
595             break;\r
596         }\r
597         case value_t::number_float:\r
598         {\r
599             val = static_cast<ArithmeticType>(\r
600                       *j.template get_ptr<const typename BasicJsonType::number_float_t*>());\r
601             break;\r
602         }\r
603         default:\r
604         {\r
605             JSON_THROW(\r
606                 std::domain_error("type must be number, but is " + j.type_name()));\r
607         }\r
608     }\r
609 }\r
610 \r
611 template<typename BasicJsonType>\r
612 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)\r
613 {\r
614     if (not j.is_boolean())\r
615     {\r
616         JSON_THROW(std::domain_error("type must be boolean, but is " + j.type_name()));\r
617     }\r
618     b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();\r
619 }\r
620 \r
621 template<typename BasicJsonType>\r
622 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)\r
623 {\r
624     if (not j.is_string())\r
625     {\r
626         JSON_THROW(std::domain_error("type must be string, but is " + j.type_name()));\r
627     }\r
628     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();\r
629 }\r
630 \r
631 template<typename BasicJsonType>\r
632 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)\r
633 {\r
634     get_arithmetic_value(j, val);\r
635 }\r
636 \r
637 template<typename BasicJsonType>\r
638 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)\r
639 {\r
640     get_arithmetic_value(j, val);\r
641 }\r
642 \r
643 template<typename BasicJsonType>\r
644 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)\r
645 {\r
646     get_arithmetic_value(j, val);\r
647 }\r
648 \r
649 template<typename BasicJsonType, typename UnscopedEnumType,\r
650          enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>\r
651 void from_json(const BasicJsonType& j, UnscopedEnumType& e)\r
652 {\r
653     typename std::underlying_type<UnscopedEnumType>::type val;\r
654     get_arithmetic_value(j, val);\r
655     e = static_cast<UnscopedEnumType>(val);\r
656 }\r
657 \r
658 template<typename BasicJsonType>\r
659 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)\r
660 {\r
661     if (not j.is_array())\r
662     {\r
663         JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));\r
664     }\r
665     arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();\r
666 }\r
667 \r
668 // forward_list doesn't have an insert method\r
669 template<typename BasicJsonType, typename T, typename Allocator>\r
670 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)\r
671 {\r
672     // do not perform the check when user wants to retrieve jsons\r
673     // (except when it's null.. ?)\r
674     if (j.is_null())\r
675     {\r
676         JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));\r
677     }\r
678     if (not std::is_same<T, BasicJsonType>::value)\r
679     {\r
680         if (not j.is_array())\r
681         {\r
682             JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));\r
683         }\r
684     }\r
685     for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)\r
686     {\r
687         l.push_front(it->template get<T>());\r
688     }\r
689 }\r
690 \r
691 template<typename BasicJsonType, typename CompatibleArrayType>\r
692 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)\r
693 {\r
694     using std::begin;\r
695     using std::end;\r
696 \r
697     std::transform(j.begin(), j.end(),\r
698                    std::inserter(arr, end(arr)), [](const BasicJsonType & i)\r
699     {\r
700         // get<BasicJsonType>() returns *this, this won't call a from_json\r
701         // method when value_type is BasicJsonType\r
702         return i.template get<typename CompatibleArrayType::value_type>();\r
703     });\r
704 }\r
705 \r
706 template<typename BasicJsonType, typename CompatibleArrayType>\r
707 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)\r
708 -> decltype(\r
709     arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),\r
710     void())\r
711 {\r
712     using std::begin;\r
713     using std::end;\r
714 \r
715     arr.reserve(j.size());\r
716     std::transform(\r
717         j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i)\r
718     {\r
719         // get<BasicJsonType>() returns *this, this won't call a from_json\r
720         // method when value_type is BasicJsonType\r
721         return i.template get<typename CompatibleArrayType::value_type>();\r
722     });\r
723 }\r
724 \r
725 template<typename BasicJsonType, typename CompatibleArrayType,\r
726          enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and\r
727                      not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>\r
728 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)\r
729 {\r
730     if (j.is_null())\r
731     {\r
732         JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));\r
733     }\r
734 \r
735     // when T == BasicJsonType, do not check if value_t is correct\r
736     if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)\r
737     {\r
738         if (not j.is_array())\r
739         {\r
740             JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));\r
741         }\r
742     }\r
743     from_json_array_impl(j, arr, priority_tag<1> {});\r
744 }\r
745 \r
746 template<typename BasicJsonType, typename CompatibleObjectType,\r
747          enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>\r
748 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)\r
749 {\r
750     if (not j.is_object())\r
751     {\r
752         JSON_THROW(std::domain_error("type must be object, but is " + j.type_name()));\r
753     }\r
754 \r
755     auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();\r
756     using std::begin;\r
757     using std::end;\r
758     // we could avoid the assignment, but this might require a for loop, which\r
759     // might be less efficient than the container constructor for some\r
760     // containers (would it?)\r
761     obj = CompatibleObjectType(begin(*inner_object), end(*inner_object));\r
762 }\r
763 \r
764 // overload for arithmetic types, not chosen for basic_json template arguments\r
765 // (BooleanType, etc..); note: Is it really necessary to provide explicit\r
766 // overloads for boolean_t etc. in case of a custom BooleanType which is not\r
767 // an arithmetic type?\r
768 template<typename BasicJsonType, typename ArithmeticType,\r
769          enable_if_t <\r
770              std::is_arithmetic<ArithmeticType>::value and\r
771              not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and\r
772              not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and\r
773              not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and\r
774              not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,\r
775              int> = 0>\r
776 void from_json(const BasicJsonType& j, ArithmeticType& val)\r
777 {\r
778     switch (static_cast<value_t>(j))\r
779     {\r
780         case value_t::number_unsigned:\r
781         {\r
782             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());\r
783             break;\r
784         }\r
785         case value_t::number_integer:\r
786         {\r
787             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());\r
788             break;\r
789         }\r
790         case value_t::number_float:\r
791         {\r
792             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());\r
793             break;\r
794         }\r
795         case value_t::boolean:\r
796         {\r
797             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());\r
798             break;\r
799         }\r
800         default:\r
801         {\r
802             JSON_THROW(std::domain_error("type must be number, but is " + j.type_name()));\r
803         }\r
804     }\r
805 }\r
806 \r
807 struct to_json_fn\r
808 {\r
809   private:\r
810     template<typename BasicJsonType, typename T>\r
811     auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward<T>(val))))\r
812     -> decltype(to_json(j, std::forward<T>(val)), void())\r
813     {\r
814         return to_json(j, std::forward<T>(val));\r
815     }\r
816 \r
817     template<typename BasicJsonType, typename T>\r
818     void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept\r
819     {\r
820         static_assert(sizeof(BasicJsonType) == 0,\r
821                       "could not find to_json() method in T's namespace");\r
822     }\r
823 \r
824   public:\r
825     template<typename BasicJsonType, typename T>\r
826     void operator()(BasicJsonType& j, T&& val) const\r
827     noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))\r
828     {\r
829         return call(j, std::forward<T>(val), priority_tag<1> {});\r
830     }\r
831 };\r
832 \r
833 struct from_json_fn\r
834 {\r
835   private:\r
836     template<typename BasicJsonType, typename T>\r
837     auto call(const BasicJsonType& j, T& val, priority_tag<1>) const\r
838     noexcept(noexcept(from_json(j, val)))\r
839     -> decltype(from_json(j, val), void())\r
840     {\r
841         return from_json(j, val);\r
842     }\r
843 \r
844     template<typename BasicJsonType, typename T>\r
845     void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept\r
846     {\r
847         static_assert(sizeof(BasicJsonType) == 0,\r
848                       "could not find from_json() method in T's namespace");\r
849     }\r
850 \r
851   public:\r
852     template<typename BasicJsonType, typename T>\r
853     void operator()(const BasicJsonType& j, T& val) const\r
854     noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))\r
855     {\r
856         return call(j, val, priority_tag<1> {});\r
857     }\r
858 };\r
859 \r
860 // taken from ranges-v3\r
861 template<typename T>\r
862 struct static_const\r
863 {\r
864     static constexpr T value{};\r
865 };\r
866 \r
867 template<typename T>\r
868 constexpr T static_const<T>::value;\r
869 } // namespace detail\r
870 \r
871 \r
872 /// namespace to hold default `to_json` / `from_json` functions\r
873 namespace\r
874 {\r
875 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;\r
876 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;\r
877 }\r
878 \r
879 \r
880 /*!\r
881 @brief default JSONSerializer template argument\r
882 \r
883 This serializer ignores the template arguments and uses ADL\r
884 ([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl))\r
885 for serialization.\r
886 */\r
887 template<typename = void, typename = void>\r
888 struct adl_serializer\r
889 {\r
890     /*!\r
891     @brief convert a JSON value to any value type\r
892 \r
893     This function is usually called by the `get()` function of the\r
894     @ref basic_json class (either explicit or via conversion operators).\r
895 \r
896     @param[in] j         JSON value to read from\r
897     @param[in,out] val  value to write to\r
898     */\r
899     template<typename BasicJsonType, typename ValueType>\r
900     static void from_json(BasicJsonType&& j, ValueType& val) noexcept(\r
901         noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))\r
902     {\r
903         ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);\r
904     }\r
905 \r
906     /*!\r
907     @brief convert any value type to a JSON value\r
908 \r
909     This function is usually called by the constructors of the @ref basic_json\r
910     class.\r
911 \r
912     @param[in,out] j  JSON value to write to\r
913     @param[in] val     value to read from\r
914     */\r
915     template<typename BasicJsonType, typename ValueType>\r
916     static void to_json(BasicJsonType& j, ValueType&& val) noexcept(\r
917         noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))\r
918     {\r
919         ::nlohmann::to_json(j, std::forward<ValueType>(val));\r
920     }\r
921 };\r
922 \r
923 \r
924 /*!\r
925 @brief a class to store JSON values\r
926 \r
927 @tparam ObjectType type for JSON objects (`std::map` by default; will be used\r
928 in @ref object_t)\r
929 @tparam ArrayType type for JSON arrays (`std::vector` by default; will be used\r
930 in @ref array_t)\r
931 @tparam StringType type for JSON strings and object keys (`std::string` by\r
932 default; will be used in @ref string_t)\r
933 @tparam BooleanType type for JSON booleans (`bool` by default; will be used\r
934 in @ref boolean_t)\r
935 @tparam NumberIntegerType type for JSON integer numbers (`int64_t` by\r
936 default; will be used in @ref number_integer_t)\r
937 @tparam NumberUnsignedType type for JSON unsigned integer numbers (@c\r
938 `uint64_t` by default; will be used in @ref number_unsigned_t)\r
939 @tparam NumberFloatType type for JSON floating-point numbers (`double` by\r
940 default; will be used in @ref number_float_t)\r
941 @tparam AllocatorType type of the allocator to use (`std::allocator` by\r
942 default)\r
943 @tparam JSONSerializer the serializer to resolve internal calls to `to_json()`\r
944 and `from_json()` (@ref adl_serializer by default)\r
945 \r
946 @requirement The class satisfies the following concept requirements:\r
947 - Basic\r
948  - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):\r
949    JSON values can be default constructed. The result will be a JSON null\r
950    value.\r
951  - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):\r
952    A JSON value can be constructed from an rvalue argument.\r
953  - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):\r
954    A JSON value can be copy-constructed from an lvalue expression.\r
955  - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):\r
956    A JSON value van be assigned from an rvalue argument.\r
957  - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):\r
958    A JSON value can be copy-assigned from an lvalue expression.\r
959  - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):\r
960    JSON values can be destructed.\r
961 - Layout\r
962  - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):\r
963    JSON values have\r
964    [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):\r
965    All non-static data members are private and standard layout types, the\r
966    class has no virtual functions or (virtual) base classes.\r
967 - Library-wide\r
968  - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):\r
969    JSON values can be compared with `==`, see @ref\r
970    operator==(const_reference,const_reference).\r
971  - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):\r
972    JSON values can be compared with `<`, see @ref\r
973    operator<(const_reference,const_reference).\r
974  - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):\r
975    Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of\r
976    other compatible types, using unqualified function call @ref swap().\r
977  - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):\r
978    JSON values can be compared against `std::nullptr_t` objects which are used\r
979    to model the `null` value.\r
980 - Container\r
981  - [Container](http://en.cppreference.com/w/cpp/concept/Container):\r
982    JSON values can be used like STL containers and provide iterator access.\r
983  - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);\r
984    JSON values can be used like STL containers and provide reverse iterator\r
985    access.\r
986 \r
987 @invariant The member variables @a m_value and @a m_type have the following\r
988 relationship:\r
989 - If `m_type == value_t::object`, then `m_value.object != nullptr`.\r
990 - If `m_type == value_t::array`, then `m_value.array != nullptr`.\r
991 - If `m_type == value_t::string`, then `m_value.string != nullptr`.\r
992 The invariants are checked by member function assert_invariant().\r
993 \r
994 @internal\r
995 @note ObjectType trick from http://stackoverflow.com/a/9860911\r
996 @endinternal\r
997 \r
998 @see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange\r
999 Format](http://rfc7159.net/rfc7159)\r
1000 \r
1001 @since version 1.0.0\r
1002 \r
1003 @nosubgrouping\r
1004 */\r
1005 template <\r
1006     template<typename U, typename V, typename... Args> class ObjectType = std::map,\r
1007     template<typename U, typename... Args> class ArrayType = std::vector,\r
1008     class StringType = std::string,\r
1009     class BooleanType = bool,\r
1010     class NumberIntegerType = std::int64_t,\r
1011     class NumberUnsignedType = std::uint64_t,\r
1012     class NumberFloatType = double,\r
1013     template<typename U> class AllocatorType = std::allocator,\r
1014     template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer\r
1015     >\r
1016 class basic_json\r
1017 {\r
1018   private:\r
1019     template<detail::value_t> friend struct detail::external_constructor;\r
1020     /// workaround type for MSVC\r
1021     using basic_json_t = basic_json<ObjectType, ArrayType, StringType,\r
1022           BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,\r
1023           AllocatorType, JSONSerializer>;\r
1024 \r
1025   public:\r
1026     using value_t = detail::value_t;\r
1027     // forward declarations\r
1028     template<typename U> class iter_impl;\r
1029     template<typename Base> class json_reverse_iterator;\r
1030     class json_pointer;\r
1031     template<typename T, typename SFINAE>\r
1032     using json_serializer = JSONSerializer<T, SFINAE>;\r
1033 \r
1034     /////////////////////\r
1035     // container types //\r
1036     /////////////////////\r
1037 \r
1038     /// @name container types\r
1039     /// The canonic container types to use @ref basic_json like any other STL\r
1040     /// container.\r
1041     /// @{\r
1042 \r
1043     /// the type of elements in a basic_json container\r
1044     using value_type = basic_json;\r
1045 \r
1046     /// the type of an element reference\r
1047     using reference = value_type&;\r
1048     /// the type of an element const reference\r
1049     using const_reference = const value_type&;\r
1050 \r
1051     /// a type to represent differences between iterators\r
1052     using difference_type = std::ptrdiff_t;\r
1053     /// a type to represent container sizes\r
1054     using size_type = std::size_t;\r
1055 \r
1056     /// the allocator type\r
1057     using allocator_type = AllocatorType<basic_json>;\r
1058 \r
1059     /// the type of an element pointer\r
1060     using pointer = typename std::allocator_traits<allocator_type>::pointer;\r
1061     /// the type of an element const pointer\r
1062     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;\r
1063 \r
1064     /// an iterator for a basic_json container\r
1065     using iterator = iter_impl<basic_json>;\r
1066     /// a const iterator for a basic_json container\r
1067     using const_iterator = iter_impl<const basic_json>;\r
1068     /// a reverse iterator for a basic_json container\r
1069     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;\r
1070     /// a const reverse iterator for a basic_json container\r
1071     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;\r
1072 \r
1073     /// @}\r
1074 \r
1075 \r
1076     /*!\r
1077     @brief returns the allocator associated with the container\r
1078     */\r
1079     static allocator_type get_allocator()\r
1080     {\r
1081         return allocator_type();\r
1082     }\r
1083 \r
1084     /*!\r
1085     @brief returns version information on the library\r
1086 \r
1087     This function returns a JSON object with information about the library,\r
1088     including the version number and information on the platform and compiler.\r
1089 \r
1090     @return JSON object holding version information\r
1091     key         | description\r
1092     ----------- | ---------------\r
1093     `compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).\r
1094     `copyright` | The copyright line for the library as string.\r
1095     `name`      | The name of the library as string.\r
1096     `platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.\r
1097     `url`       | The URL of the project as string.\r
1098     `version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).\r
1099 \r
1100     @liveexample{The following code shows an example output of the `meta()`\r
1101     function.,meta}\r
1102 \r
1103     @complexity Constant.\r
1104 \r
1105     @since 2.1.0\r
1106     */\r
1107     static basic_json meta()\r
1108     {\r
1109         basic_json result;\r
1110 \r
1111         result["copyright"] = "(C) 2013-2017 Niels Lohmann";\r
1112         result["name"] = "JSON for Modern C++";\r
1113         result["url"] = "https://github.com/nlohmann/json";\r
1114         result["version"] =\r
1115         {\r
1116             {"string", "2.1.1"},\r
1117             {"major", 2},\r
1118             {"minor", 1},\r
1119             {"patch", 1}\r
1120         };\r
1121 \r
1122 #ifdef _WIN32\r
1123         result["platform"] = "win32";\r
1124 #elif defined __linux__\r
1125         result["platform"] = "linux";\r
1126 #elif defined __APPLE__\r
1127         result["platform"] = "apple";\r
1128 #elif defined __unix__\r
1129         result["platform"] = "unix";\r
1130 #else\r
1131         result["platform"] = "unknown";\r
1132 #endif\r
1133 \r
1134 #if defined(__clang__)\r
1135         result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};\r
1136 #elif defined(__ICC) || defined(__INTEL_COMPILER)\r
1137         result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};\r
1138 #elif defined(__GNUC__) || defined(__GNUG__)\r
1139         result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};\r
1140 #elif defined(__HP_cc) || defined(__HP_aCC)\r
1141         result["compiler"] = "hp"\r
1142 #elif defined(__IBMCPP__)\r
1143         result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};\r
1144 #elif defined(_MSC_VER)\r
1145         result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};\r
1146 #elif defined(__PGI)\r
1147         result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};\r
1148 #elif defined(__SUNPRO_CC)\r
1149         result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};\r
1150 #else\r
1151         result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};\r
1152 #endif\r
1153 \r
1154 #ifdef __cplusplus\r
1155         result["compiler"]["c++"] = std::to_string(__cplusplus);\r
1156 #else\r
1157         result["compiler"]["c++"] = "unknown";\r
1158 #endif\r
1159         return result;\r
1160     }\r
1161 \r
1162 \r
1163     ///////////////////////////\r
1164     // JSON value data types //\r
1165     ///////////////////////////\r
1166 \r
1167     /// @name JSON value data types\r
1168     /// The data types to store a JSON value. These types are derived from\r
1169     /// the template arguments passed to class @ref basic_json.\r
1170     /// @{\r
1171 \r
1172     /*!\r
1173     @brief a type for an object\r
1174 \r
1175     [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:\r
1176     > An object is an unordered collection of zero or more name/value pairs,\r
1177     > where a name is a string and a value is a string, number, boolean, null,\r
1178     > object, or array.\r
1179 \r
1180     To store objects in C++, a type is defined by the template parameters\r
1181     described below.\r
1182 \r
1183     @tparam ObjectType  the container to store objects (e.g., `std::map` or\r
1184     `std::unordered_map`)\r
1185     @tparam StringType the type of the keys or names (e.g., `std::string`).\r
1186     The comparison function `std::less<StringType>` is used to order elements\r
1187     inside the container.\r
1188     @tparam AllocatorType the allocator to use for objects (e.g.,\r
1189     `std::allocator`)\r
1190 \r
1191     #### Default type\r
1192 \r
1193     With the default values for @a ObjectType (`std::map`), @a StringType\r
1194     (`std::string`), and @a AllocatorType (`std::allocator`), the default\r
1195     value for @a object_t is:\r
1196 \r
1197     @code {.cpp}\r
1198     std::map<\r
1199       std::string, // key_type\r
1200       basic_json, // value_type\r
1201       std::less<std::string>, // key_compare\r
1202       std::allocator<std::pair<const std::string, basic_json>> // allocator_type\r
1203     >\r
1204     @endcode\r
1205 \r
1206     #### Behavior\r
1207 \r
1208     The choice of @a object_t influences the behavior of the JSON class. With\r
1209     the default type, objects have the following behavior:\r
1210 \r
1211     - When all names are unique, objects will be interoperable in the sense\r
1212       that all software implementations receiving that object will agree on\r
1213       the name-value mappings.\r
1214     - When the names within an object are not unique, later stored name/value\r
1215       pairs overwrite previously stored name/value pairs, leaving the used\r
1216       names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will\r
1217       be treated as equal and both stored as `{"key": 1}`.\r
1218     - Internally, name/value pairs are stored in lexicographical order of the\r
1219       names. Objects will also be serialized (see @ref dump) in this order.\r
1220       For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored\r
1221       and serialized as `{"a": 2, "b": 1}`.\r
1222     - When comparing objects, the order of the name/value pairs is irrelevant.\r
1223       This makes objects interoperable in the sense that they will not be\r
1224       affected by these differences. For instance, `{"b": 1, "a": 2}` and\r
1225       `{"a": 2, "b": 1}` will be treated as equal.\r
1226 \r
1227     #### Limits\r
1228 \r
1229     [RFC 7159](http://rfc7159.net/rfc7159) specifies:\r
1230     > An implementation may set limits on the maximum depth of nesting.\r
1231 \r
1232     In this class, the object's limit of nesting is not constraint explicitly.\r
1233     However, a maximum depth of nesting may be introduced by the compiler or\r
1234     runtime environment. A theoretical limit can be queried by calling the\r
1235     @ref max_size function of a JSON object.\r
1236 \r
1237     #### Storage\r
1238 \r
1239     Objects are stored as pointers in a @ref basic_json type. That is, for any\r
1240     access to object values, a pointer of type `object_t*` must be\r
1241     dereferenced.\r
1242 \r
1243     @sa @ref array_t -- type for an array value\r
1244 \r
1245     @since version 1.0.0\r
1246 \r
1247     @note The order name/value pairs are added to the object is *not*\r
1248     preserved by the library. Therefore, iterating an object may return\r
1249     name/value pairs in a different order than they were originally stored. In\r
1250     fact, keys will be traversed in alphabetical order as `std::map` with\r
1251     `std::less` is used by default. Please note this behavior conforms to [RFC\r
1252     7159](http://rfc7159.net/rfc7159), because any order implements the\r
1253     specified "unordered" nature of JSON objects.\r
1254     */\r
1255     using object_t = ObjectType<StringType,\r
1256           basic_json,\r
1257           std::less<StringType>,\r
1258           AllocatorType<std::pair<const StringType,\r
1259           basic_json>>>;\r
1260 \r
1261     /*!\r
1262     @brief a type for an array\r
1263 \r
1264     [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:\r
1265     > An array is an ordered sequence of zero or more values.\r
1266 \r
1267     To store objects in C++, a type is defined by the template parameters\r
1268     explained below.\r
1269 \r
1270     @tparam ArrayType  container type to store arrays (e.g., `std::vector` or\r
1271     `std::list`)\r
1272     @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)\r
1273 \r
1274     #### Default type\r
1275 \r
1276     With the default values for @a ArrayType (`std::vector`) and @a\r
1277     AllocatorType (`std::allocator`), the default value for @a array_t is:\r
1278 \r
1279     @code {.cpp}\r
1280     std::vector<\r
1281       basic_json, // value_type\r
1282       std::allocator<basic_json> // allocator_type\r
1283     >\r
1284     @endcode\r
1285 \r
1286     #### Limits\r
1287 \r
1288     [RFC 7159](http://rfc7159.net/rfc7159) specifies:\r
1289     > An implementation may set limits on the maximum depth of nesting.\r
1290 \r
1291     In this class, the array's limit of nesting is not constraint explicitly.\r
1292     However, a maximum depth of nesting may be introduced by the compiler or\r
1293     runtime environment. A theoretical limit can be queried by calling the\r
1294     @ref max_size function of a JSON array.\r
1295 \r
1296     #### Storage\r
1297 \r
1298     Arrays are stored as pointers in a @ref basic_json type. That is, for any\r
1299     access to array values, a pointer of type `array_t*` must be dereferenced.\r
1300 \r
1301     @sa @ref object_t -- type for an object value\r
1302 \r
1303     @since version 1.0.0\r
1304     */\r
1305     using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;\r
1306 \r
1307     /*!\r
1308     @brief a type for a string\r
1309 \r
1310     [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:\r
1311     > A string is a sequence of zero or more Unicode characters.\r
1312 \r
1313     To store objects in C++, a type is defined by the template parameter\r
1314     described below. Unicode values are split by the JSON class into\r
1315     byte-sized characters during deserialization.\r
1316 \r
1317     @tparam StringType  the container to store strings (e.g., `std::string`).\r
1318     Note this container is used for keys/names in objects, see @ref object_t.\r
1319 \r
1320     #### Default type\r
1321 \r
1322     With the default values for @a StringType (`std::string`), the default\r
1323     value for @a string_t is:\r
1324 \r
1325     @code {.cpp}\r
1326     std::string\r
1327     @endcode\r
1328 \r
1329     #### Encoding\r
1330 \r
1331     Strings are stored in UTF-8 encoding. Therefore, functions like\r
1332     `std::string::size()` or `std::string::length()` return the number of\r
1333     bytes in the string rather than the number of characters or glyphs.\r
1334 \r
1335     #### String comparison\r
1336 \r
1337     [RFC 7159](http://rfc7159.net/rfc7159) states:\r
1338     > Software implementations are typically required to test names of object\r
1339     > members for equality. Implementations that transform the textual\r
1340     > representation into sequences of Unicode code units and then perform the\r
1341     > comparison numerically, code unit by code unit, are interoperable in the\r
1342     > sense that implementations will agree in all cases on equality or\r
1343     > inequality of two strings. For example, implementations that compare\r
1344     > strings with escaped characters unconverted may incorrectly find that\r
1345     > `"a\\b"` and `"a\u005Cb"` are not equal.\r
1346 \r
1347     This implementation is interoperable as it does compare strings code unit\r
1348     by code unit.\r
1349 \r
1350     #### Storage\r
1351 \r
1352     String values are stored as pointers in a @ref basic_json type. That is,\r
1353     for any access to string values, a pointer of type `string_t*` must be\r
1354     dereferenced.\r
1355 \r
1356     @since version 1.0.0\r
1357     */\r
1358     using string_t = StringType;\r
1359 \r
1360     /*!\r
1361     @brief a type for a boolean\r
1362 \r
1363     [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a\r
1364     type which differentiates the two literals `true` and `false`.\r
1365 \r
1366     To store objects in C++, a type is defined by the template parameter @a\r
1367     BooleanType which chooses the type to use.\r
1368 \r
1369     #### Default type\r
1370 \r
1371     With the default values for @a BooleanType (`bool`), the default value for\r
1372     @a boolean_t is:\r
1373 \r
1374     @code {.cpp}\r
1375     bool\r
1376     @endcode\r
1377 \r
1378     #### Storage\r
1379 \r
1380     Boolean values are stored directly inside a @ref basic_json type.\r
1381 \r
1382     @since version 1.0.0\r
1383     */\r
1384     using boolean_t = BooleanType;\r
1385 \r
1386     /*!\r
1387     @brief a type for a number (integer)\r
1388 \r
1389     [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\r
1390     > The representation of numbers is similar to that used in most\r
1391     > programming languages. A number is represented in base 10 using decimal\r
1392     > digits. It contains an integer component that may be prefixed with an\r
1393     > optional minus sign, which may be followed by a fraction part and/or an\r
1394     > exponent part. Leading zeros are not allowed. (...) Numeric values that\r
1395     > cannot be represented in the grammar below (such as Infinity and NaN)\r
1396     > are not permitted.\r
1397 \r
1398     This description includes both integer and floating-point numbers.\r
1399     However, C++ allows more precise storage if it is known whether the number\r
1400     is a signed integer, an unsigned integer or a floating-point number.\r
1401     Therefore, three different types, @ref number_integer_t, @ref\r
1402     number_unsigned_t and @ref number_float_t are used.\r
1403 \r
1404     To store integer numbers in C++, a type is defined by the template\r
1405     parameter @a NumberIntegerType which chooses the type to use.\r
1406 \r
1407     #### Default type\r
1408 \r
1409     With the default values for @a NumberIntegerType (`int64_t`), the default\r
1410     value for @a number_integer_t is:\r
1411 \r
1412     @code {.cpp}\r
1413     int64_t\r
1414     @endcode\r
1415 \r
1416     #### Default behavior\r
1417 \r
1418     - The restrictions about leading zeros is not enforced in C++. Instead,\r
1419       leading zeros in integer literals lead to an interpretation as octal\r
1420       number. Internally, the value will be stored as decimal number. For\r
1421       instance, the C++ integer literal `010` will be serialized to `8`.\r
1422       During deserialization, leading zeros yield an error.\r
1423     - Not-a-number (NaN) values will be serialized to `null`.\r
1424 \r
1425     #### Limits\r
1426 \r
1427     [RFC 7159](http://rfc7159.net/rfc7159) specifies:\r
1428     > An implementation may set limits on the range and precision of numbers.\r
1429 \r
1430     When the default type is used, the maximal integer number that can be\r
1431     stored is `9223372036854775807` (INT64_MAX) and the minimal integer number\r
1432     that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers\r
1433     that are out of range will yield over/underflow when used in a\r
1434     constructor. During deserialization, too large or small integer numbers\r
1435     will be automatically be stored as @ref number_unsigned_t or @ref\r
1436     number_float_t.\r
1437 \r
1438     [RFC 7159](http://rfc7159.net/rfc7159) further states:\r
1439     > Note that when such software is used, numbers that are integers and are\r
1440     > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense\r
1441     > that implementations will agree exactly on their numeric values.\r
1442 \r
1443     As this range is a subrange of the exactly supported range [INT64_MIN,\r
1444     INT64_MAX], this class's integer type is interoperable.\r
1445 \r
1446     #### Storage\r
1447 \r
1448     Integer number values are stored directly inside a @ref basic_json type.\r
1449 \r
1450     @sa @ref number_float_t -- type for number values (floating-point)\r
1451 \r
1452     @sa @ref number_unsigned_t -- type for number values (unsigned integer)\r
1453 \r
1454     @since version 1.0.0\r
1455     */\r
1456     using number_integer_t = NumberIntegerType;\r
1457 \r
1458     /*!\r
1459     @brief a type for a number (unsigned)\r
1460 \r
1461     [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\r
1462     > The representation of numbers is similar to that used in most\r
1463     > programming languages. A number is represented in base 10 using decimal\r
1464     > digits. It contains an integer component that may be prefixed with an\r
1465     > optional minus sign, which may be followed by a fraction part and/or an\r
1466     > exponent part. Leading zeros are not allowed. (...) Numeric values that\r
1467     > cannot be represented in the grammar below (such as Infinity and NaN)\r
1468     > are not permitted.\r
1469 \r
1470     This description includes both integer and floating-point numbers.\r
1471     However, C++ allows more precise storage if it is known whether the number\r
1472     is a signed integer, an unsigned integer or a floating-point number.\r
1473     Therefore, three different types, @ref number_integer_t, @ref\r
1474     number_unsigned_t and @ref number_float_t are used.\r
1475 \r
1476     To store unsigned integer numbers in C++, a type is defined by the\r
1477     template parameter @a NumberUnsignedType which chooses the type to use.\r
1478 \r
1479     #### Default type\r
1480 \r
1481     With the default values for @a NumberUnsignedType (`uint64_t`), the\r
1482     default value for @a number_unsigned_t is:\r
1483 \r
1484     @code {.cpp}\r
1485     uint64_t\r
1486     @endcode\r
1487 \r
1488     #### Default behavior\r
1489 \r
1490     - The restrictions about leading zeros is not enforced in C++. Instead,\r
1491       leading zeros in integer literals lead to an interpretation as octal\r
1492       number. Internally, the value will be stored as decimal number. For\r
1493       instance, the C++ integer literal `010` will be serialized to `8`.\r
1494       During deserialization, leading zeros yield an error.\r
1495     - Not-a-number (NaN) values will be serialized to `null`.\r
1496 \r
1497     #### Limits\r
1498 \r
1499     [RFC 7159](http://rfc7159.net/rfc7159) specifies:\r
1500     > An implementation may set limits on the range and precision of numbers.\r
1501 \r
1502     When the default type is used, the maximal integer number that can be\r
1503     stored is `18446744073709551615` (UINT64_MAX) and the minimal integer\r
1504     number that can be stored is `0`. Integer numbers that are out of range\r
1505     will yield over/underflow when used in a constructor. During\r
1506     deserialization, too large or small integer numbers will be automatically\r
1507     be stored as @ref number_integer_t or @ref number_float_t.\r
1508 \r
1509     [RFC 7159](http://rfc7159.net/rfc7159) further states:\r
1510     > Note that when such software is used, numbers that are integers and are\r
1511     > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense\r
1512     > that implementations will agree exactly on their numeric values.\r
1513 \r
1514     As this range is a subrange (when considered in conjunction with the\r
1515     number_integer_t type) of the exactly supported range [0, UINT64_MAX],\r
1516     this class's integer type is interoperable.\r
1517 \r
1518     #### Storage\r
1519 \r
1520     Integer number values are stored directly inside a @ref basic_json type.\r
1521 \r
1522     @sa @ref number_float_t -- type for number values (floating-point)\r
1523     @sa @ref number_integer_t -- type for number values (integer)\r
1524 \r
1525     @since version 2.0.0\r
1526     */\r
1527     using number_unsigned_t = NumberUnsignedType;\r
1528 \r
1529     /*!\r
1530     @brief a type for a number (floating-point)\r
1531 \r
1532     [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\r
1533     > The representation of numbers is similar to that used in most\r
1534     > programming languages. A number is represented in base 10 using decimal\r
1535     > digits. It contains an integer component that may be prefixed with an\r
1536     > optional minus sign, which may be followed by a fraction part and/or an\r
1537     > exponent part. Leading zeros are not allowed. (...) Numeric values that\r
1538     > cannot be represented in the grammar below (such as Infinity and NaN)\r
1539     > are not permitted.\r
1540 \r
1541     This description includes both integer and floating-point numbers.\r
1542     However, C++ allows more precise storage if it is known whether the number\r
1543     is a signed integer, an unsigned integer or a floating-point number.\r
1544     Therefore, three different types, @ref number_integer_t, @ref\r
1545     number_unsigned_t and @ref number_float_t are used.\r
1546 \r
1547     To store floating-point numbers in C++, a type is defined by the template\r
1548     parameter @a NumberFloatType which chooses the type to use.\r
1549 \r
1550     #### Default type\r
1551 \r
1552     With the default values for @a NumberFloatType (`double`), the default\r
1553     value for @a number_float_t is:\r
1554 \r
1555     @code {.cpp}\r
1556     double\r
1557     @endcode\r
1558 \r
1559     #### Default behavior\r
1560 \r
1561     - The restrictions about leading zeros is not enforced in C++. Instead,\r
1562       leading zeros in floating-point literals will be ignored. Internally,\r
1563       the value will be stored as decimal number. For instance, the C++\r
1564       floating-point literal `01.2` will be serialized to `1.2`. During\r
1565       deserialization, leading zeros yield an error.\r
1566     - Not-a-number (NaN) values will be serialized to `null`.\r
1567 \r
1568     #### Limits\r
1569 \r
1570     [RFC 7159](http://rfc7159.net/rfc7159) states:\r
1571     > This specification allows implementations to set limits on the range and\r
1572     > precision of numbers accepted. Since software that implements IEEE\r
1573     > 754-2008 binary64 (double precision) numbers is generally available and\r
1574     > widely used, good interoperability can be achieved by implementations\r
1575     > that expect no more precision or range than these provide, in the sense\r
1576     > that implementations will approximate JSON numbers within the expected\r
1577     > precision.\r
1578 \r
1579     This implementation does exactly follow this approach, as it uses double\r
1580     precision floating-point numbers. Note values smaller than\r
1581     `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`\r
1582     will be stored as NaN internally and be serialized to `null`.\r
1583 \r
1584     #### Storage\r
1585 \r
1586     Floating-point number values are stored directly inside a @ref basic_json\r
1587     type.\r
1588 \r
1589     @sa @ref number_integer_t -- type for number values (integer)\r
1590 \r
1591     @sa @ref number_unsigned_t -- type for number values (unsigned integer)\r
1592 \r
1593     @since version 1.0.0\r
1594     */\r
1595     using number_float_t = NumberFloatType;\r
1596 \r
1597     /// @}\r
1598 \r
1599   private:\r
1600 \r
1601     /// helper for exception-safe object creation\r
1602     template<typename T, typename... Args>\r
1603     static T* create(Args&& ... args)\r
1604     {\r
1605         AllocatorType<T> alloc;\r
1606         auto deleter = [&](T * object)\r
1607         {\r
1608             alloc.deallocate(object, 1);\r
1609         };\r
1610         std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);\r
1611         alloc.construct(object.get(), std::forward<Args>(args)...);\r
1612         assert(object != nullptr);\r
1613         return object.release();\r
1614     }\r
1615 \r
1616     ////////////////////////\r
1617     // JSON value storage //\r
1618     ////////////////////////\r
1619 \r
1620     /*!\r
1621     @brief a JSON value\r
1622 \r
1623     The actual storage for a JSON value of the @ref basic_json class. This\r
1624     union combines the different storage types for the JSON value types\r
1625     defined in @ref value_t.\r
1626 \r
1627     JSON type | value_t type    | used type\r
1628     --------- | --------------- | ------------------------\r
1629     object    | object          | pointer to @ref object_t\r
1630     array     | array           | pointer to @ref array_t\r
1631     string    | string          | pointer to @ref string_t\r
1632     boolean   | boolean         | @ref boolean_t\r
1633     number    | number_integer  | @ref number_integer_t\r
1634     number    | number_unsigned | @ref number_unsigned_t\r
1635     number    | number_float    | @ref number_float_t\r
1636     null      | null            | *no value is stored*\r
1637 \r
1638     @note Variable-length types (objects, arrays, and strings) are stored as\r
1639     pointers. The size of the union should not exceed 64 bits if the default\r
1640     value types are used.\r
1641 \r
1642     @since version 1.0.0\r
1643     */\r
1644     union json_value\r
1645     {\r
1646         /// object (stored with pointer to save storage)\r
1647         object_t* object;\r
1648         /// array (stored with pointer to save storage)\r
1649         array_t* array;\r
1650         /// string (stored with pointer to save storage)\r
1651         string_t* string;\r
1652         /// boolean\r
1653         boolean_t boolean;\r
1654         /// number (integer)\r
1655         number_integer_t number_integer;\r
1656         /// number (unsigned integer)\r
1657         number_unsigned_t number_unsigned;\r
1658         /// number (floating-point)\r
1659         number_float_t number_float;\r
1660 \r
1661         /// default constructor (for null values)\r
1662         json_value() = default;\r
1663         /// constructor for booleans\r
1664         json_value(boolean_t v) noexcept : boolean(v) {}\r
1665         /// constructor for numbers (integer)\r
1666         json_value(number_integer_t v) noexcept : number_integer(v) {}\r
1667         /// constructor for numbers (unsigned)\r
1668         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}\r
1669         /// constructor for numbers (floating-point)\r
1670         json_value(number_float_t v) noexcept : number_float(v) {}\r
1671         /// constructor for empty values of a given type\r
1672         json_value(value_t t)\r
1673         {\r
1674             switch (t)\r
1675             {\r
1676                 case value_t::object:\r
1677                 {\r
1678                     object = create<object_t>();\r
1679                     break;\r
1680                 }\r
1681 \r
1682                 case value_t::array:\r
1683                 {\r
1684                     array = create<array_t>();\r
1685                     break;\r
1686                 }\r
1687 \r
1688                 case value_t::string:\r
1689                 {\r
1690                     string = create<string_t>("");\r
1691                     break;\r
1692                 }\r
1693 \r
1694                 case value_t::boolean:\r
1695                 {\r
1696                     boolean = boolean_t(false);\r
1697                     break;\r
1698                 }\r
1699 \r
1700                 case value_t::number_integer:\r
1701                 {\r
1702                     number_integer = number_integer_t(0);\r
1703                     break;\r
1704                 }\r
1705 \r
1706                 case value_t::number_unsigned:\r
1707                 {\r
1708                     number_unsigned = number_unsigned_t(0);\r
1709                     break;\r
1710                 }\r
1711 \r
1712                 case value_t::number_float:\r
1713                 {\r
1714                     number_float = number_float_t(0.0);\r
1715                     break;\r
1716                 }\r
1717 \r
1718                 case value_t::null:\r
1719                 {\r
1720                     break;\r
1721                 }\r
1722 \r
1723                 default:\r
1724                 {\r
1725                     if (t == value_t::null)\r
1726                     {\r
1727                         JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE\r
1728                     }\r
1729                     break;\r
1730                 }\r
1731             }\r
1732         }\r
1733 \r
1734         /// constructor for strings\r
1735         json_value(const string_t& value)\r
1736         {\r
1737             string = create<string_t>(value);\r
1738         }\r
1739 \r
1740         /// constructor for objects\r
1741         json_value(const object_t& value)\r
1742         {\r
1743             object = create<object_t>(value);\r
1744         }\r
1745 \r
1746         /// constructor for arrays\r
1747         json_value(const array_t& value)\r
1748         {\r
1749             array = create<array_t>(value);\r
1750         }\r
1751     };\r
1752 \r
1753     /*!\r
1754     @brief checks the class invariants\r
1755 \r
1756     This function asserts the class invariants. It needs to be called at the\r
1757     end of every constructor to make sure that created objects respect the\r
1758     invariant. Furthermore, it has to be called each time the type of a JSON\r
1759     value is changed, because the invariant expresses a relationship between\r
1760     @a m_type and @a m_value.\r
1761     */\r
1762     void assert_invariant() const\r
1763     {\r
1764         assert(m_type != value_t::object or m_value.object != nullptr);\r
1765         assert(m_type != value_t::array or m_value.array != nullptr);\r
1766         assert(m_type != value_t::string or m_value.string != nullptr);\r
1767     }\r
1768 \r
1769   public:\r
1770     //////////////////////////\r
1771     // JSON parser callback //\r
1772     //////////////////////////\r
1773 \r
1774     /*!\r
1775     @brief JSON callback events\r
1776 \r
1777     This enumeration lists the parser events that can trigger calling a\r
1778     callback function of type @ref parser_callback_t during parsing.\r
1779 \r
1780     @image html callback_events.png "Example when certain parse events are triggered"\r
1781 \r
1782     @since version 1.0.0\r
1783     */\r
1784     enum class parse_event_t : uint8_t\r
1785     {\r
1786         /// the parser read `{` and started to process a JSON object\r
1787         object_start,\r
1788         /// the parser read `}` and finished processing a JSON object\r
1789         object_end,\r
1790         /// the parser read `[` and started to process a JSON array\r
1791         array_start,\r
1792         /// the parser read `]` and finished processing a JSON array\r
1793         array_end,\r
1794         /// the parser read a key of a value in an object\r
1795         key,\r
1796         /// the parser finished reading a JSON value\r
1797         value\r
1798     };\r
1799 \r
1800     /*!\r
1801     @brief per-element parser callback type\r
1802 \r
1803     With a parser callback function, the result of parsing a JSON text can be\r
1804     influenced. When passed to @ref parse(std::istream&, const\r
1805     parser_callback_t) or @ref parse(const CharT, const parser_callback_t),\r
1806     it is called on certain events (passed as @ref parse_event_t via parameter\r
1807     @a event) with a set recursion depth @a depth and context JSON value\r
1808     @a parsed. The return value of the callback function is a boolean\r
1809     indicating whether the element that emitted the callback shall be kept or\r
1810     not.\r
1811 \r
1812     We distinguish six scenarios (determined by the event type) in which the\r
1813     callback function can be called. The following table describes the values\r
1814     of the parameters @a depth, @a event, and @a parsed.\r
1815 \r
1816     parameter @a event | description | parameter @a depth | parameter @a parsed\r
1817     ------------------ | ----------- | ------------------ | -------------------\r
1818     parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded\r
1819     parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key\r
1820     parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object\r
1821     parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded\r
1822     parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array\r
1823     parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value\r
1824 \r
1825     @image html callback_events.png "Example when certain parse events are triggered"\r
1826 \r
1827     Discarding a value (i.e., returning `false`) has different effects\r
1828     depending on the context in which function was called:\r
1829 \r
1830     - Discarded values in structured types are skipped. That is, the parser\r
1831       will behave as if the discarded value was never read.\r
1832     - In case a value outside a structured type is skipped, it is replaced\r
1833       with `null`. This case happens if the top-level element is skipped.\r
1834 \r
1835     @param[in] depth  the depth of the recursion during parsing\r
1836 \r
1837     @param[in] event  an event of type parse_event_t indicating the context in\r
1838     the callback function has been called\r
1839 \r
1840     @param[in,out] parsed  the current intermediate parse result; note that\r
1841     writing to this value has no effect for parse_event_t::key events\r
1842 \r
1843     @return Whether the JSON value which called the function during parsing\r
1844     should be kept (`true`) or not (`false`). In the latter case, it is either\r
1845     skipped completely or replaced by an empty discarded object.\r
1846 \r
1847     @sa @ref parse(std::istream&, parser_callback_t) or\r
1848     @ref parse(const CharT, const parser_callback_t) for examples\r
1849 \r
1850     @since version 1.0.0\r
1851     */\r
1852     using parser_callback_t = std::function<bool(int depth,\r
1853                               parse_event_t event,\r
1854                               basic_json& parsed)>;\r
1855 \r
1856 \r
1857     //////////////////\r
1858     // constructors //\r
1859     //////////////////\r
1860 \r
1861     /// @name constructors and destructors\r
1862     /// Constructors of class @ref basic_json, copy/move constructor, copy\r
1863     /// assignment, static functions creating objects, and the destructor.\r
1864     /// @{\r
1865 \r
1866     /*!\r
1867     @brief create an empty value with a given type\r
1868 \r
1869     Create an empty JSON value with a given type. The value will be default\r
1870     initialized with an empty value which depends on the type:\r
1871 \r
1872     Value type  | initial value\r
1873     ----------- | -------------\r
1874     null        | `null`\r
1875     boolean     | `false`\r
1876     string      | `""`\r
1877     number      | `0`\r
1878     object      | `{}`\r
1879     array       | `[]`\r
1880 \r
1881     @param[in] value_type  the type of the value to create\r
1882 \r
1883     @complexity Constant.\r
1884 \r
1885     @throw std::bad_alloc if allocation for object, array, or string value\r
1886     fails\r
1887 \r
1888     @liveexample{The following code shows the constructor for different @ref\r
1889     value_t values,basic_json__value_t}\r
1890 \r
1891     @since version 1.0.0\r
1892     */\r
1893     basic_json(const value_t value_type)\r
1894         : m_type(value_type), m_value(value_type)\r
1895     {\r
1896         assert_invariant();\r
1897     }\r
1898 \r
1899     /*!\r
1900     @brief create a null object\r
1901 \r
1902     Create a `null` JSON value. It either takes a null pointer as parameter\r
1903     (explicitly creating `null`) or no parameter (implicitly creating `null`).\r
1904     The passed null pointer itself is not read -- it is only used to choose\r
1905     the right constructor.\r
1906 \r
1907     @complexity Constant.\r
1908 \r
1909     @exceptionsafety No-throw guarantee: this constructor never throws\r
1910     exceptions.\r
1911 \r
1912     @liveexample{The following code shows the constructor with and without a\r
1913     null pointer parameter.,basic_json__nullptr_t}\r
1914 \r
1915     @since version 1.0.0\r
1916     */\r
1917     basic_json(std::nullptr_t = nullptr) noexcept\r
1918         : basic_json(value_t::null)\r
1919     {\r
1920         assert_invariant();\r
1921     }\r
1922 \r
1923     /*!\r
1924     @brief create a JSON value\r
1925 \r
1926     This is a "catch all" constructor for all compatible JSON types; that is,\r
1927     types for which a `to_json()` method exsits. The constructor forwards the\r
1928     parameter @a val to that method (to `json_serializer<U>::to_json` method\r
1929     with `U = uncvref_t<CompatibleType>`, to be exact).\r
1930 \r
1931     Template type @a CompatibleType includes, but is not limited to, the\r
1932     following types:\r
1933     - **arrays**: @ref array_t and all kinds of compatible containers such as\r
1934       `std::vector`, `std::deque`, `std::list`, `std::forward_list`,\r
1935       `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and\r
1936       `unordered_multiset` with a `value_type` from which a @ref basic_json\r
1937       value can be constructed.\r
1938     - **objects**: @ref object_t and all kinds of compatible associative\r
1939       containers such as `std::map`, `std::unordered_map`, `std::multimap`,\r
1940       and `std::unordered_multimap` with a `key_type` compatible to\r
1941       @ref string_t and a `value_type` from which a @ref basic_json value can\r
1942       be constructed.\r
1943     - **strings**: @ref string_t, string literals, and all compatible string\r
1944       containers can be used.\r
1945     - **numbers**: @ref number_integer_t, @ref number_unsigned_t,\r
1946       @ref number_float_t, and all convertible number types such as `int`,\r
1947       `size_t`, `int64_t`, `float` or `double` can be used.\r
1948     - **boolean**: @ref boolean_t / `bool` can be used.\r
1949 \r
1950     See the examples below.\r
1951 \r
1952     @tparam CompatibleType a type such that:\r
1953     - @a CompatibleType is not derived from `std::istream`,\r
1954     - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move\r
1955          constructors),\r
1956     - @a CompatibleType is not a @ref basic_json nested type (e.g.,\r
1957          @ref json_pointer, @ref iterator, etc ...)\r
1958     - @ref @ref json_serializer<U> has a\r
1959          `to_json(basic_json_t&, CompatibleType&&)` method\r
1960 \r
1961     @tparam U = `uncvref_t<CompatibleType>`\r
1962 \r
1963     @param[in] val the value to be forwarded\r
1964 \r
1965     @complexity Usually linear in the size of the passed @a val, also\r
1966                 depending on the implementation of the called `to_json()`\r
1967                 method.\r
1968 \r
1969     @throw what `json_serializer<U>::to_json()` throws\r
1970 \r
1971     @liveexample{The following code shows the constructor with several\r
1972     compatible types.,basic_json__CompatibleType}\r
1973 \r
1974     @since version 2.1.0\r
1975     */\r
1976     template<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,\r
1977              detail::enable_if_t<not std::is_base_of<std::istream, U>::value and\r
1978                                  not std::is_same<U, basic_json_t>::value and\r
1979                                  not detail::is_basic_json_nested_type<\r
1980                                      basic_json_t, U>::value and\r
1981                                  detail::has_to_json<basic_json, U>::value,\r
1982                                  int> = 0>\r
1983     basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(\r
1984                 std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))\r
1985     {\r
1986         JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));\r
1987         assert_invariant();\r
1988     }\r
1989 \r
1990     /*!\r
1991     @brief create a container (array or object) from an initializer list\r
1992 \r
1993     Creates a JSON value of type array or object from the passed initializer\r
1994     list @a init. In case @a type_deduction is `true` (default), the type of\r
1995     the JSON value to be created is deducted from the initializer list @a init\r
1996     according to the following rules:\r
1997 \r
1998     1. If the list is empty, an empty JSON object value `{}` is created.\r
1999     2. If the list consists of pairs whose first element is a string, a JSON\r
2000        object value is created where the first elements of the pairs are\r
2001        treated as keys and the second elements are as values.\r
2002     3. In all other cases, an array is created.\r
2003 \r
2004     The rules aim to create the best fit between a C++ initializer list and\r
2005     JSON values. The rationale is as follows:\r
2006 \r
2007     1. The empty initializer list is written as `{}` which is exactly an empty\r
2008        JSON object.\r
2009     2. C++ has now way of describing mapped types other than to list a list of\r
2010        pairs. As JSON requires that keys must be of type string, rule 2 is the\r
2011        weakest constraint one can pose on initializer lists to interpret them\r
2012        as an object.\r
2013     3. In all other cases, the initializer list could not be interpreted as\r
2014        JSON object type, so interpreting it as JSON array type is safe.\r
2015 \r
2016     With the rules described above, the following JSON values cannot be\r
2017     expressed by an initializer list:\r
2018 \r
2019     - the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)\r
2020       with an empty initializer list in this case\r
2021     - arrays whose elements satisfy rule 2: use @ref\r
2022       array(std::initializer_list<basic_json>) with the same initializer list\r
2023       in this case\r
2024 \r
2025     @note When used without parentheses around an empty initializer list, @ref\r
2026     basic_json() is called instead of this function, yielding the JSON null\r
2027     value.\r
2028 \r
2029     @param[in] init  initializer list with JSON values\r
2030 \r
2031     @param[in] type_deduction internal parameter; when set to `true`, the type\r
2032     of the JSON value is deducted from the initializer list @a init; when set\r
2033     to `false`, the type provided via @a manual_type is forced. This mode is\r
2034     used by the functions @ref array(std::initializer_list<basic_json>) and\r
2035     @ref object(std::initializer_list<basic_json>).\r
2036 \r
2037     @param[in] manual_type internal parameter; when @a type_deduction is set\r
2038     to `false`, the created JSON value will use the provided type (only @ref\r
2039     value_t::array and @ref value_t::object are valid); when @a type_deduction\r
2040     is set to `true`, this parameter has no effect\r
2041 \r
2042     @throw std::domain_error if @a type_deduction is `false`, @a manual_type\r
2043     is `value_t::object`, but @a init contains an element which is not a pair\r
2044     whose first element is a string; example: `"cannot create object from\r
2045     initializer list"`\r
2046 \r
2047     @complexity Linear in the size of the initializer list @a init.\r
2048 \r
2049     @liveexample{The example below shows how JSON values are created from\r
2050     initializer lists.,basic_json__list_init_t}\r
2051 \r
2052     @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array\r
2053     value from an initializer list\r
2054     @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object\r
2055     value from an initializer list\r
2056 \r
2057     @since version 1.0.0\r
2058     */\r
2059     basic_json(std::initializer_list<basic_json> init,\r
2060                bool type_deduction = true,\r
2061                value_t manual_type = value_t::array)\r
2062     {\r
2063         // check if each element is an array with two elements whose first\r
2064         // element is a string\r
2065         bool is_an_object = std::all_of(init.begin(), init.end(),\r
2066                                         [](const basic_json & element)\r
2067         {\r
2068             return element.is_array() and element.size() == 2 and element[0].is_string();\r
2069         });\r
2070 \r
2071         // adjust type if type deduction is not wanted\r
2072         if (not type_deduction)\r
2073         {\r
2074             // if array is wanted, do not create an object though possible\r
2075             if (manual_type == value_t::array)\r
2076             {\r
2077                 is_an_object = false;\r
2078             }\r
2079 \r
2080             // if object is wanted but impossible, throw an exception\r
2081             if (manual_type == value_t::object and not is_an_object)\r
2082             {\r
2083                 JSON_THROW(std::domain_error("cannot create object from initializer list"));\r
2084             }\r
2085         }\r
2086 \r
2087         if (is_an_object)\r
2088         {\r
2089             // the initializer list is a list of pairs -> create object\r
2090             m_type = value_t::object;\r
2091             m_value = value_t::object;\r
2092 \r
2093             std::for_each(init.begin(), init.end(), [this](const basic_json & element)\r
2094             {\r
2095                 m_value.object->emplace(*(element[0].m_value.string), element[1]);\r
2096             });\r
2097         }\r
2098         else\r
2099         {\r
2100             // the initializer list describes an array -> create array\r
2101             m_type = value_t::array;\r
2102             m_value.array = create<array_t>(init);\r
2103         }\r
2104 \r
2105         assert_invariant();\r
2106     }\r
2107 \r
2108     /*!\r
2109     @brief explicitly create an array from an initializer list\r
2110 \r
2111     Creates a JSON array value from a given initializer list. That is, given a\r
2112     list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the\r
2113     initializer list is empty, the empty array `[]` is created.\r
2114 \r
2115     @note This function is only needed to express two edge cases that cannot\r
2116     be realized with the initializer list constructor (@ref\r
2117     basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases\r
2118     are:\r
2119     1. creating an array whose elements are all pairs whose first element is a\r
2120     string -- in this case, the initializer list constructor would create an\r
2121     object, taking the first elements as keys\r
2122     2. creating an empty array -- passing the empty initializer list to the\r
2123     initializer list constructor yields an empty object\r
2124 \r
2125     @param[in] init  initializer list with JSON values to create an array from\r
2126     (optional)\r
2127 \r
2128     @return JSON array value\r
2129 \r
2130     @complexity Linear in the size of @a init.\r
2131 \r
2132     @liveexample{The following code shows an example for the `array`\r
2133     function.,array}\r
2134 \r
2135     @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --\r
2136     create a JSON value from an initializer list\r
2137     @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object\r
2138     value from an initializer list\r
2139 \r
2140     @since version 1.0.0\r
2141     */\r
2142     static basic_json array(std::initializer_list<basic_json> init =\r
2143                                 std::initializer_list<basic_json>())\r
2144     {\r
2145         return basic_json(init, false, value_t::array);\r
2146     }\r
2147 \r
2148     /*!\r
2149     @brief explicitly create an object from an initializer list\r
2150 \r
2151     Creates a JSON object value from a given initializer list. The initializer\r
2152     lists elements must be pairs, and their first elements must be strings. If\r
2153     the initializer list is empty, the empty object `{}` is created.\r
2154 \r
2155     @note This function is only added for symmetry reasons. In contrast to the\r
2156     related function @ref array(std::initializer_list<basic_json>), there are\r
2157     no cases which can only be expressed by this function. That is, any\r
2158     initializer list @a init can also be passed to the initializer list\r
2159     constructor @ref basic_json(std::initializer_list<basic_json>, bool,\r
2160     value_t).\r
2161 \r
2162     @param[in] init  initializer list to create an object from (optional)\r
2163 \r
2164     @return JSON object value\r
2165 \r
2166     @throw std::domain_error if @a init is not a pair whose first elements are\r
2167     strings; thrown by\r
2168     @ref basic_json(std::initializer_list<basic_json>, bool, value_t)\r
2169 \r
2170     @complexity Linear in the size of @a init.\r
2171 \r
2172     @liveexample{The following code shows an example for the `object`\r
2173     function.,object}\r
2174 \r
2175     @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --\r
2176     create a JSON value from an initializer list\r
2177     @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array\r
2178     value from an initializer list\r
2179 \r
2180     @since version 1.0.0\r
2181     */\r
2182     static basic_json object(std::initializer_list<basic_json> init =\r
2183                                  std::initializer_list<basic_json>())\r
2184     {\r
2185         return basic_json(init, false, value_t::object);\r
2186     }\r
2187 \r
2188     /*!\r
2189     @brief construct an array with count copies of given value\r
2190 \r
2191     Constructs a JSON array value by creating @a cnt copies of a passed value.\r
2192     In case @a cnt is `0`, an empty array is created. As postcondition,\r
2193     `std::distance(begin(),end()) == cnt` holds.\r
2194 \r
2195     @param[in] cnt  the number of JSON copies of @a val to create\r
2196     @param[in] val  the JSON value to copy\r
2197 \r
2198     @complexity Linear in @a cnt.\r
2199 \r
2200     @liveexample{The following code shows examples for the @ref\r
2201     basic_json(size_type\, const basic_json&)\r
2202     constructor.,basic_json__size_type_basic_json}\r
2203 \r
2204     @since version 1.0.0\r
2205     */\r
2206     basic_json(size_type cnt, const basic_json& val)\r
2207         : m_type(value_t::array)\r
2208     {\r
2209         m_value.array = create<array_t>(cnt, val);\r
2210         assert_invariant();\r
2211     }\r
2212 \r
2213     /*!\r
2214     @brief construct a JSON container given an iterator range\r
2215 \r
2216     Constructs the JSON value with the contents of the range `[first, last)`.\r
2217     The semantics depends on the different types a JSON value can have:\r
2218     - In case of primitive types (number, boolean, or string), @a first must\r
2219       be `begin()` and @a last must be `end()`. In this case, the value is\r
2220       copied. Otherwise, std::out_of_range is thrown.\r
2221     - In case of structured types (array, object), the constructor behaves as\r
2222       similar versions for `std::vector`.\r
2223     - In case of a null type, std::domain_error is thrown.\r
2224 \r
2225     @tparam InputIT an input iterator type (@ref iterator or @ref\r
2226     const_iterator)\r
2227 \r
2228     @param[in] first begin of the range to copy from (included)\r
2229     @param[in] last end of the range to copy from (excluded)\r
2230 \r
2231     @pre Iterators @a first and @a last must be initialized. **This\r
2232          precondition is enforced with an assertion.**\r
2233 \r
2234     @throw std::domain_error if iterators are not compatible; that is, do not\r
2235     belong to the same JSON value; example: `"iterators are not compatible"`\r
2236     @throw std::out_of_range if iterators are for a primitive type (number,\r
2237     boolean, or string) where an out of range error can be detected easily;\r
2238     example: `"iterators out of range"`\r
2239     @throw std::bad_alloc if allocation for object, array, or string fails\r
2240     @throw std::domain_error if called with a null value; example: `"cannot\r
2241     use construct with iterators from null"`\r
2242 \r
2243     @complexity Linear in distance between @a first and @a last.\r
2244 \r
2245     @liveexample{The example below shows several ways to create JSON values by\r
2246     specifying a subrange with iterators.,basic_json__InputIt_InputIt}\r
2247 \r
2248     @since version 1.0.0\r
2249     */\r
2250     template<class InputIT, typename std::enable_if<\r
2251                  std::is_same<InputIT, typename basic_json_t::iterator>::value or\r
2252                  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>\r
2253     basic_json(InputIT first, InputIT last)\r
2254     {\r
2255         assert(first.m_object != nullptr);\r
2256         assert(last.m_object != nullptr);\r
2257 \r
2258         // make sure iterator fits the current value\r
2259         if (first.m_object != last.m_object)\r
2260         {\r
2261             JSON_THROW(std::domain_error("iterators are not compatible"));\r
2262         }\r
2263 \r
2264         // copy type from first iterator\r
2265         m_type = first.m_object->m_type;\r
2266 \r
2267         // check if iterator range is complete for primitive values\r
2268         switch (m_type)\r
2269         {\r
2270             case value_t::boolean:\r
2271             case value_t::number_float:\r
2272             case value_t::number_integer:\r
2273             case value_t::number_unsigned:\r
2274             case value_t::string:\r
2275             {\r
2276                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())\r
2277                 {\r
2278                     JSON_THROW(std::out_of_range("iterators out of range"));\r
2279                 }\r
2280                 break;\r
2281             }\r
2282 \r
2283             default:\r
2284             {\r
2285                 break;\r
2286             }\r
2287         }\r
2288 \r
2289         switch (m_type)\r
2290         {\r
2291             case value_t::number_integer:\r
2292             {\r
2293                 m_value.number_integer = first.m_object->m_value.number_integer;\r
2294                 break;\r
2295             }\r
2296 \r
2297             case value_t::number_unsigned:\r
2298             {\r
2299                 m_value.number_unsigned = first.m_object->m_value.number_unsigned;\r
2300                 break;\r
2301             }\r
2302 \r
2303             case value_t::number_float:\r
2304             {\r
2305                 m_value.number_float = first.m_object->m_value.number_float;\r
2306                 break;\r
2307             }\r
2308 \r
2309             case value_t::boolean:\r
2310             {\r
2311                 m_value.boolean = first.m_object->m_value.boolean;\r
2312                 break;\r
2313             }\r
2314 \r
2315             case value_t::string:\r
2316             {\r
2317                 m_value = *first.m_object->m_value.string;\r
2318                 break;\r
2319             }\r
2320 \r
2321             case value_t::object:\r
2322             {\r
2323                 m_value.object = create<object_t>(first.m_it.object_iterator,\r
2324                                                   last.m_it.object_iterator);\r
2325                 break;\r
2326             }\r
2327 \r
2328             case value_t::array:\r
2329             {\r
2330                 m_value.array = create<array_t>(first.m_it.array_iterator,\r
2331                                                 last.m_it.array_iterator);\r
2332                 break;\r
2333             }\r
2334 \r
2335             default:\r
2336             {\r
2337                 JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()));\r
2338             }\r
2339         }\r
2340 \r
2341         assert_invariant();\r
2342     }\r
2343 \r
2344     /*!\r
2345     @brief construct a JSON value given an input stream\r
2346 \r
2347     @param[in,out] i  stream to read a serialized JSON value from\r
2348     @param[in] cb a parser callback function of type @ref parser_callback_t\r
2349     which is used to control the deserialization by filtering unwanted values\r
2350     (optional)\r
2351 \r
2352     @complexity Linear in the length of the input. The parser is a predictive\r
2353     LL(1) parser. The complexity can be higher if the parser callback function\r
2354     @a cb has a super-linear complexity.\r
2355 \r
2356     @note A UTF-8 byte order mark is silently ignored.\r
2357 \r
2358     @deprecated This constructor is deprecated and will be removed in version\r
2359       3.0.0 to unify the interface of the library. Deserialization will be\r
2360       done by stream operators or by calling one of the `parse` functions,\r
2361       e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls\r
2362       like `json j(i);` for an input stream @a i need to be replaced by\r
2363       `json j = json::parse(i);`. See the example below.\r
2364 \r
2365     @liveexample{The example below demonstrates constructing a JSON value from\r
2366     a `std::stringstream` with and without callback\r
2367     function.,basic_json__istream}\r
2368 \r
2369     @since version 2.0.0, deprecated in version 2.0.3, to be removed in\r
2370            version 3.0.0\r
2371     */\r
2372     JSON_DEPRECATED\r
2373     explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)\r
2374     {\r
2375         *this = parser(i, cb).parse();\r
2376         assert_invariant();\r
2377     }\r
2378 \r
2379     ///////////////////////////////////////\r
2380     // other constructors and destructor //\r
2381     ///////////////////////////////////////\r
2382 \r
2383     /*!\r
2384     @brief copy constructor\r
2385 \r
2386     Creates a copy of a given JSON value.\r
2387 \r
2388     @param[in] other  the JSON value to copy\r
2389 \r
2390     @complexity Linear in the size of @a other.\r
2391 \r
2392     @requirement This function helps `basic_json` satisfying the\r
2393     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
2394     requirements:\r
2395     - The complexity is linear.\r
2396     - As postcondition, it holds: `other == basic_json(other)`.\r
2397 \r
2398     @throw std::bad_alloc if allocation for object, array, or string fails.\r
2399 \r
2400     @liveexample{The following code shows an example for the copy\r
2401     constructor.,basic_json__basic_json}\r
2402 \r
2403     @since version 1.0.0\r
2404     */\r
2405     basic_json(const basic_json& other)\r
2406         : m_type(other.m_type)\r
2407     {\r
2408         // check of passed value is valid\r
2409         other.assert_invariant();\r
2410 \r
2411         switch (m_type)\r
2412         {\r
2413             case value_t::object:\r
2414             {\r
2415                 m_value = *other.m_value.object;\r
2416                 break;\r
2417             }\r
2418 \r
2419             case value_t::array:\r
2420             {\r
2421                 m_value = *other.m_value.array;\r
2422                 break;\r
2423             }\r
2424 \r
2425             case value_t::string:\r
2426             {\r
2427                 m_value = *other.m_value.string;\r
2428                 break;\r
2429             }\r
2430 \r
2431             case value_t::boolean:\r
2432             {\r
2433                 m_value = other.m_value.boolean;\r
2434                 break;\r
2435             }\r
2436 \r
2437             case value_t::number_integer:\r
2438             {\r
2439                 m_value = other.m_value.number_integer;\r
2440                 break;\r
2441             }\r
2442 \r
2443             case value_t::number_unsigned:\r
2444             {\r
2445                 m_value = other.m_value.number_unsigned;\r
2446                 break;\r
2447             }\r
2448 \r
2449             case value_t::number_float:\r
2450             {\r
2451                 m_value = other.m_value.number_float;\r
2452                 break;\r
2453             }\r
2454 \r
2455             default:\r
2456             {\r
2457                 break;\r
2458             }\r
2459         }\r
2460 \r
2461         assert_invariant();\r
2462     }\r
2463 \r
2464     /*!\r
2465     @brief move constructor\r
2466 \r
2467     Move constructor. Constructs a JSON value with the contents of the given\r
2468     value @a other using move semantics. It "steals" the resources from @a\r
2469     other and leaves it as JSON null value.\r
2470 \r
2471     @param[in,out] other  value to move to this object\r
2472 \r
2473     @post @a other is a JSON null value\r
2474 \r
2475     @complexity Constant.\r
2476 \r
2477     @liveexample{The code below shows the move constructor explicitly called\r
2478     via std::move.,basic_json__moveconstructor}\r
2479 \r
2480     @since version 1.0.0\r
2481     */\r
2482     basic_json(basic_json&& other) noexcept\r
2483         : m_type(std::move(other.m_type)),\r
2484           m_value(std::move(other.m_value))\r
2485     {\r
2486         // check that passed value is valid\r
2487         other.assert_invariant();\r
2488 \r
2489         // invalidate payload\r
2490         other.m_type = value_t::null;\r
2491         other.m_value = {};\r
2492 \r
2493         assert_invariant();\r
2494     }\r
2495 \r
2496     /*!\r
2497     @brief copy assignment\r
2498 \r
2499     Copy assignment operator. Copies a JSON value via the "copy and swap"\r
2500     strategy: It is expressed in terms of the copy constructor, destructor,\r
2501     and the swap() member function.\r
2502 \r
2503     @param[in] other  value to copy from\r
2504 \r
2505     @complexity Linear.\r
2506 \r
2507     @requirement This function helps `basic_json` satisfying the\r
2508     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
2509     requirements:\r
2510     - The complexity is linear.\r
2511 \r
2512     @liveexample{The code below shows and example for the copy assignment. It\r
2513     creates a copy of value `a` which is then swapped with `b`. Finally\, the\r
2514     copy of `a` (which is the null value after the swap) is\r
2515     destroyed.,basic_json__copyassignment}\r
2516 \r
2517     @since version 1.0.0\r
2518     */\r
2519     reference& operator=(basic_json other) noexcept (\r
2520         std::is_nothrow_move_constructible<value_t>::value and\r
2521         std::is_nothrow_move_assignable<value_t>::value and\r
2522         std::is_nothrow_move_constructible<json_value>::value and\r
2523         std::is_nothrow_move_assignable<json_value>::value\r
2524     )\r
2525     {\r
2526         // check that passed value is valid\r
2527         other.assert_invariant();\r
2528 \r
2529         using std::swap;\r
2530         swap(m_type, other.m_type);\r
2531         swap(m_value, other.m_value);\r
2532 \r
2533         assert_invariant();\r
2534         return *this;\r
2535     }\r
2536 \r
2537     /*!\r
2538     @brief destructor\r
2539 \r
2540     Destroys the JSON value and frees all allocated memory.\r
2541 \r
2542     @complexity Linear.\r
2543 \r
2544     @requirement This function helps `basic_json` satisfying the\r
2545     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
2546     requirements:\r
2547     - The complexity is linear.\r
2548     - All stored elements are destroyed and all memory is freed.\r
2549 \r
2550     @since version 1.0.0\r
2551     */\r
2552     ~basic_json()\r
2553     {\r
2554         assert_invariant();\r
2555 \r
2556         switch (m_type)\r
2557         {\r
2558             case value_t::object:\r
2559             {\r
2560                 AllocatorType<object_t> alloc;\r
2561                 alloc.destroy(m_value.object);\r
2562                 alloc.deallocate(m_value.object, 1);\r
2563                 break;\r
2564             }\r
2565 \r
2566             case value_t::array:\r
2567             {\r
2568                 AllocatorType<array_t> alloc;\r
2569                 alloc.destroy(m_value.array);\r
2570                 alloc.deallocate(m_value.array, 1);\r
2571                 break;\r
2572             }\r
2573 \r
2574             case value_t::string:\r
2575             {\r
2576                 AllocatorType<string_t> alloc;\r
2577                 alloc.destroy(m_value.string);\r
2578                 alloc.deallocate(m_value.string, 1);\r
2579                 break;\r
2580             }\r
2581 \r
2582             default:\r
2583             {\r
2584                 // all other types need no specific destructor\r
2585                 break;\r
2586             }\r
2587         }\r
2588     }\r
2589 \r
2590     /// @}\r
2591 \r
2592   public:\r
2593     ///////////////////////\r
2594     // object inspection //\r
2595     ///////////////////////\r
2596 \r
2597     /// @name object inspection\r
2598     /// Functions to inspect the type of a JSON value.\r
2599     /// @{\r
2600 \r
2601     /*!\r
2602     @brief serialization\r
2603 \r
2604     Serialization function for JSON values. The function tries to mimic\r
2605     Python's `json.dumps()` function, and currently supports its @a indent\r
2606     parameter.\r
2607 \r
2608     @param[in] indent If indent is nonnegative, then array elements and object\r
2609     members will be pretty-printed with that indent level. An indent level of\r
2610     `0` will only insert newlines. `-1` (the default) selects the most compact\r
2611     representation.\r
2612 \r
2613     @return string containing the serialization of the JSON value\r
2614 \r
2615     @complexity Linear.\r
2616 \r
2617     @liveexample{The following example shows the effect of different @a indent\r
2618     parameters to the result of the serialization.,dump}\r
2619 \r
2620     @see https://docs.python.org/2/library/json.html#json.dump\r
2621 \r
2622     @since version 1.0.0\r
2623     */\r
2624     string_t dump(const int indent = -1) const\r
2625     {\r
2626         std::stringstream ss;\r
2627 \r
2628         if (indent >= 0)\r
2629         {\r
2630             dump(ss, true, static_cast<unsigned int>(indent));\r
2631         }\r
2632         else\r
2633         {\r
2634             dump(ss, false, 0);\r
2635         }\r
2636 \r
2637         return ss.str();\r
2638     }\r
2639 \r
2640     /*!\r
2641     @brief return the type of the JSON value (explicit)\r
2642 \r
2643     Return the type of the JSON value as a value from the @ref value_t\r
2644     enumeration.\r
2645 \r
2646     @return the type of the JSON value\r
2647 \r
2648     @complexity Constant.\r
2649 \r
2650     @exceptionsafety No-throw guarantee: this member function never throws\r
2651     exceptions.\r
2652 \r
2653     @liveexample{The following code exemplifies `type()` for all JSON\r
2654     types.,type}\r
2655 \r
2656     @since version 1.0.0\r
2657     */\r
2658     constexpr value_t type() const noexcept\r
2659     {\r
2660         return m_type;\r
2661     }\r
2662 \r
2663     /*!\r
2664     @brief return whether type is primitive\r
2665 \r
2666     This function returns true iff the JSON type is primitive (string, number,\r
2667     boolean, or null).\r
2668 \r
2669     @return `true` if type is primitive (string, number, boolean, or null),\r
2670     `false` otherwise.\r
2671 \r
2672     @complexity Constant.\r
2673 \r
2674     @exceptionsafety No-throw guarantee: this member function never throws\r
2675     exceptions.\r
2676 \r
2677     @liveexample{The following code exemplifies `is_primitive()` for all JSON\r
2678     types.,is_primitive}\r
2679 \r
2680     @sa @ref is_structured() -- returns whether JSON value is structured\r
2681     @sa @ref is_null() -- returns whether JSON value is `null`\r
2682     @sa @ref is_string() -- returns whether JSON value is a string\r
2683     @sa @ref is_boolean() -- returns whether JSON value is a boolean\r
2684     @sa @ref is_number() -- returns whether JSON value is a number\r
2685 \r
2686     @since version 1.0.0\r
2687     */\r
2688     constexpr bool is_primitive() const noexcept\r
2689     {\r
2690         return is_null() or is_string() or is_boolean() or is_number();\r
2691     }\r
2692 \r
2693     /*!\r
2694     @brief return whether type is structured\r
2695 \r
2696     This function returns true iff the JSON type is structured (array or\r
2697     object).\r
2698 \r
2699     @return `true` if type is structured (array or object), `false` otherwise.\r
2700 \r
2701     @complexity Constant.\r
2702 \r
2703     @exceptionsafety No-throw guarantee: this member function never throws\r
2704     exceptions.\r
2705 \r
2706     @liveexample{The following code exemplifies `is_structured()` for all JSON\r
2707     types.,is_structured}\r
2708 \r
2709     @sa @ref is_primitive() -- returns whether value is primitive\r
2710     @sa @ref is_array() -- returns whether value is an array\r
2711     @sa @ref is_object() -- returns whether value is an object\r
2712 \r
2713     @since version 1.0.0\r
2714     */\r
2715     constexpr bool is_structured() const noexcept\r
2716     {\r
2717         return is_array() or is_object();\r
2718     }\r
2719 \r
2720     /*!\r
2721     @brief return whether value is null\r
2722 \r
2723     This function returns true iff the JSON value is null.\r
2724 \r
2725     @return `true` if type is null, `false` otherwise.\r
2726 \r
2727     @complexity Constant.\r
2728 \r
2729     @exceptionsafety No-throw guarantee: this member function never throws\r
2730     exceptions.\r
2731 \r
2732     @liveexample{The following code exemplifies `is_null()` for all JSON\r
2733     types.,is_null}\r
2734 \r
2735     @since version 1.0.0\r
2736     */\r
2737     constexpr bool is_null() const noexcept\r
2738     {\r
2739         return m_type == value_t::null;\r
2740     }\r
2741 \r
2742     /*!\r
2743     @brief return whether value is a boolean\r
2744 \r
2745     This function returns true iff the JSON value is a boolean.\r
2746 \r
2747     @return `true` if type is boolean, `false` otherwise.\r
2748 \r
2749     @complexity Constant.\r
2750 \r
2751     @exceptionsafety No-throw guarantee: this member function never throws\r
2752     exceptions.\r
2753 \r
2754     @liveexample{The following code exemplifies `is_boolean()` for all JSON\r
2755     types.,is_boolean}\r
2756 \r
2757     @since version 1.0.0\r
2758     */\r
2759     constexpr bool is_boolean() const noexcept\r
2760     {\r
2761         return m_type == value_t::boolean;\r
2762     }\r
2763 \r
2764     /*!\r
2765     @brief return whether value is a number\r
2766 \r
2767     This function returns true iff the JSON value is a number. This includes\r
2768     both integer and floating-point values.\r
2769 \r
2770     @return `true` if type is number (regardless whether integer, unsigned\r
2771     integer or floating-type), `false` otherwise.\r
2772 \r
2773     @complexity Constant.\r
2774 \r
2775     @exceptionsafety No-throw guarantee: this member function never throws\r
2776     exceptions.\r
2777 \r
2778     @liveexample{The following code exemplifies `is_number()` for all JSON\r
2779     types.,is_number}\r
2780 \r
2781     @sa @ref is_number_integer() -- check if value is an integer or unsigned\r
2782     integer number\r
2783     @sa @ref is_number_unsigned() -- check if value is an unsigned integer\r
2784     number\r
2785     @sa @ref is_number_float() -- check if value is a floating-point number\r
2786 \r
2787     @since version 1.0.0\r
2788     */\r
2789     constexpr bool is_number() const noexcept\r
2790     {\r
2791         return is_number_integer() or is_number_float();\r
2792     }\r
2793 \r
2794     /*!\r
2795     @brief return whether value is an integer number\r
2796 \r
2797     This function returns true iff the JSON value is an integer or unsigned\r
2798     integer number. This excludes floating-point values.\r
2799 \r
2800     @return `true` if type is an integer or unsigned integer number, `false`\r
2801     otherwise.\r
2802 \r
2803     @complexity Constant.\r
2804 \r
2805     @exceptionsafety No-throw guarantee: this member function never throws\r
2806     exceptions.\r
2807 \r
2808     @liveexample{The following code exemplifies `is_number_integer()` for all\r
2809     JSON types.,is_number_integer}\r
2810 \r
2811     @sa @ref is_number() -- check if value is a number\r
2812     @sa @ref is_number_unsigned() -- check if value is an unsigned integer\r
2813     number\r
2814     @sa @ref is_number_float() -- check if value is a floating-point number\r
2815 \r
2816     @since version 1.0.0\r
2817     */\r
2818     constexpr bool is_number_integer() const noexcept\r
2819     {\r
2820         return m_type == value_t::number_integer or m_type == value_t::number_unsigned;\r
2821     }\r
2822 \r
2823     /*!\r
2824     @brief return whether value is an unsigned integer number\r
2825 \r
2826     This function returns true iff the JSON value is an unsigned integer\r
2827     number. This excludes floating-point and (signed) integer values.\r
2828 \r
2829     @return `true` if type is an unsigned integer number, `false` otherwise.\r
2830 \r
2831     @complexity Constant.\r
2832 \r
2833     @exceptionsafety No-throw guarantee: this member function never throws\r
2834     exceptions.\r
2835 \r
2836     @liveexample{The following code exemplifies `is_number_unsigned()` for all\r
2837     JSON types.,is_number_unsigned}\r
2838 \r
2839     @sa @ref is_number() -- check if value is a number\r
2840     @sa @ref is_number_integer() -- check if value is an integer or unsigned\r
2841     integer number\r
2842     @sa @ref is_number_float() -- check if value is a floating-point number\r
2843 \r
2844     @since version 2.0.0\r
2845     */\r
2846     constexpr bool is_number_unsigned() const noexcept\r
2847     {\r
2848         return m_type == value_t::number_unsigned;\r
2849     }\r
2850 \r
2851     /*!\r
2852     @brief return whether value is a floating-point number\r
2853 \r
2854     This function returns true iff the JSON value is a floating-point number.\r
2855     This excludes integer and unsigned integer values.\r
2856 \r
2857     @return `true` if type is a floating-point number, `false` otherwise.\r
2858 \r
2859     @complexity Constant.\r
2860 \r
2861     @exceptionsafety No-throw guarantee: this member function never throws\r
2862     exceptions.\r
2863 \r
2864     @liveexample{The following code exemplifies `is_number_float()` for all\r
2865     JSON types.,is_number_float}\r
2866 \r
2867     @sa @ref is_number() -- check if value is number\r
2868     @sa @ref is_number_integer() -- check if value is an integer number\r
2869     @sa @ref is_number_unsigned() -- check if value is an unsigned integer\r
2870     number\r
2871 \r
2872     @since version 1.0.0\r
2873     */\r
2874     constexpr bool is_number_float() const noexcept\r
2875     {\r
2876         return m_type == value_t::number_float;\r
2877     }\r
2878 \r
2879     /*!\r
2880     @brief return whether value is an object\r
2881 \r
2882     This function returns true iff the JSON value is an object.\r
2883 \r
2884     @return `true` if type is object, `false` otherwise.\r
2885 \r
2886     @complexity Constant.\r
2887 \r
2888     @exceptionsafety No-throw guarantee: this member function never throws\r
2889     exceptions.\r
2890 \r
2891     @liveexample{The following code exemplifies `is_object()` for all JSON\r
2892     types.,is_object}\r
2893 \r
2894     @since version 1.0.0\r
2895     */\r
2896     constexpr bool is_object() const noexcept\r
2897     {\r
2898         return m_type == value_t::object;\r
2899     }\r
2900 \r
2901     /*!\r
2902     @brief return whether value is an array\r
2903 \r
2904     This function returns true iff the JSON value is an array.\r
2905 \r
2906     @return `true` if type is array, `false` otherwise.\r
2907 \r
2908     @complexity Constant.\r
2909 \r
2910     @exceptionsafety No-throw guarantee: this member function never throws\r
2911     exceptions.\r
2912 \r
2913     @liveexample{The following code exemplifies `is_array()` for all JSON\r
2914     types.,is_array}\r
2915 \r
2916     @since version 1.0.0\r
2917     */\r
2918     constexpr bool is_array() const noexcept\r
2919     {\r
2920         return m_type == value_t::array;\r
2921     }\r
2922 \r
2923     /*!\r
2924     @brief return whether value is a string\r
2925 \r
2926     This function returns true iff the JSON value is a string.\r
2927 \r
2928     @return `true` if type is string, `false` otherwise.\r
2929 \r
2930     @complexity Constant.\r
2931 \r
2932     @exceptionsafety No-throw guarantee: this member function never throws\r
2933     exceptions.\r
2934 \r
2935     @liveexample{The following code exemplifies `is_string()` for all JSON\r
2936     types.,is_string}\r
2937 \r
2938     @since version 1.0.0\r
2939     */\r
2940     constexpr bool is_string() const noexcept\r
2941     {\r
2942         return m_type == value_t::string;\r
2943     }\r
2944 \r
2945     /*!\r
2946     @brief return whether value is discarded\r
2947 \r
2948     This function returns true iff the JSON value was discarded during parsing\r
2949     with a callback function (see @ref parser_callback_t).\r
2950 \r
2951     @note This function will always be `false` for JSON values after parsing.\r
2952     That is, discarded values can only occur during parsing, but will be\r
2953     removed when inside a structured value or replaced by null in other cases.\r
2954 \r
2955     @return `true` if type is discarded, `false` otherwise.\r
2956 \r
2957     @complexity Constant.\r
2958 \r
2959     @exceptionsafety No-throw guarantee: this member function never throws\r
2960     exceptions.\r
2961 \r
2962     @liveexample{The following code exemplifies `is_discarded()` for all JSON\r
2963     types.,is_discarded}\r
2964 \r
2965     @since version 1.0.0\r
2966     */\r
2967     constexpr bool is_discarded() const noexcept\r
2968     {\r
2969         return m_type == value_t::discarded;\r
2970     }\r
2971 \r
2972     /*!\r
2973     @brief return the type of the JSON value (implicit)\r
2974 \r
2975     Implicitly return the type of the JSON value as a value from the @ref\r
2976     value_t enumeration.\r
2977 \r
2978     @return the type of the JSON value\r
2979 \r
2980     @complexity Constant.\r
2981 \r
2982     @exceptionsafety No-throw guarantee: this member function never throws\r
2983     exceptions.\r
2984 \r
2985     @liveexample{The following code exemplifies the @ref value_t operator for\r
2986     all JSON types.,operator__value_t}\r
2987 \r
2988     @since version 1.0.0\r
2989     */\r
2990     constexpr operator value_t() const noexcept\r
2991     {\r
2992         return m_type;\r
2993     }\r
2994 \r
2995     /// @}\r
2996 \r
2997   private:\r
2998     //////////////////\r
2999     // value access //\r
3000     //////////////////\r
3001 \r
3002     /// get a boolean (explicit)\r
3003     boolean_t get_impl(boolean_t* /*unused*/) const\r
3004     {\r
3005         if (is_boolean())\r
3006         {\r
3007             return m_value.boolean;\r
3008         }\r
3009 \r
3010         JSON_THROW(std::domain_error("type must be boolean, but is " + type_name()));\r
3011     }\r
3012 \r
3013     /// get a pointer to the value (object)\r
3014     object_t* get_impl_ptr(object_t* /*unused*/) noexcept\r
3015     {\r
3016         return is_object() ? m_value.object : nullptr;\r
3017     }\r
3018 \r
3019     /// get a pointer to the value (object)\r
3020     constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept\r
3021     {\r
3022         return is_object() ? m_value.object : nullptr;\r
3023     }\r
3024 \r
3025     /// get a pointer to the value (array)\r
3026     array_t* get_impl_ptr(array_t* /*unused*/) noexcept\r
3027     {\r
3028         return is_array() ? m_value.array : nullptr;\r
3029     }\r
3030 \r
3031     /// get a pointer to the value (array)\r
3032     constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept\r
3033     {\r
3034         return is_array() ? m_value.array : nullptr;\r
3035     }\r
3036 \r
3037     /// get a pointer to the value (string)\r
3038     string_t* get_impl_ptr(string_t* /*unused*/) noexcept\r
3039     {\r
3040         return is_string() ? m_value.string : nullptr;\r
3041     }\r
3042 \r
3043     /// get a pointer to the value (string)\r
3044     constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept\r
3045     {\r
3046         return is_string() ? m_value.string : nullptr;\r
3047     }\r
3048 \r
3049     /// get a pointer to the value (boolean)\r
3050     boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept\r
3051     {\r
3052         return is_boolean() ? &m_value.boolean : nullptr;\r
3053     }\r
3054 \r
3055     /// get a pointer to the value (boolean)\r
3056     constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept\r
3057     {\r
3058         return is_boolean() ? &m_value.boolean : nullptr;\r
3059     }\r
3060 \r
3061     /// get a pointer to the value (integer number)\r
3062     number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept\r
3063     {\r
3064         return is_number_integer() ? &m_value.number_integer : nullptr;\r
3065     }\r
3066 \r
3067     /// get a pointer to the value (integer number)\r
3068     constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept\r
3069     {\r
3070         return is_number_integer() ? &m_value.number_integer : nullptr;\r
3071     }\r
3072 \r
3073     /// get a pointer to the value (unsigned number)\r
3074     number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept\r
3075     {\r
3076         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;\r
3077     }\r
3078 \r
3079     /// get a pointer to the value (unsigned number)\r
3080     constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept\r
3081     {\r
3082         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;\r
3083     }\r
3084 \r
3085     /// get a pointer to the value (floating-point number)\r
3086     number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept\r
3087     {\r
3088         return is_number_float() ? &m_value.number_float : nullptr;\r
3089     }\r
3090 \r
3091     /// get a pointer to the value (floating-point number)\r
3092     constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept\r
3093     {\r
3094         return is_number_float() ? &m_value.number_float : nullptr;\r
3095     }\r
3096 \r
3097     /*!\r
3098     @brief helper function to implement get_ref()\r
3099 \r
3100     This funcion helps to implement get_ref() without code duplication for\r
3101     const and non-const overloads\r
3102 \r
3103     @tparam ThisType will be deduced as `basic_json` or `const basic_json`\r
3104 \r
3105     @throw std::domain_error if ReferenceType does not match underlying value\r
3106     type of the current JSON\r
3107     */\r
3108     template<typename ReferenceType, typename ThisType>\r
3109     static ReferenceType get_ref_impl(ThisType& obj)\r
3110     {\r
3111         // helper type\r
3112         using PointerType = typename std::add_pointer<ReferenceType>::type;\r
3113 \r
3114         // delegate the call to get_ptr<>()\r
3115         auto ptr = obj.template get_ptr<PointerType>();\r
3116 \r
3117         if (ptr != nullptr)\r
3118         {\r
3119             return *ptr;\r
3120         }\r
3121 \r
3122         JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " +\r
3123                                      obj.type_name()));\r
3124     }\r
3125 \r
3126   public:\r
3127     /// @name value access\r
3128     /// Direct access to the stored value of a JSON value.\r
3129     /// @{\r
3130 \r
3131     /*!\r
3132     @brief get special-case overload\r
3133 \r
3134     This overloads avoids a lot of template boilerplate, it can be seen as the\r
3135     identity method\r
3136 \r
3137     @tparam BasicJsonType == @ref basic_json\r
3138 \r
3139     @return a copy of *this\r
3140 \r
3141     @complexity Constant.\r
3142 \r
3143     @since version 2.1.0\r
3144     */\r
3145     template <\r
3146         typename BasicJsonType,\r
3147         detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,\r
3148                                          basic_json_t>::value,\r
3149                             int> = 0 >\r
3150     basic_json get() const\r
3151     {\r
3152         return *this;\r
3153     }\r
3154 \r
3155     /*!\r
3156     @brief get a value (explicit)\r
3157 \r
3158     Explicit type conversion between the JSON value and a compatible value\r
3159     which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)\r
3160     and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).\r
3161     The value is converted by calling the @ref json_serializer<ValueType>\r
3162     `from_json()` method.\r
3163 \r
3164     The function is equivalent to executing\r
3165     @code {.cpp}\r
3166     ValueType ret;\r
3167     JSONSerializer<ValueType>::from_json(*this, ret);\r
3168     return ret;\r
3169     @endcode\r
3170 \r
3171     This overloads is chosen if:\r
3172     - @a ValueType is not @ref basic_json,\r
3173     - @ref json_serializer<ValueType> has a `from_json()` method of the form\r
3174       `void from_json(const @ref basic_json&, ValueType&)`, and\r
3175     - @ref json_serializer<ValueType> does not have a `from_json()` method of\r
3176       the form `ValueType from_json(const @ref basic_json&)`\r
3177 \r
3178     @tparam ValueTypeCV the provided value type\r
3179     @tparam ValueType the returned value type\r
3180 \r
3181     @return copy of the JSON value, converted to @a ValueType\r
3182 \r
3183     @throw what @ref json_serializer<ValueType> `from_json()` method throws\r
3184 \r
3185     @liveexample{The example below shows several conversions from JSON values\r
3186     to other types. There a few things to note: (1) Floating-point numbers can\r
3187     be converted to integers\, (2) A JSON array can be converted to a standard\r
3188     `std::vector<short>`\, (3) A JSON object can be converted to C++\r
3189     associative containers such as `std::unordered_map<std::string\,\r
3190     json>`.,get__ValueType_const}\r
3191 \r
3192     @since version 2.1.0\r
3193     */\r
3194     template <\r
3195         typename ValueTypeCV,\r
3196         typename ValueType = detail::uncvref_t<ValueTypeCV>,\r
3197         detail::enable_if_t <\r
3198             not std::is_same<basic_json_t, ValueType>::value and\r
3199             detail::has_from_json<basic_json_t, ValueType>::value and\r
3200             not detail::has_non_default_from_json<basic_json_t, ValueType>::value,\r
3201             int > = 0 >\r
3202     ValueType get() const noexcept(noexcept(\r
3203                                        JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))\r
3204     {\r
3205         // we cannot static_assert on ValueTypeCV being non-const, because\r
3206         // there is support for get<const basic_json_t>(), which is why we\r
3207         // still need the uncvref\r
3208         static_assert(not std::is_reference<ValueTypeCV>::value,\r
3209                       "get() cannot be used with reference types, you might want to use get_ref()");\r
3210         static_assert(std::is_default_constructible<ValueType>::value,\r
3211                       "types must be DefaultConstructible when used with get()");\r
3212 \r
3213         ValueType ret;\r
3214         JSONSerializer<ValueType>::from_json(*this, ret);\r
3215         return ret;\r
3216     }\r
3217 \r
3218     /*!\r
3219     @brief get a value (explicit); special case\r
3220 \r
3221     Explicit type conversion between the JSON value and a compatible value\r
3222     which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)\r
3223     and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).\r
3224     The value is converted by calling the @ref json_serializer<ValueType>\r
3225     `from_json()` method.\r
3226 \r
3227     The function is equivalent to executing\r
3228     @code {.cpp}\r
3229     return JSONSerializer<ValueTypeCV>::from_json(*this);\r
3230     @endcode\r
3231 \r
3232     This overloads is chosen if:\r
3233     - @a ValueType is not @ref basic_json and\r
3234     - @ref json_serializer<ValueType> has a `from_json()` method of the form\r
3235       `ValueType from_json(const @ref basic_json&)`\r
3236 \r
3237     @note If @ref json_serializer<ValueType> has both overloads of\r
3238     `from_json()`, this one is chosen.\r
3239 \r
3240     @tparam ValueTypeCV the provided value type\r
3241     @tparam ValueType the returned value type\r
3242 \r
3243     @return copy of the JSON value, converted to @a ValueType\r
3244 \r
3245     @throw what @ref json_serializer<ValueType> `from_json()` method throws\r
3246 \r
3247     @since version 2.1.0\r
3248     */\r
3249     template <\r
3250         typename ValueTypeCV,\r
3251         typename ValueType = detail::uncvref_t<ValueTypeCV>,\r
3252         detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and\r
3253                             detail::has_non_default_from_json<basic_json_t,\r
3254                                     ValueType>::value, int> = 0 >\r
3255     ValueType get() const noexcept(noexcept(\r
3256                                        JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))\r
3257     {\r
3258         static_assert(not std::is_reference<ValueTypeCV>::value,\r
3259                       "get() cannot be used with reference types, you might want to use get_ref()");\r
3260         return JSONSerializer<ValueTypeCV>::from_json(*this);\r
3261     }\r
3262 \r
3263     /*!\r
3264     @brief get a pointer value (explicit)\r
3265 \r
3266     Explicit pointer access to the internally stored JSON value. No copies are\r
3267     made.\r
3268 \r
3269     @warning The pointer becomes invalid if the underlying JSON object\r
3270     changes.\r
3271 \r
3272     @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\r
3273     object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\r
3274     @ref number_unsigned_t, or @ref number_float_t.\r
3275 \r
3276     @return pointer to the internally stored JSON value if the requested\r
3277     pointer type @a PointerType fits to the JSON value; `nullptr` otherwise\r
3278 \r
3279     @complexity Constant.\r
3280 \r
3281     @liveexample{The example below shows how pointers to internal values of a\r
3282     JSON value can be requested. Note that no type conversions are made and a\r
3283     `nullptr` is returned if the value and the requested pointer type does not\r
3284     match.,get__PointerType}\r
3285 \r
3286     @sa @ref get_ptr() for explicit pointer-member access\r
3287 \r
3288     @since version 1.0.0\r
3289     */\r
3290     template<typename PointerType, typename std::enable_if<\r
3291                  std::is_pointer<PointerType>::value, int>::type = 0>\r
3292     PointerType get() noexcept\r
3293     {\r
3294         // delegate the call to get_ptr\r
3295         return get_ptr<PointerType>();\r
3296     }\r
3297 \r
3298     /*!\r
3299     @brief get a pointer value (explicit)\r
3300     @copydoc get()\r
3301     */\r
3302     template<typename PointerType, typename std::enable_if<\r
3303                  std::is_pointer<PointerType>::value, int>::type = 0>\r
3304     constexpr const PointerType get() const noexcept\r
3305     {\r
3306         // delegate the call to get_ptr\r
3307         return get_ptr<PointerType>();\r
3308     }\r
3309 \r
3310     /*!\r
3311     @brief get a pointer value (implicit)\r
3312 \r
3313     Implicit pointer access to the internally stored JSON value. No copies are\r
3314     made.\r
3315 \r
3316     @warning Writing data to the pointee of the result yields an undefined\r
3317     state.\r
3318 \r
3319     @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\r
3320     object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\r
3321     @ref number_unsigned_t, or @ref number_float_t. Enforced by a static\r
3322     assertion.\r
3323 \r
3324     @return pointer to the internally stored JSON value if the requested\r
3325     pointer type @a PointerType fits to the JSON value; `nullptr` otherwise\r
3326 \r
3327     @complexity Constant.\r
3328 \r
3329     @liveexample{The example below shows how pointers to internal values of a\r
3330     JSON value can be requested. Note that no type conversions are made and a\r
3331     `nullptr` is returned if the value and the requested pointer type does not\r
3332     match.,get_ptr}\r
3333 \r
3334     @since version 1.0.0\r
3335     */\r
3336     template<typename PointerType, typename std::enable_if<\r
3337                  std::is_pointer<PointerType>::value, int>::type = 0>\r
3338     PointerType get_ptr() noexcept\r
3339     {\r
3340         // get the type of the PointerType (remove pointer and const)\r
3341         using pointee_t = typename std::remove_const<typename\r
3342                           std::remove_pointer<typename\r
3343                           std::remove_const<PointerType>::type>::type>::type;\r
3344         // make sure the type matches the allowed types\r
3345         static_assert(\r
3346             std::is_same<object_t, pointee_t>::value\r
3347             or std::is_same<array_t, pointee_t>::value\r
3348             or std::is_same<string_t, pointee_t>::value\r
3349             or std::is_same<boolean_t, pointee_t>::value\r
3350             or std::is_same<number_integer_t, pointee_t>::value\r
3351             or std::is_same<number_unsigned_t, pointee_t>::value\r
3352             or std::is_same<number_float_t, pointee_t>::value\r
3353             , "incompatible pointer type");\r
3354 \r
3355         // delegate the call to get_impl_ptr<>()\r
3356         return get_impl_ptr(static_cast<PointerType>(nullptr));\r
3357     }\r
3358 \r
3359     /*!\r
3360     @brief get a pointer value (implicit)\r
3361     @copydoc get_ptr()\r
3362     */\r
3363     template<typename PointerType, typename std::enable_if<\r
3364                  std::is_pointer<PointerType>::value and\r
3365                  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>\r
3366     constexpr const PointerType get_ptr() const noexcept\r
3367     {\r
3368         // get the type of the PointerType (remove pointer and const)\r
3369         using pointee_t = typename std::remove_const<typename\r
3370                           std::remove_pointer<typename\r
3371                           std::remove_const<PointerType>::type>::type>::type;\r
3372         // make sure the type matches the allowed types\r
3373         static_assert(\r
3374             std::is_same<object_t, pointee_t>::value\r
3375             or std::is_same<array_t, pointee_t>::value\r
3376             or std::is_same<string_t, pointee_t>::value\r
3377             or std::is_same<boolean_t, pointee_t>::value\r
3378             or std::is_same<number_integer_t, pointee_t>::value\r
3379             or std::is_same<number_unsigned_t, pointee_t>::value\r
3380             or std::is_same<number_float_t, pointee_t>::value\r
3381             , "incompatible pointer type");\r
3382 \r
3383         // delegate the call to get_impl_ptr<>() const\r
3384         return get_impl_ptr(static_cast<const PointerType>(nullptr));\r
3385     }\r
3386 \r
3387     /*!\r
3388     @brief get a reference value (implicit)\r
3389 \r
3390     Implicit reference access to the internally stored JSON value. No copies\r
3391     are made.\r
3392 \r
3393     @warning Writing data to the referee of the result yields an undefined\r
3394     state.\r
3395 \r
3396     @tparam ReferenceType reference type; must be a reference to @ref array_t,\r
3397     @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or\r
3398     @ref number_float_t. Enforced by static assertion.\r
3399 \r
3400     @return reference to the internally stored JSON value if the requested\r
3401     reference type @a ReferenceType fits to the JSON value; throws\r
3402     std::domain_error otherwise\r
3403 \r
3404     @throw std::domain_error in case passed type @a ReferenceType is\r
3405     incompatible with the stored JSON value\r
3406 \r
3407     @complexity Constant.\r
3408 \r
3409     @liveexample{The example shows several calls to `get_ref()`.,get_ref}\r
3410 \r
3411     @since version 1.1.0\r
3412     */\r
3413     template<typename ReferenceType, typename std::enable_if<\r
3414                  std::is_reference<ReferenceType>::value, int>::type = 0>\r
3415     ReferenceType get_ref()\r
3416     {\r
3417         // delegate call to get_ref_impl\r
3418         return get_ref_impl<ReferenceType>(*this);\r
3419     }\r
3420 \r
3421     /*!\r
3422     @brief get a reference value (implicit)\r
3423     @copydoc get_ref()\r
3424     */\r
3425     template<typename ReferenceType, typename std::enable_if<\r
3426                  std::is_reference<ReferenceType>::value and\r
3427                  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>\r
3428     ReferenceType get_ref() const\r
3429     {\r
3430         // delegate call to get_ref_impl\r
3431         return get_ref_impl<ReferenceType>(*this);\r
3432     }\r
3433 \r
3434     /*!\r
3435     @brief get a value (implicit)\r
3436 \r
3437     Implicit type conversion between the JSON value and a compatible value.\r
3438     The call is realized by calling @ref get() const.\r
3439 \r
3440     @tparam ValueType non-pointer type compatible to the JSON value, for\r
3441     instance `int` for JSON integer numbers, `bool` for JSON booleans, or\r
3442     `std::vector` types for JSON arrays. The character type of @ref string_t\r
3443     as well as an initializer list of this type is excluded to avoid\r
3444     ambiguities as these types implicitly convert to `std::string`.\r
3445 \r
3446     @return copy of the JSON value, converted to type @a ValueType\r
3447 \r
3448     @throw std::domain_error in case passed type @a ValueType is incompatible\r
3449     to JSON, thrown by @ref get() const\r
3450 \r
3451     @complexity Linear in the size of the JSON value.\r
3452 \r
3453     @liveexample{The example below shows several conversions from JSON values\r
3454     to other types. There a few things to note: (1) Floating-point numbers can\r
3455     be converted to integers\, (2) A JSON array can be converted to a standard\r
3456     `std::vector<short>`\, (3) A JSON object can be converted to C++\r
3457     associative containers such as `std::unordered_map<std::string\,\r
3458     json>`.,operator__ValueType}\r
3459 \r
3460     @since version 1.0.0\r
3461     */\r
3462     template < typename ValueType, typename std::enable_if <\r
3463                    not std::is_pointer<ValueType>::value and\r
3464                    not std::is_same<ValueType, typename string_t::value_type>::value\r
3465 #ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015\r
3466                    and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value\r
3467 #endif\r
3468                    , int >::type = 0 >\r
3469     operator ValueType() const\r
3470     {\r
3471         // delegate the call to get<>() const\r
3472         return get<ValueType>();\r
3473     }\r
3474 \r
3475     /// @}\r
3476 \r
3477 \r
3478     ////////////////////\r
3479     // element access //\r
3480     ////////////////////\r
3481 \r
3482     /// @name element access\r
3483     /// Access to the JSON value.\r
3484     /// @{\r
3485 \r
3486     /*!\r
3487     @brief access specified array element with bounds checking\r
3488 \r
3489     Returns a reference to the element at specified location @a idx, with\r
3490     bounds checking.\r
3491 \r
3492     @param[in] idx  index of the element to access\r
3493 \r
3494     @return reference to the element at index @a idx\r
3495 \r
3496     @throw std::domain_error if the JSON value is not an array; example:\r
3497     `"cannot use at() with string"`\r
3498     @throw std::out_of_range if the index @a idx is out of range of the array;\r
3499     that is, `idx >= size()`; example: `"array index 7 is out of range"`\r
3500 \r
3501     @complexity Constant.\r
3502 \r
3503     @liveexample{The example below shows how array elements can be read and\r
3504     written using `at()`.,at__size_type}\r
3505 \r
3506     @since version 1.0.0\r
3507     */\r
3508     reference at(size_type idx)\r
3509     {\r
3510         // at only works for arrays\r
3511         if (is_array())\r
3512         {\r
3513             JSON_TRY\r
3514             {\r
3515                 return m_value.array->at(idx);\r
3516             }\r
3517             JSON_CATCH (std::out_of_range&)\r
3518             {\r
3519                 // create better exception explanation\r
3520                 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));\r
3521             }\r
3522         }\r
3523         else\r
3524         {\r
3525             JSON_THROW(std::domain_error("cannot use at() with " + type_name()));\r
3526         }\r
3527     }\r
3528 \r
3529     /*!\r
3530     @brief access specified array element with bounds checking\r
3531 \r
3532     Returns a const reference to the element at specified location @a idx,\r
3533     with bounds checking.\r
3534 \r
3535     @param[in] idx  index of the element to access\r
3536 \r
3537     @return const reference to the element at index @a idx\r
3538 \r
3539     @throw std::domain_error if the JSON value is not an array; example:\r
3540     `"cannot use at() with string"`\r
3541     @throw std::out_of_range if the index @a idx is out of range of the array;\r
3542     that is, `idx >= size()`; example: `"array index 7 is out of range"`\r
3543 \r
3544     @complexity Constant.\r
3545 \r
3546     @liveexample{The example below shows how array elements can be read using\r
3547     `at()`.,at__size_type_const}\r
3548 \r
3549     @since version 1.0.0\r
3550     */\r
3551     const_reference at(size_type idx) const\r
3552     {\r
3553         // at only works for arrays\r
3554         if (is_array())\r
3555         {\r
3556             JSON_TRY\r
3557             {\r
3558                 return m_value.array->at(idx);\r
3559             }\r
3560             JSON_CATCH (std::out_of_range&)\r
3561             {\r
3562                 // create better exception explanation\r
3563                 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));\r
3564             }\r
3565         }\r
3566         else\r
3567         {\r
3568             JSON_THROW(std::domain_error("cannot use at() with " + type_name()));\r
3569         }\r
3570     }\r
3571 \r
3572     /*!\r
3573     @brief access specified object element with bounds checking\r
3574 \r
3575     Returns a reference to the element at with specified key @a key, with\r
3576     bounds checking.\r
3577 \r
3578     @param[in] key  key of the element to access\r
3579 \r
3580     @return reference to the element at key @a key\r
3581 \r
3582     @throw std::domain_error if the JSON value is not an object; example:\r
3583     `"cannot use at() with boolean"`\r
3584     @throw std::out_of_range if the key @a key is is not stored in the object;\r
3585     that is, `find(key) == end()`; example: `"key "the fast" not found"`\r
3586 \r
3587     @complexity Logarithmic in the size of the container.\r
3588 \r
3589     @liveexample{The example below shows how object elements can be read and\r
3590     written using `at()`.,at__object_t_key_type}\r
3591 \r
3592     @sa @ref operator[](const typename object_t::key_type&) for unchecked\r
3593     access by reference\r
3594     @sa @ref value() for access by value with a default value\r
3595 \r
3596     @since version 1.0.0\r
3597     */\r
3598     reference at(const typename object_t::key_type& key)\r
3599     {\r
3600         // at only works for objects\r
3601         if (is_object())\r
3602         {\r
3603             JSON_TRY\r
3604             {\r
3605                 return m_value.object->at(key);\r
3606             }\r
3607             JSON_CATCH (std::out_of_range&)\r
3608             {\r
3609                 // create better exception explanation\r
3610                 JSON_THROW(std::out_of_range("key '" + key + "' not found"));\r
3611             }\r
3612         }\r
3613         else\r
3614         {\r
3615             JSON_THROW(std::domain_error("cannot use at() with " + type_name()));\r
3616         }\r
3617     }\r
3618 \r
3619     /*!\r
3620     @brief access specified object element with bounds checking\r
3621 \r
3622     Returns a const reference to the element at with specified key @a key,\r
3623     with bounds checking.\r
3624 \r
3625     @param[in] key  key of the element to access\r
3626 \r
3627     @return const reference to the element at key @a key\r
3628 \r
3629     @throw std::domain_error if the JSON value is not an object; example:\r
3630     `"cannot use at() with boolean"`\r
3631     @throw std::out_of_range if the key @a key is is not stored in the object;\r
3632     that is, `find(key) == end()`; example: `"key "the fast" not found"`\r
3633 \r
3634     @complexity Logarithmic in the size of the container.\r
3635 \r
3636     @liveexample{The example below shows how object elements can be read using\r
3637     `at()`.,at__object_t_key_type_const}\r
3638 \r
3639     @sa @ref operator[](const typename object_t::key_type&) for unchecked\r
3640     access by reference\r
3641     @sa @ref value() for access by value with a default value\r
3642 \r
3643     @since version 1.0.0\r
3644     */\r
3645     const_reference at(const typename object_t::key_type& key) const\r
3646     {\r
3647         // at only works for objects\r
3648         if (is_object())\r
3649         {\r
3650             JSON_TRY\r
3651             {\r
3652                 return m_value.object->at(key);\r
3653             }\r
3654             JSON_CATCH (std::out_of_range&)\r
3655             {\r
3656                 // create better exception explanation\r
3657                 JSON_THROW(std::out_of_range("key '" + key + "' not found"));\r
3658             }\r
3659         }\r
3660         else\r
3661         {\r
3662             JSON_THROW(std::domain_error("cannot use at() with " + type_name()));\r
3663         }\r
3664     }\r
3665 \r
3666     /*!\r
3667     @brief access specified array element\r
3668 \r
3669     Returns a reference to the element at specified location @a idx.\r
3670 \r
3671     @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),\r
3672     then the array is silently filled up with `null` values to make `idx` a\r
3673     valid reference to the last stored element.\r
3674 \r
3675     @param[in] idx  index of the element to access\r
3676 \r
3677     @return reference to the element at index @a idx\r
3678 \r
3679     @throw std::domain_error if JSON is not an array or null; example:\r
3680     `"cannot use operator[] with string"`\r
3681 \r
3682     @complexity Constant if @a idx is in the range of the array. Otherwise\r
3683     linear in `idx - size()`.\r
3684 \r
3685     @liveexample{The example below shows how array elements can be read and\r
3686     written using `[]` operator. Note the addition of `null`\r
3687     values.,operatorarray__size_type}\r
3688 \r
3689     @since version 1.0.0\r
3690     */\r
3691     reference operator[](size_type idx)\r
3692     {\r
3693         // implicitly convert null value to an empty array\r
3694         if (is_null())\r
3695         {\r
3696             m_type = value_t::array;\r
3697             m_value.array = create<array_t>();\r
3698             assert_invariant();\r
3699         }\r
3700 \r
3701         // operator[] only works for arrays\r
3702         if (is_array())\r
3703         {\r
3704             // fill up array with null values if given idx is outside range\r
3705             if (idx >= m_value.array->size())\r
3706             {\r
3707                 m_value.array->insert(m_value.array->end(),\r
3708                                       idx - m_value.array->size() + 1,\r
3709                                       basic_json());\r
3710             }\r
3711 \r
3712             return m_value.array->operator[](idx);\r
3713         }\r
3714 \r
3715         JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));\r
3716     }\r
3717 \r
3718     /*!\r
3719     @brief access specified array element\r
3720 \r
3721     Returns a const reference to the element at specified location @a idx.\r
3722 \r
3723     @param[in] idx  index of the element to access\r
3724 \r
3725     @return const reference to the element at index @a idx\r
3726 \r
3727     @throw std::domain_error if JSON is not an array; example: `"cannot use\r
3728     operator[] with null"`\r
3729 \r
3730     @complexity Constant.\r
3731 \r
3732     @liveexample{The example below shows how array elements can be read using\r
3733     the `[]` operator.,operatorarray__size_type_const}\r
3734 \r
3735     @since version 1.0.0\r
3736     */\r
3737     const_reference operator[](size_type idx) const\r
3738     {\r
3739         // const operator[] only works for arrays\r
3740         if (is_array())\r
3741         {\r
3742             return m_value.array->operator[](idx);\r
3743         }\r
3744 \r
3745         JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));\r
3746     }\r
3747 \r
3748     /*!\r
3749     @brief access specified object element\r
3750 \r
3751     Returns a reference to the element at with specified key @a key.\r
3752 \r
3753     @note If @a key is not found in the object, then it is silently added to\r
3754     the object and filled with a `null` value to make `key` a valid reference.\r
3755     In case the value was `null` before, it is converted to an object.\r
3756 \r
3757     @param[in] key  key of the element to access\r
3758 \r
3759     @return reference to the element at key @a key\r
3760 \r
3761     @throw std::domain_error if JSON is not an object or null; example:\r
3762     `"cannot use operator[] with string"`\r
3763 \r
3764     @complexity Logarithmic in the size of the container.\r
3765 \r
3766     @liveexample{The example below shows how object elements can be read and\r
3767     written using the `[]` operator.,operatorarray__key_type}\r
3768 \r
3769     @sa @ref at(const typename object_t::key_type&) for access by reference\r
3770     with range checking\r
3771     @sa @ref value() for access by value with a default value\r
3772 \r
3773     @since version 1.0.0\r
3774     */\r
3775     reference operator[](const typename object_t::key_type& key)\r
3776     {\r
3777         // implicitly convert null value to an empty object\r
3778         if (is_null())\r
3779         {\r
3780             m_type = value_t::object;\r
3781             m_value.object = create<object_t>();\r
3782             assert_invariant();\r
3783         }\r
3784 \r
3785         // operator[] only works for objects\r
3786         if (is_object())\r
3787         {\r
3788             return m_value.object->operator[](key);\r
3789         }\r
3790 \r
3791         JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));\r
3792     }\r
3793 \r
3794     /*!\r
3795     @brief read-only access specified object element\r
3796 \r
3797     Returns a const reference to the element at with specified key @a key. No\r
3798     bounds checking is performed.\r
3799 \r
3800     @warning If the element with key @a key does not exist, the behavior is\r
3801     undefined.\r
3802 \r
3803     @param[in] key  key of the element to access\r
3804 \r
3805     @return const reference to the element at key @a key\r
3806 \r
3807     @pre The element with key @a key must exist. **This precondition is\r
3808          enforced with an assertion.**\r
3809 \r
3810     @throw std::domain_error if JSON is not an object; example: `"cannot use\r
3811     operator[] with null"`\r
3812 \r
3813     @complexity Logarithmic in the size of the container.\r
3814 \r
3815     @liveexample{The example below shows how object elements can be read using\r
3816     the `[]` operator.,operatorarray__key_type_const}\r
3817 \r
3818     @sa @ref at(const typename object_t::key_type&) for access by reference\r
3819     with range checking\r
3820     @sa @ref value() for access by value with a default value\r
3821 \r
3822     @since version 1.0.0\r
3823     */\r
3824     const_reference operator[](const typename object_t::key_type& key) const\r
3825     {\r
3826         // const operator[] only works for objects\r
3827         if (is_object())\r
3828         {\r
3829             assert(m_value.object->find(key) != m_value.object->end());\r
3830             return m_value.object->find(key)->second;\r
3831         }\r
3832 \r
3833         JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));\r
3834     }\r
3835 \r
3836     /*!\r
3837     @brief access specified object element\r
3838 \r
3839     Returns a reference to the element at with specified key @a key.\r
3840 \r
3841     @note If @a key is not found in the object, then it is silently added to\r
3842     the object and filled with a `null` value to make `key` a valid reference.\r
3843     In case the value was `null` before, it is converted to an object.\r
3844 \r
3845     @param[in] key  key of the element to access\r
3846 \r
3847     @return reference to the element at key @a key\r
3848 \r
3849     @throw std::domain_error if JSON is not an object or null; example:\r
3850     `"cannot use operator[] with string"`\r
3851 \r
3852     @complexity Logarithmic in the size of the container.\r
3853 \r
3854     @liveexample{The example below shows how object elements can be read and\r
3855     written using the `[]` operator.,operatorarray__key_type}\r
3856 \r
3857     @sa @ref at(const typename object_t::key_type&) for access by reference\r
3858     with range checking\r
3859     @sa @ref value() for access by value with a default value\r
3860 \r
3861     @since version 1.0.0\r
3862     */\r
3863     template<typename T, std::size_t n>\r
3864     reference operator[](T * (&key)[n])\r
3865     {\r
3866         return operator[](static_cast<const T>(key));\r
3867     }\r
3868 \r
3869     /*!\r
3870     @brief read-only access specified object element\r
3871 \r
3872     Returns a const reference to the element at with specified key @a key. No\r
3873     bounds checking is performed.\r
3874 \r
3875     @warning If the element with key @a key does not exist, the behavior is\r
3876     undefined.\r
3877 \r
3878     @note This function is required for compatibility reasons with Clang.\r
3879 \r
3880     @param[in] key  key of the element to access\r
3881 \r
3882     @return const reference to the element at key @a key\r
3883 \r
3884     @throw std::domain_error if JSON is not an object; example: `"cannot use\r
3885     operator[] with null"`\r
3886 \r
3887     @complexity Logarithmic in the size of the container.\r
3888 \r
3889     @liveexample{The example below shows how object elements can be read using\r
3890     the `[]` operator.,operatorarray__key_type_const}\r
3891 \r
3892     @sa @ref at(const typename object_t::key_type&) for access by reference\r
3893     with range checking\r
3894     @sa @ref value() for access by value with a default value\r
3895 \r
3896     @since version 1.0.0\r
3897     */\r
3898     template<typename T, std::size_t n>\r
3899     const_reference operator[](T * (&key)[n]) const\r
3900     {\r
3901         return operator[](static_cast<const T>(key));\r
3902     }\r
3903 \r
3904     /*!\r
3905     @brief access specified object element\r
3906 \r
3907     Returns a reference to the element at with specified key @a key.\r
3908 \r
3909     @note If @a key is not found in the object, then it is silently added to\r
3910     the object and filled with a `null` value to make `key` a valid reference.\r
3911     In case the value was `null` before, it is converted to an object.\r
3912 \r
3913     @param[in] key  key of the element to access\r
3914 \r
3915     @return reference to the element at key @a key\r
3916 \r
3917     @throw std::domain_error if JSON is not an object or null; example:\r
3918     `"cannot use operator[] with string"`\r
3919 \r
3920     @complexity Logarithmic in the size of the container.\r
3921 \r
3922     @liveexample{The example below shows how object elements can be read and\r
3923     written using the `[]` operator.,operatorarray__key_type}\r
3924 \r
3925     @sa @ref at(const typename object_t::key_type&) for access by reference\r
3926     with range checking\r
3927     @sa @ref value() for access by value with a default value\r
3928 \r
3929     @since version 1.1.0\r
3930     */\r
3931     template<typename T>\r
3932     reference operator[](T* key)\r
3933     {\r
3934         // implicitly convert null to object\r
3935         if (is_null())\r
3936         {\r
3937             m_type = value_t::object;\r
3938             m_value = value_t::object;\r
3939             assert_invariant();\r
3940         }\r
3941 \r
3942         // at only works for objects\r
3943         if (is_object())\r
3944         {\r
3945             return m_value.object->operator[](key);\r
3946         }\r
3947 \r
3948         JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));\r
3949     }\r
3950 \r
3951     /*!\r
3952     @brief read-only access specified object element\r
3953 \r
3954     Returns a const reference to the element at with specified key @a key. No\r
3955     bounds checking is performed.\r
3956 \r
3957     @warning If the element with key @a key does not exist, the behavior is\r
3958     undefined.\r
3959 \r
3960     @param[in] key  key of the element to access\r
3961 \r
3962     @return const reference to the element at key @a key\r
3963 \r
3964     @pre The element with key @a key must exist. **This precondition is\r
3965          enforced with an assertion.**\r
3966 \r
3967     @throw std::domain_error if JSON is not an object; example: `"cannot use\r
3968     operator[] with null"`\r
3969 \r
3970     @complexity Logarithmic in the size of the container.\r
3971 \r
3972     @liveexample{The example below shows how object elements can be read using\r
3973     the `[]` operator.,operatorarray__key_type_const}\r
3974 \r
3975     @sa @ref at(const typename object_t::key_type&) for access by reference\r
3976     with range checking\r
3977     @sa @ref value() for access by value with a default value\r
3978 \r
3979     @since version 1.1.0\r
3980     */\r
3981     template<typename T>\r
3982     const_reference operator[](T* key) const\r
3983     {\r
3984         // at only works for objects\r
3985         if (is_object())\r
3986         {\r
3987             assert(m_value.object->find(key) != m_value.object->end());\r
3988             return m_value.object->find(key)->second;\r
3989         }\r
3990 \r
3991         JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));\r
3992     }\r
3993 \r
3994     /*!\r
3995     @brief access specified object element with default value\r
3996 \r
3997     Returns either a copy of an object's element at the specified key @a key\r
3998     or a given default value if no element with key @a key exists.\r
3999 \r
4000     The function is basically equivalent to executing\r
4001     @code {.cpp}\r
4002     try {\r
4003         return at(key);\r
4004     } catch(std::out_of_range) {\r
4005         return default_value;\r
4006     }\r
4007     @endcode\r
4008 \r
4009     @note Unlike @ref at(const typename object_t::key_type&), this function\r
4010     does not throw if the given key @a key was not found.\r
4011 \r
4012     @note Unlike @ref operator[](const typename object_t::key_type& key), this\r
4013     function does not implicitly add an element to the position defined by @a\r
4014     key. This function is furthermore also applicable to const objects.\r
4015 \r
4016     @param[in] key  key of the element to access\r
4017     @param[in] default_value  the value to return if @a key is not found\r
4018 \r
4019     @tparam ValueType type compatible to JSON values, for instance `int` for\r
4020     JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\r
4021     JSON arrays. Note the type of the expected value at @a key and the default\r
4022     value @a default_value must be compatible.\r
4023 \r
4024     @return copy of the element at key @a key or @a default_value if @a key\r
4025     is not found\r
4026 \r
4027     @throw std::domain_error if JSON is not an object; example: `"cannot use\r
4028     value() with null"`\r
4029 \r
4030     @complexity Logarithmic in the size of the container.\r
4031 \r
4032     @liveexample{The example below shows how object elements can be queried\r
4033     with a default value.,basic_json__value}\r
4034 \r
4035     @sa @ref at(const typename object_t::key_type&) for access by reference\r
4036     with range checking\r
4037     @sa @ref operator[](const typename object_t::key_type&) for unchecked\r
4038     access by reference\r
4039 \r
4040     @since version 1.0.0\r
4041     */\r
4042     template<class ValueType, typename std::enable_if<\r
4043                  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>\r
4044     ValueType value(const typename object_t::key_type& key, ValueType default_value) const\r
4045     {\r
4046         // at only works for objects\r
4047         if (is_object())\r
4048         {\r
4049             // if key is found, return value and given default value otherwise\r
4050             const auto it = find(key);\r
4051             if (it != end())\r
4052             {\r
4053                 return *it;\r
4054             }\r
4055 \r
4056             return default_value;\r
4057         }\r
4058         else\r
4059         {\r
4060             JSON_THROW(std::domain_error("cannot use value() with " + type_name()));\r
4061         }\r
4062     }\r
4063 \r
4064     /*!\r
4065     @brief overload for a default value of type const char*\r
4066     @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const\r
4067     */\r
4068     string_t value(const typename object_t::key_type& key, const char* default_value) const\r
4069     {\r
4070         return value(key, string_t(default_value));\r
4071     }\r
4072 \r
4073     /*!\r
4074     @brief access specified object element via JSON Pointer with default value\r
4075 \r
4076     Returns either a copy of an object's element at the specified key @a key\r
4077     or a given default value if no element with key @a key exists.\r
4078 \r
4079     The function is basically equivalent to executing\r
4080     @code {.cpp}\r
4081     try {\r
4082         return at(ptr);\r
4083     } catch(std::out_of_range) {\r
4084         return default_value;\r
4085     }\r
4086     @endcode\r
4087 \r
4088     @note Unlike @ref at(const json_pointer&), this function does not throw\r
4089     if the given key @a key was not found.\r
4090 \r
4091     @param[in] ptr  a JSON pointer to the element to access\r
4092     @param[in] default_value  the value to return if @a ptr found no value\r
4093 \r
4094     @tparam ValueType type compatible to JSON values, for instance `int` for\r
4095     JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\r
4096     JSON arrays. Note the type of the expected value at @a key and the default\r
4097     value @a default_value must be compatible.\r
4098 \r
4099     @return copy of the element at key @a key or @a default_value if @a key\r
4100     is not found\r
4101 \r
4102     @throw std::domain_error if JSON is not an object; example: `"cannot use\r
4103     value() with null"`\r
4104 \r
4105     @complexity Logarithmic in the size of the container.\r
4106 \r
4107     @liveexample{The example below shows how object elements can be queried\r
4108     with a default value.,basic_json__value_ptr}\r
4109 \r
4110     @sa @ref operator[](const json_pointer&) for unchecked access by reference\r
4111 \r
4112     @since version 2.0.2\r
4113     */\r
4114     template<class ValueType, typename std::enable_if<\r
4115                  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>\r
4116     ValueType value(const json_pointer& ptr, ValueType default_value) const\r
4117     {\r
4118         // at only works for objects\r
4119         if (is_object())\r
4120         {\r
4121             // if pointer resolves a value, return it or use default value\r
4122             JSON_TRY\r
4123             {\r
4124                 return ptr.get_checked(this);\r
4125             }\r
4126             JSON_CATCH (std::out_of_range&)\r
4127             {\r
4128                 return default_value;\r
4129             }\r
4130         }\r
4131 \r
4132         JSON_THROW(std::domain_error("cannot use value() with " + type_name()));\r
4133     }\r
4134 \r
4135     /*!\r
4136     @brief overload for a default value of type const char*\r
4137     @copydoc basic_json::value(const json_pointer&, ValueType) const\r
4138     */\r
4139     string_t value(const json_pointer& ptr, const char* default_value) const\r
4140     {\r
4141         return value(ptr, string_t(default_value));\r
4142     }\r
4143 \r
4144     /*!\r
4145     @brief access the first element\r
4146 \r
4147     Returns a reference to the first element in the container. For a JSON\r
4148     container `c`, the expression `c.front()` is equivalent to `*c.begin()`.\r
4149 \r
4150     @return In case of a structured type (array or object), a reference to the\r
4151     first element is returned. In case of number, string, or boolean values, a\r
4152     reference to the value is returned.\r
4153 \r
4154     @complexity Constant.\r
4155 \r
4156     @pre The JSON value must not be `null` (would throw `std::out_of_range`)\r
4157     or an empty array or object (undefined behavior, **guarded by\r
4158     assertions**).\r
4159     @post The JSON value remains unchanged.\r
4160 \r
4161     @throw std::out_of_range when called on `null` value\r
4162 \r
4163     @liveexample{The following code shows an example for `front()`.,front}\r
4164 \r
4165     @sa @ref back() -- access the last element\r
4166 \r
4167     @since version 1.0.0\r
4168     */\r
4169     reference front()\r
4170     {\r
4171         return *begin();\r
4172     }\r
4173 \r
4174     /*!\r
4175     @copydoc basic_json::front()\r
4176     */\r
4177     const_reference front() const\r
4178     {\r
4179         return *cbegin();\r
4180     }\r
4181 \r
4182     /*!\r
4183     @brief access the last element\r
4184 \r
4185     Returns a reference to the last element in the container. For a JSON\r
4186     container `c`, the expression `c.back()` is equivalent to\r
4187     @code {.cpp}\r
4188     auto tmp = c.end();\r
4189     --tmp;\r
4190     return *tmp;\r
4191     @endcode\r
4192 \r
4193     @return In case of a structured type (array or object), a reference to the\r
4194     last element is returned. In case of number, string, or boolean values, a\r
4195     reference to the value is returned.\r
4196 \r
4197     @complexity Constant.\r
4198 \r
4199     @pre The JSON value must not be `null` (would throw `std::out_of_range`)\r
4200     or an empty array or object (undefined behavior, **guarded by\r
4201     assertions**).\r
4202     @post The JSON value remains unchanged.\r
4203 \r
4204     @throw std::out_of_range when called on `null` value.\r
4205 \r
4206     @liveexample{The following code shows an example for `back()`.,back}\r
4207 \r
4208     @sa @ref front() -- access the first element\r
4209 \r
4210     @since version 1.0.0\r
4211     */\r
4212     reference back()\r
4213     {\r
4214         auto tmp = end();\r
4215         --tmp;\r
4216         return *tmp;\r
4217     }\r
4218 \r
4219     /*!\r
4220     @copydoc basic_json::back()\r
4221     */\r
4222     const_reference back() const\r
4223     {\r
4224         auto tmp = cend();\r
4225         --tmp;\r
4226         return *tmp;\r
4227     }\r
4228 \r
4229     /*!\r
4230     @brief remove element given an iterator\r
4231 \r
4232     Removes the element specified by iterator @a pos. The iterator @a pos must\r
4233     be valid and dereferenceable. Thus the `end()` iterator (which is valid,\r
4234     but is not dereferenceable) cannot be used as a value for @a pos.\r
4235 \r
4236     If called on a primitive type other than `null`, the resulting JSON value\r
4237     will be `null`.\r
4238 \r
4239     @param[in] pos iterator to the element to remove\r
4240     @return Iterator following the last removed element. If the iterator @a\r
4241     pos refers to the last element, the `end()` iterator is returned.\r
4242 \r
4243     @tparam IteratorType an @ref iterator or @ref const_iterator\r
4244 \r
4245     @post Invalidates iterators and references at or after the point of the\r
4246     erase, including the `end()` iterator.\r
4247 \r
4248     @throw std::domain_error if called on a `null` value; example: `"cannot\r
4249     use erase() with null"`\r
4250     @throw std::domain_error if called on an iterator which does not belong to\r
4251     the current JSON value; example: `"iterator does not fit current value"`\r
4252     @throw std::out_of_range if called on a primitive type with invalid\r
4253     iterator (i.e., any iterator which is not `begin()`); example: `"iterator\r
4254     out of range"`\r
4255 \r
4256     @complexity The complexity depends on the type:\r
4257     - objects: amortized constant\r
4258     - arrays: linear in distance between @a pos and the end of the container\r
4259     - strings: linear in the length of the string\r
4260     - other types: constant\r
4261 \r
4262     @liveexample{The example shows the result of `erase()` for different JSON\r
4263     types.,erase__IteratorType}\r
4264 \r
4265     @sa @ref erase(IteratorType, IteratorType) -- removes the elements in\r
4266     the given range\r
4267     @sa @ref erase(const typename object_t::key_type&) -- removes the element\r
4268     from an object at the given key\r
4269     @sa @ref erase(const size_type) -- removes the element from an array at\r
4270     the given index\r
4271 \r
4272     @since version 1.0.0\r
4273     */\r
4274     template<class IteratorType, typename std::enable_if<\r
4275                  std::is_same<IteratorType, typename basic_json_t::iterator>::value or\r
4276                  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type\r
4277              = 0>\r
4278     IteratorType erase(IteratorType pos)\r
4279     {\r
4280         // make sure iterator fits the current value\r
4281         if (this != pos.m_object)\r
4282         {\r
4283             JSON_THROW(std::domain_error("iterator does not fit current value"));\r
4284         }\r
4285 \r
4286         IteratorType result = end();\r
4287 \r
4288         switch (m_type)\r
4289         {\r
4290             case value_t::boolean:\r
4291             case value_t::number_float:\r
4292             case value_t::number_integer:\r
4293             case value_t::number_unsigned:\r
4294             case value_t::string:\r
4295             {\r
4296                 if (not pos.m_it.primitive_iterator.is_begin())\r
4297                 {\r
4298                     JSON_THROW(std::out_of_range("iterator out of range"));\r
4299                 }\r
4300 \r
4301                 if (is_string())\r
4302                 {\r
4303                     AllocatorType<string_t> alloc;\r
4304                     alloc.destroy(m_value.string);\r
4305                     alloc.deallocate(m_value.string, 1);\r
4306                     m_value.string = nullptr;\r
4307                 }\r
4308 \r
4309                 m_type = value_t::null;\r
4310                 assert_invariant();\r
4311                 break;\r
4312             }\r
4313 \r
4314             case value_t::object:\r
4315             {\r
4316                 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);\r
4317                 break;\r
4318             }\r
4319 \r
4320             case value_t::array:\r
4321             {\r
4322                 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);\r
4323                 break;\r
4324             }\r
4325 \r
4326             default:\r
4327             {\r
4328                 JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));\r
4329             }\r
4330         }\r
4331 \r
4332         return result;\r
4333     }\r
4334 \r
4335     /*!\r
4336     @brief remove elements given an iterator range\r
4337 \r
4338     Removes the element specified by the range `[first; last)`. The iterator\r
4339     @a first does not need to be dereferenceable if `first == last`: erasing\r
4340     an empty range is a no-op.\r
4341 \r
4342     If called on a primitive type other than `null`, the resulting JSON value\r
4343     will be `null`.\r
4344 \r
4345     @param[in] first iterator to the beginning of the range to remove\r
4346     @param[in] last iterator past the end of the range to remove\r
4347     @return Iterator following the last removed element. If the iterator @a\r
4348     second refers to the last element, the `end()` iterator is returned.\r
4349 \r
4350     @tparam IteratorType an @ref iterator or @ref const_iterator\r
4351 \r
4352     @post Invalidates iterators and references at or after the point of the\r
4353     erase, including the `end()` iterator.\r
4354 \r
4355     @throw std::domain_error if called on a `null` value; example: `"cannot\r
4356     use erase() with null"`\r
4357     @throw std::domain_error if called on iterators which does not belong to\r
4358     the current JSON value; example: `"iterators do not fit current value"`\r
4359     @throw std::out_of_range if called on a primitive type with invalid\r
4360     iterators (i.e., if `first != begin()` and `last != end()`); example:\r
4361     `"iterators out of range"`\r
4362 \r
4363     @complexity The complexity depends on the type:\r
4364     - objects: `log(size()) + std::distance(first, last)`\r
4365     - arrays: linear in the distance between @a first and @a last, plus linear\r
4366       in the distance between @a last and end of the container\r
4367     - strings: linear in the length of the string\r
4368     - other types: constant\r
4369 \r
4370     @liveexample{The example shows the result of `erase()` for different JSON\r
4371     types.,erase__IteratorType_IteratorType}\r
4372 \r
4373     @sa @ref erase(IteratorType) -- removes the element at a given position\r
4374     @sa @ref erase(const typename object_t::key_type&) -- removes the element\r
4375     from an object at the given key\r
4376     @sa @ref erase(const size_type) -- removes the element from an array at\r
4377     the given index\r
4378 \r
4379     @since version 1.0.0\r
4380     */\r
4381     template<class IteratorType, typename std::enable_if<\r
4382                  std::is_same<IteratorType, typename basic_json_t::iterator>::value or\r
4383                  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type\r
4384              = 0>\r
4385     IteratorType erase(IteratorType first, IteratorType last)\r
4386     {\r
4387         // make sure iterator fits the current value\r
4388         if (this != first.m_object or this != last.m_object)\r
4389         {\r
4390             JSON_THROW(std::domain_error("iterators do not fit current value"));\r
4391         }\r
4392 \r
4393         IteratorType result = end();\r
4394 \r
4395         switch (m_type)\r
4396         {\r
4397             case value_t::boolean:\r
4398             case value_t::number_float:\r
4399             case value_t::number_integer:\r
4400             case value_t::number_unsigned:\r
4401             case value_t::string:\r
4402             {\r
4403                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())\r
4404                 {\r
4405                     JSON_THROW(std::out_of_range("iterators out of range"));\r
4406                 }\r
4407 \r
4408                 if (is_string())\r
4409                 {\r
4410                     AllocatorType<string_t> alloc;\r
4411                     alloc.destroy(m_value.string);\r
4412                     alloc.deallocate(m_value.string, 1);\r
4413                     m_value.string = nullptr;\r
4414                 }\r
4415 \r
4416                 m_type = value_t::null;\r
4417                 assert_invariant();\r
4418                 break;\r
4419             }\r
4420 \r
4421             case value_t::object:\r
4422             {\r
4423                 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,\r
4424                                               last.m_it.object_iterator);\r
4425                 break;\r
4426             }\r
4427 \r
4428             case value_t::array:\r
4429             {\r
4430                 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,\r
4431                                              last.m_it.array_iterator);\r
4432                 break;\r
4433             }\r
4434 \r
4435             default:\r
4436             {\r
4437                 JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));\r
4438             }\r
4439         }\r
4440 \r
4441         return result;\r
4442     }\r
4443 \r
4444     /*!\r
4445     @brief remove element from a JSON object given a key\r
4446 \r
4447     Removes elements from a JSON object with the key value @a key.\r
4448 \r
4449     @param[in] key value of the elements to remove\r
4450 \r
4451     @return Number of elements removed. If @a ObjectType is the default\r
4452     `std::map` type, the return value will always be `0` (@a key was not\r
4453     found) or `1` (@a key was found).\r
4454 \r
4455     @post References and iterators to the erased elements are invalidated.\r
4456     Other references and iterators are not affected.\r
4457 \r
4458     @throw std::domain_error when called on a type other than JSON object;\r
4459     example: `"cannot use erase() with null"`\r
4460 \r
4461     @complexity `log(size()) + count(key)`\r
4462 \r
4463     @liveexample{The example shows the effect of `erase()`.,erase__key_type}\r
4464 \r
4465     @sa @ref erase(IteratorType) -- removes the element at a given position\r
4466     @sa @ref erase(IteratorType, IteratorType) -- removes the elements in\r
4467     the given range\r
4468     @sa @ref erase(const size_type) -- removes the element from an array at\r
4469     the given index\r
4470 \r
4471     @since version 1.0.0\r
4472     */\r
4473     size_type erase(const typename object_t::key_type& key)\r
4474     {\r
4475         // this erase only works for objects\r
4476         if (is_object())\r
4477         {\r
4478             return m_value.object->erase(key);\r
4479         }\r
4480 \r
4481         JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));\r
4482     }\r
4483 \r
4484     /*!\r
4485     @brief remove element from a JSON array given an index\r
4486 \r
4487     Removes element from a JSON array at the index @a idx.\r
4488 \r
4489     @param[in] idx index of the element to remove\r
4490 \r
4491     @throw std::domain_error when called on a type other than JSON array;\r
4492     example: `"cannot use erase() with null"`\r
4493     @throw std::out_of_range when `idx >= size()`; example: `"array index 17\r
4494     is out of range"`\r
4495 \r
4496     @complexity Linear in distance between @a idx and the end of the container.\r
4497 \r
4498     @liveexample{The example shows the effect of `erase()`.,erase__size_type}\r
4499 \r
4500     @sa @ref erase(IteratorType) -- removes the element at a given position\r
4501     @sa @ref erase(IteratorType, IteratorType) -- removes the elements in\r
4502     the given range\r
4503     @sa @ref erase(const typename object_t::key_type&) -- removes the element\r
4504     from an object at the given key\r
4505 \r
4506     @since version 1.0.0\r
4507     */\r
4508     void erase(const size_type idx)\r
4509     {\r
4510         // this erase only works for arrays\r
4511         if (is_array())\r
4512         {\r
4513             if (idx >= size())\r
4514             {\r
4515                 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));\r
4516             }\r
4517 \r
4518             m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));\r
4519         }\r
4520         else\r
4521         {\r
4522             JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));\r
4523         }\r
4524     }\r
4525 \r
4526     /// @}\r
4527 \r
4528 \r
4529     ////////////\r
4530     // lookup //\r
4531     ////////////\r
4532 \r
4533     /// @name lookup\r
4534     /// @{\r
4535 \r
4536     /*!\r
4537     @brief find an element in a JSON object\r
4538 \r
4539     Finds an element in a JSON object with key equivalent to @a key. If the\r
4540     element is not found or the JSON value is not an object, end() is\r
4541     returned.\r
4542 \r
4543     @note This method always returns @ref end() when executed on a JSON type\r
4544           that is not an object.\r
4545 \r
4546     @param[in] key key value of the element to search for\r
4547 \r
4548     @return Iterator to an element with key equivalent to @a key. If no such\r
4549     element is found or the JSON value is not an object, past-the-end (see\r
4550     @ref end()) iterator is returned.\r
4551 \r
4552     @complexity Logarithmic in the size of the JSON object.\r
4553 \r
4554     @liveexample{The example shows how `find()` is used.,find__key_type}\r
4555 \r
4556     @since version 1.0.0\r
4557     */\r
4558     iterator find(typename object_t::key_type key)\r
4559     {\r
4560         auto result = end();\r
4561 \r
4562         if (is_object())\r
4563         {\r
4564             result.m_it.object_iterator = m_value.object->find(key);\r
4565         }\r
4566 \r
4567         return result;\r
4568     }\r
4569 \r
4570     /*!\r
4571     @brief find an element in a JSON object\r
4572     @copydoc find(typename object_t::key_type)\r
4573     */\r
4574     const_iterator find(typename object_t::key_type key) const\r
4575     {\r
4576         auto result = cend();\r
4577 \r
4578         if (is_object())\r
4579         {\r
4580             result.m_it.object_iterator = m_value.object->find(key);\r
4581         }\r
4582 \r
4583         return result;\r
4584     }\r
4585 \r
4586     /*!\r
4587     @brief returns the number of occurrences of a key in a JSON object\r
4588 \r
4589     Returns the number of elements with key @a key. If ObjectType is the\r
4590     default `std::map` type, the return value will always be `0` (@a key was\r
4591     not found) or `1` (@a key was found).\r
4592 \r
4593     @note This method always returns `0` when executed on a JSON type that is\r
4594           not an object.\r
4595 \r
4596     @param[in] key key value of the element to count\r
4597 \r
4598     @return Number of elements with key @a key. If the JSON value is not an\r
4599     object, the return value will be `0`.\r
4600 \r
4601     @complexity Logarithmic in the size of the JSON object.\r
4602 \r
4603     @liveexample{The example shows how `count()` is used.,count}\r
4604 \r
4605     @since version 1.0.0\r
4606     */\r
4607     size_type count(typename object_t::key_type key) const\r
4608     {\r
4609         // return 0 for all nonobject types\r
4610         return is_object() ? m_value.object->count(key) : 0;\r
4611     }\r
4612 \r
4613     /// @}\r
4614 \r
4615 \r
4616     ///////////////\r
4617     // iterators //\r
4618     ///////////////\r
4619 \r
4620     /// @name iterators\r
4621     /// @{\r
4622 \r
4623     /*!\r
4624     @brief returns an iterator to the first element\r
4625 \r
4626     Returns an iterator to the first element.\r
4627 \r
4628     @image html range-begin-end.svg "Illustration from cppreference.com"\r
4629 \r
4630     @return iterator to the first element\r
4631 \r
4632     @complexity Constant.\r
4633 \r
4634     @requirement This function helps `basic_json` satisfying the\r
4635     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
4636     requirements:\r
4637     - The complexity is constant.\r
4638 \r
4639     @liveexample{The following code shows an example for `begin()`.,begin}\r
4640 \r
4641     @sa @ref cbegin() -- returns a const iterator to the beginning\r
4642     @sa @ref end() -- returns an iterator to the end\r
4643     @sa @ref cend() -- returns a const iterator to the end\r
4644 \r
4645     @since version 1.0.0\r
4646     */\r
4647     iterator begin() noexcept\r
4648     {\r
4649         iterator result(this);\r
4650         result.set_begin();\r
4651         return result;\r
4652     }\r
4653 \r
4654     /*!\r
4655     @copydoc basic_json::cbegin()\r
4656     */\r
4657     const_iterator begin() const noexcept\r
4658     {\r
4659         return cbegin();\r
4660     }\r
4661 \r
4662     /*!\r
4663     @brief returns a const iterator to the first element\r
4664 \r
4665     Returns a const iterator to the first element.\r
4666 \r
4667     @image html range-begin-end.svg "Illustration from cppreference.com"\r
4668 \r
4669     @return const iterator to the first element\r
4670 \r
4671     @complexity Constant.\r
4672 \r
4673     @requirement This function helps `basic_json` satisfying the\r
4674     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
4675     requirements:\r
4676     - The complexity is constant.\r
4677     - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.\r
4678 \r
4679     @liveexample{The following code shows an example for `cbegin()`.,cbegin}\r
4680 \r
4681     @sa @ref begin() -- returns an iterator to the beginning\r
4682     @sa @ref end() -- returns an iterator to the end\r
4683     @sa @ref cend() -- returns a const iterator to the end\r
4684 \r
4685     @since version 1.0.0\r
4686     */\r
4687     const_iterator cbegin() const noexcept\r
4688     {\r
4689         const_iterator result(this);\r
4690         result.set_begin();\r
4691         return result;\r
4692     }\r
4693 \r
4694     /*!\r
4695     @brief returns an iterator to one past the last element\r
4696 \r
4697     Returns an iterator to one past the last element.\r
4698 \r
4699     @image html range-begin-end.svg "Illustration from cppreference.com"\r
4700 \r
4701     @return iterator one past the last element\r
4702 \r
4703     @complexity Constant.\r
4704 \r
4705     @requirement This function helps `basic_json` satisfying the\r
4706     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
4707     requirements:\r
4708     - The complexity is constant.\r
4709 \r
4710     @liveexample{The following code shows an example for `end()`.,end}\r
4711 \r
4712     @sa @ref cend() -- returns a const iterator to the end\r
4713     @sa @ref begin() -- returns an iterator to the beginning\r
4714     @sa @ref cbegin() -- returns a const iterator to the beginning\r
4715 \r
4716     @since version 1.0.0\r
4717     */\r
4718     iterator end() noexcept\r
4719     {\r
4720         iterator result(this);\r
4721         result.set_end();\r
4722         return result;\r
4723     }\r
4724 \r
4725     /*!\r
4726     @copydoc basic_json::cend()\r
4727     */\r
4728     const_iterator end() const noexcept\r
4729     {\r
4730         return cend();\r
4731     }\r
4732 \r
4733     /*!\r
4734     @brief returns a const iterator to one past the last element\r
4735 \r
4736     Returns a const iterator to one past the last element.\r
4737 \r
4738     @image html range-begin-end.svg "Illustration from cppreference.com"\r
4739 \r
4740     @return const iterator one past the last element\r
4741 \r
4742     @complexity Constant.\r
4743 \r
4744     @requirement This function helps `basic_json` satisfying the\r
4745     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
4746     requirements:\r
4747     - The complexity is constant.\r
4748     - Has the semantics of `const_cast<const basic_json&>(*this).end()`.\r
4749 \r
4750     @liveexample{The following code shows an example for `cend()`.,cend}\r
4751 \r
4752     @sa @ref end() -- returns an iterator to the end\r
4753     @sa @ref begin() -- returns an iterator to the beginning\r
4754     @sa @ref cbegin() -- returns a const iterator to the beginning\r
4755 \r
4756     @since version 1.0.0\r
4757     */\r
4758     const_iterator cend() const noexcept\r
4759     {\r
4760         const_iterator result(this);\r
4761         result.set_end();\r
4762         return result;\r
4763     }\r
4764 \r
4765     /*!\r
4766     @brief returns an iterator to the reverse-beginning\r
4767 \r
4768     Returns an iterator to the reverse-beginning; that is, the last element.\r
4769 \r
4770     @image html range-rbegin-rend.svg "Illustration from cppreference.com"\r
4771 \r
4772     @complexity Constant.\r
4773 \r
4774     @requirement This function helps `basic_json` satisfying the\r
4775     [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\r
4776     requirements:\r
4777     - The complexity is constant.\r
4778     - Has the semantics of `reverse_iterator(end())`.\r
4779 \r
4780     @liveexample{The following code shows an example for `rbegin()`.,rbegin}\r
4781 \r
4782     @sa @ref crbegin() -- returns a const reverse iterator to the beginning\r
4783     @sa @ref rend() -- returns a reverse iterator to the end\r
4784     @sa @ref crend() -- returns a const reverse iterator to the end\r
4785 \r
4786     @since version 1.0.0\r
4787     */\r
4788     reverse_iterator rbegin() noexcept\r
4789     {\r
4790         return reverse_iterator(end());\r
4791     }\r
4792 \r
4793     /*!\r
4794     @copydoc basic_json::crbegin()\r
4795     */\r
4796     const_reverse_iterator rbegin() const noexcept\r
4797     {\r
4798         return crbegin();\r
4799     }\r
4800 \r
4801     /*!\r
4802     @brief returns an iterator to the reverse-end\r
4803 \r
4804     Returns an iterator to the reverse-end; that is, one before the first\r
4805     element.\r
4806 \r
4807     @image html range-rbegin-rend.svg "Illustration from cppreference.com"\r
4808 \r
4809     @complexity Constant.\r
4810 \r
4811     @requirement This function helps `basic_json` satisfying the\r
4812     [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\r
4813     requirements:\r
4814     - The complexity is constant.\r
4815     - Has the semantics of `reverse_iterator(begin())`.\r
4816 \r
4817     @liveexample{The following code shows an example for `rend()`.,rend}\r
4818 \r
4819     @sa @ref crend() -- returns a const reverse iterator to the end\r
4820     @sa @ref rbegin() -- returns a reverse iterator to the beginning\r
4821     @sa @ref crbegin() -- returns a const reverse iterator to the beginning\r
4822 \r
4823     @since version 1.0.0\r
4824     */\r
4825     reverse_iterator rend() noexcept\r
4826     {\r
4827         return reverse_iterator(begin());\r
4828     }\r
4829 \r
4830     /*!\r
4831     @copydoc basic_json::crend()\r
4832     */\r
4833     const_reverse_iterator rend() const noexcept\r
4834     {\r
4835         return crend();\r
4836     }\r
4837 \r
4838     /*!\r
4839     @brief returns a const reverse iterator to the last element\r
4840 \r
4841     Returns a const iterator to the reverse-beginning; that is, the last\r
4842     element.\r
4843 \r
4844     @image html range-rbegin-rend.svg "Illustration from cppreference.com"\r
4845 \r
4846     @complexity Constant.\r
4847 \r
4848     @requirement This function helps `basic_json` satisfying the\r
4849     [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\r
4850     requirements:\r
4851     - The complexity is constant.\r
4852     - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.\r
4853 \r
4854     @liveexample{The following code shows an example for `crbegin()`.,crbegin}\r
4855 \r
4856     @sa @ref rbegin() -- returns a reverse iterator to the beginning\r
4857     @sa @ref rend() -- returns a reverse iterator to the end\r
4858     @sa @ref crend() -- returns a const reverse iterator to the end\r
4859 \r
4860     @since version 1.0.0\r
4861     */\r
4862     const_reverse_iterator crbegin() const noexcept\r
4863     {\r
4864         return const_reverse_iterator(cend());\r
4865     }\r
4866 \r
4867     /*!\r
4868     @brief returns a const reverse iterator to one before the first\r
4869 \r
4870     Returns a const reverse iterator to the reverse-end; that is, one before\r
4871     the first element.\r
4872 \r
4873     @image html range-rbegin-rend.svg "Illustration from cppreference.com"\r
4874 \r
4875     @complexity Constant.\r
4876 \r
4877     @requirement This function helps `basic_json` satisfying the\r
4878     [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\r
4879     requirements:\r
4880     - The complexity is constant.\r
4881     - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.\r
4882 \r
4883     @liveexample{The following code shows an example for `crend()`.,crend}\r
4884 \r
4885     @sa @ref rend() -- returns a reverse iterator to the end\r
4886     @sa @ref rbegin() -- returns a reverse iterator to the beginning\r
4887     @sa @ref crbegin() -- returns a const reverse iterator to the beginning\r
4888 \r
4889     @since version 1.0.0\r
4890     */\r
4891     const_reverse_iterator crend() const noexcept\r
4892     {\r
4893         return const_reverse_iterator(cbegin());\r
4894     }\r
4895 \r
4896   private:\r
4897     // forward declaration\r
4898     template<typename IteratorType> class iteration_proxy;\r
4899 \r
4900   public:\r
4901     /*!\r
4902     @brief wrapper to access iterator member functions in range-based for\r
4903 \r
4904     This function allows to access @ref iterator::key() and @ref\r
4905     iterator::value() during range-based for loops. In these loops, a\r
4906     reference to the JSON values is returned, so there is no access to the\r
4907     underlying iterator.\r
4908 \r
4909     @note The name of this function is not yet final and may change in the\r
4910     future.\r
4911     */\r
4912     static iteration_proxy<iterator> iterator_wrapper(reference cont)\r
4913     {\r
4914         return iteration_proxy<iterator>(cont);\r
4915     }\r
4916 \r
4917     /*!\r
4918     @copydoc iterator_wrapper(reference)\r
4919     */\r
4920     static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)\r
4921     {\r
4922         return iteration_proxy<const_iterator>(cont);\r
4923     }\r
4924 \r
4925     /// @}\r
4926 \r
4927 \r
4928     //////////////\r
4929     // capacity //\r
4930     //////////////\r
4931 \r
4932     /// @name capacity\r
4933     /// @{\r
4934 \r
4935     /*!\r
4936     @brief checks whether the container is empty\r
4937 \r
4938     Checks if a JSON value has no elements.\r
4939 \r
4940     @return The return value depends on the different types and is\r
4941             defined as follows:\r
4942             Value type  | return value\r
4943             ----------- | -------------\r
4944             null        | `true`\r
4945             boolean     | `false`\r
4946             string      | `false`\r
4947             number      | `false`\r
4948             object      | result of function `object_t::empty()`\r
4949             array       | result of function `array_t::empty()`\r
4950 \r
4951     @note This function does not return whether a string stored as JSON value\r
4952     is empty - it returns whether the JSON container itself is empty which is\r
4953     false in the case of a string.\r
4954 \r
4955     @complexity Constant, as long as @ref array_t and @ref object_t satisfy\r
4956     the Container concept; that is, their `empty()` functions have constant\r
4957     complexity.\r
4958 \r
4959     @requirement This function helps `basic_json` satisfying the\r
4960     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
4961     requirements:\r
4962     - The complexity is constant.\r
4963     - Has the semantics of `begin() == end()`.\r
4964 \r
4965     @liveexample{The following code uses `empty()` to check if a JSON\r
4966     object contains any elements.,empty}\r
4967 \r
4968     @sa @ref size() -- returns the number of elements\r
4969 \r
4970     @since version 1.0.0\r
4971     */\r
4972     bool empty() const noexcept\r
4973     {\r
4974         switch (m_type)\r
4975         {\r
4976             case value_t::null:\r
4977             {\r
4978                 // null values are empty\r
4979                 return true;\r
4980             }\r
4981 \r
4982             case value_t::array:\r
4983             {\r
4984                 // delegate call to array_t::empty()\r
4985                 return m_value.array->empty();\r
4986             }\r
4987 \r
4988             case value_t::object:\r
4989             {\r
4990                 // delegate call to object_t::empty()\r
4991                 return m_value.object->empty();\r
4992             }\r
4993 \r
4994             default:\r
4995             {\r
4996                 // all other types are nonempty\r
4997                 return false;\r
4998             }\r
4999         }\r
5000     }\r
5001 \r
5002     /*!\r
5003     @brief returns the number of elements\r
5004 \r
5005     Returns the number of elements in a JSON value.\r
5006 \r
5007     @return The return value depends on the different types and is\r
5008             defined as follows:\r
5009             Value type  | return value\r
5010             ----------- | -------------\r
5011             null        | `0`\r
5012             boolean     | `1`\r
5013             string      | `1`\r
5014             number      | `1`\r
5015             object      | result of function object_t::size()\r
5016             array       | result of function array_t::size()\r
5017 \r
5018     @note This function does not return the length of a string stored as JSON\r
5019     value - it returns the number of elements in the JSON value which is 1 in\r
5020     the case of a string.\r
5021 \r
5022     @complexity Constant, as long as @ref array_t and @ref object_t satisfy\r
5023     the Container concept; that is, their size() functions have constant\r
5024     complexity.\r
5025 \r
5026     @requirement This function helps `basic_json` satisfying the\r
5027     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
5028     requirements:\r
5029     - The complexity is constant.\r
5030     - Has the semantics of `std::distance(begin(), end())`.\r
5031 \r
5032     @liveexample{The following code calls `size()` on the different value\r
5033     types.,size}\r
5034 \r
5035     @sa @ref empty() -- checks whether the container is empty\r
5036     @sa @ref max_size() -- returns the maximal number of elements\r
5037 \r
5038     @since version 1.0.0\r
5039     */\r
5040     size_type size() const noexcept\r
5041     {\r
5042         switch (m_type)\r
5043         {\r
5044             case value_t::null:\r
5045             {\r
5046                 // null values are empty\r
5047                 return 0;\r
5048             }\r
5049 \r
5050             case value_t::array:\r
5051             {\r
5052                 // delegate call to array_t::size()\r
5053                 return m_value.array->size();\r
5054             }\r
5055 \r
5056             case value_t::object:\r
5057             {\r
5058                 // delegate call to object_t::size()\r
5059                 return m_value.object->size();\r
5060             }\r
5061 \r
5062             default:\r
5063             {\r
5064                 // all other types have size 1\r
5065                 return 1;\r
5066             }\r
5067         }\r
5068     }\r
5069 \r
5070     /*!\r
5071     @brief returns the maximum possible number of elements\r
5072 \r
5073     Returns the maximum number of elements a JSON value is able to hold due to\r
5074     system or library implementation limitations, i.e. `std::distance(begin(),\r
5075     end())` for the JSON value.\r
5076 \r
5077     @return The return value depends on the different types and is\r
5078             defined as follows:\r
5079             Value type  | return value\r
5080             ----------- | -------------\r
5081             null        | `0` (same as `size()`)\r
5082             boolean     | `1` (same as `size()`)\r
5083             string      | `1` (same as `size()`)\r
5084             number      | `1` (same as `size()`)\r
5085             object      | result of function `object_t::max_size()`\r
5086             array       | result of function `array_t::max_size()`\r
5087 \r
5088     @complexity Constant, as long as @ref array_t and @ref object_t satisfy\r
5089     the Container concept; that is, their `max_size()` functions have constant\r
5090     complexity.\r
5091 \r
5092     @requirement This function helps `basic_json` satisfying the\r
5093     [Container](http://en.cppreference.com/w/cpp/concept/Container)\r
5094     requirements:\r
5095     - The complexity is constant.\r
5096     - Has the semantics of returning `b.size()` where `b` is the largest\r
5097       possible JSON value.\r
5098 \r
5099     @liveexample{The following code calls `max_size()` on the different value\r
5100     types. Note the output is implementation specific.,max_size}\r
5101 \r
5102     @sa @ref size() -- returns the number of elements\r
5103 \r
5104     @since version 1.0.0\r
5105     */\r
5106     size_type max_size() const noexcept\r
5107     {\r
5108         switch (m_type)\r
5109         {\r
5110             case value_t::array:\r
5111             {\r
5112                 // delegate call to array_t::max_size()\r
5113                 return m_value.array->max_size();\r
5114             }\r
5115 \r
5116             case value_t::object:\r
5117             {\r
5118                 // delegate call to object_t::max_size()\r
5119                 return m_value.object->max_size();\r
5120             }\r
5121 \r
5122             default:\r
5123             {\r
5124                 // all other types have max_size() == size()\r
5125                 return size();\r
5126             }\r
5127         }\r
5128     }\r
5129 \r
5130     /// @}\r
5131 \r
5132 \r
5133     ///////////////\r
5134     // modifiers //\r
5135     ///////////////\r
5136 \r
5137     /// @name modifiers\r
5138     /// @{\r
5139 \r
5140     /*!\r
5141     @brief clears the contents\r
5142 \r
5143     Clears the content of a JSON value and resets it to the default value as\r
5144     if @ref basic_json(value_t) would have been called:\r
5145 \r
5146     Value type  | initial value\r
5147     ----------- | -------------\r
5148     null        | `null`\r
5149     boolean     | `false`\r
5150     string      | `""`\r
5151     number      | `0`\r
5152     object      | `{}`\r
5153     array       | `[]`\r
5154 \r
5155     @complexity Linear in the size of the JSON value.\r
5156 \r
5157     @liveexample{The example below shows the effect of `clear()` to different\r
5158     JSON types.,clear}\r
5159 \r
5160     @since version 1.0.0\r
5161     */\r
5162     void clear() noexcept\r
5163     {\r
5164         switch (m_type)\r
5165         {\r
5166             case value_t::number_integer:\r
5167             {\r
5168                 m_value.number_integer = 0;\r
5169                 break;\r
5170             }\r
5171 \r
5172             case value_t::number_unsigned:\r
5173             {\r
5174                 m_value.number_unsigned = 0;\r
5175                 break;\r
5176             }\r
5177 \r
5178             case value_t::number_float:\r
5179             {\r
5180                 m_value.number_float = 0.0;\r
5181                 break;\r
5182             }\r
5183 \r
5184             case value_t::boolean:\r
5185             {\r
5186                 m_value.boolean = false;\r
5187                 break;\r
5188             }\r
5189 \r
5190             case value_t::string:\r
5191             {\r
5192                 m_value.string->clear();\r
5193                 break;\r
5194             }\r
5195 \r
5196             case value_t::array:\r
5197             {\r
5198                 m_value.array->clear();\r
5199                 break;\r
5200             }\r
5201 \r
5202             case value_t::object:\r
5203             {\r
5204                 m_value.object->clear();\r
5205                 break;\r
5206             }\r
5207 \r
5208             default:\r
5209             {\r
5210                 break;\r
5211             }\r
5212         }\r
5213     }\r
5214 \r
5215     /*!\r
5216     @brief add an object to an array\r
5217 \r
5218     Appends the given element @a val to the end of the JSON value. If the\r
5219     function is called on a JSON null value, an empty array is created before\r
5220     appending @a val.\r
5221 \r
5222     @param[in] val the value to add to the JSON array\r
5223 \r
5224     @throw std::domain_error when called on a type other than JSON array or\r
5225     null; example: `"cannot use push_back() with number"`\r
5226 \r
5227     @complexity Amortized constant.\r
5228 \r
5229     @liveexample{The example shows how `push_back()` and `+=` can be used to\r
5230     add elements to a JSON array. Note how the `null` value was silently\r
5231     converted to a JSON array.,push_back}\r
5232 \r
5233     @since version 1.0.0\r
5234     */\r
5235     void push_back(basic_json&& val)\r
5236     {\r
5237         // push_back only works for null objects or arrays\r
5238         if (not(is_null() or is_array()))\r
5239         {\r
5240             JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));\r
5241         }\r
5242 \r
5243         // transform null object into an array\r
5244         if (is_null())\r
5245         {\r
5246             m_type = value_t::array;\r
5247             m_value = value_t::array;\r
5248             assert_invariant();\r
5249         }\r
5250 \r
5251         // add element to array (move semantics)\r
5252         m_value.array->push_back(std::move(val));\r
5253         // invalidate object\r
5254         val.m_type = value_t::null;\r
5255     }\r
5256 \r
5257     /*!\r
5258     @brief add an object to an array\r
5259     @copydoc push_back(basic_json&&)\r
5260     */\r
5261     reference operator+=(basic_json&& val)\r
5262     {\r
5263         push_back(std::move(val));\r
5264         return *this;\r
5265     }\r
5266 \r
5267     /*!\r
5268     @brief add an object to an array\r
5269     @copydoc push_back(basic_json&&)\r
5270     */\r
5271     void push_back(const basic_json& val)\r
5272     {\r
5273         // push_back only works for null objects or arrays\r
5274         if (not(is_null() or is_array()))\r
5275         {\r
5276             JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));\r
5277         }\r
5278 \r
5279         // transform null object into an array\r
5280         if (is_null())\r
5281         {\r
5282             m_type = value_t::array;\r
5283             m_value = value_t::array;\r
5284             assert_invariant();\r
5285         }\r
5286 \r
5287         // add element to array\r
5288         m_value.array->push_back(val);\r
5289     }\r
5290 \r
5291     /*!\r
5292     @brief add an object to an array\r
5293     @copydoc push_back(basic_json&&)\r
5294     */\r
5295     reference operator+=(const basic_json& val)\r
5296     {\r
5297         push_back(val);\r
5298         return *this;\r
5299     }\r
5300 \r
5301     /*!\r
5302     @brief add an object to an object\r
5303 \r
5304     Inserts the given element @a val to the JSON object. If the function is\r
5305     called on a JSON null value, an empty object is created before inserting\r
5306     @a val.\r
5307 \r
5308     @param[in] val the value to add to the JSON object\r
5309 \r
5310     @throw std::domain_error when called on a type other than JSON object or\r
5311     null; example: `"cannot use push_back() with number"`\r
5312 \r
5313     @complexity Logarithmic in the size of the container, O(log(`size()`)).\r
5314 \r
5315     @liveexample{The example shows how `push_back()` and `+=` can be used to\r
5316     add elements to a JSON object. Note how the `null` value was silently\r
5317     converted to a JSON object.,push_back__object_t__value}\r
5318 \r
5319     @since version 1.0.0\r
5320     */\r
5321     void push_back(const typename object_t::value_type& val)\r
5322     {\r
5323         // push_back only works for null objects or objects\r
5324         if (not(is_null() or is_object()))\r
5325         {\r
5326             JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));\r
5327         }\r
5328 \r
5329         // transform null object into an object\r
5330         if (is_null())\r
5331         {\r
5332             m_type = value_t::object;\r
5333             m_value = value_t::object;\r
5334             assert_invariant();\r
5335         }\r
5336 \r
5337         // add element to array\r
5338         m_value.object->insert(val);\r
5339     }\r
5340 \r
5341     /*!\r
5342     @brief add an object to an object\r
5343     @copydoc push_back(const typename object_t::value_type&)\r
5344     */\r
5345     reference operator+=(const typename object_t::value_type& val)\r
5346     {\r
5347         push_back(val);\r
5348         return *this;\r
5349     }\r
5350 \r
5351     /*!\r
5352     @brief add an object to an object\r
5353 \r
5354     This function allows to use `push_back` with an initializer list. In case\r
5355 \r
5356     1. the current value is an object,\r
5357     2. the initializer list @a init contains only two elements, and\r
5358     3. the first element of @a init is a string,\r
5359 \r
5360     @a init is converted into an object element and added using\r
5361     @ref push_back(const typename object_t::value_type&). Otherwise, @a init\r
5362     is converted to a JSON value and added using @ref push_back(basic_json&&).\r
5363 \r
5364     @param init  an initializer list\r
5365 \r
5366     @complexity Linear in the size of the initializer list @a init.\r
5367 \r
5368     @note This function is required to resolve an ambiguous overload error,\r
5369           because pairs like `{"key", "value"}` can be both interpreted as\r
5370           `object_t::value_type` or `std::initializer_list<basic_json>`, see\r
5371           https://github.com/nlohmann/json/issues/235 for more information.\r
5372 \r
5373     @liveexample{The example shows how initializer lists are treated as\r
5374     objects when possible.,push_back__initializer_list}\r
5375     */\r
5376     void push_back(std::initializer_list<basic_json> init)\r
5377     {\r
5378         if (is_object() and init.size() == 2 and init.begin()->is_string())\r
5379         {\r
5380             const string_t key = *init.begin();\r
5381             push_back(typename object_t::value_type(key, *(init.begin() + 1)));\r
5382         }\r
5383         else\r
5384         {\r
5385             push_back(basic_json(init));\r
5386         }\r
5387     }\r
5388 \r
5389     /*!\r
5390     @brief add an object to an object\r
5391     @copydoc push_back(std::initializer_list<basic_json>)\r
5392     */\r
5393     reference operator+=(std::initializer_list<basic_json> init)\r
5394     {\r
5395         push_back(init);\r
5396         return *this;\r
5397     }\r
5398 \r
5399     /*!\r
5400     @brief add an object to an array\r
5401 \r
5402     Creates a JSON value from the passed parameters @a args to the end of the\r
5403     JSON value. If the function is called on a JSON null value, an empty array\r
5404     is created before appending the value created from @a args.\r
5405 \r
5406     @param[in] args arguments to forward to a constructor of @ref basic_json\r
5407     @tparam Args compatible types to create a @ref basic_json object\r
5408 \r
5409     @throw std::domain_error when called on a type other than JSON array or\r
5410     null; example: `"cannot use emplace_back() with number"`\r
5411 \r
5412     @complexity Amortized constant.\r
5413 \r
5414     @liveexample{The example shows how `push_back()` can be used to add\r
5415     elements to a JSON array. Note how the `null` value was silently converted\r
5416     to a JSON array.,emplace_back}\r
5417 \r
5418     @since version 2.0.8\r
5419     */\r
5420     template<class... Args>\r
5421     void emplace_back(Args&& ... args)\r
5422     {\r
5423         // emplace_back only works for null objects or arrays\r
5424         if (not(is_null() or is_array()))\r
5425         {\r
5426             JSON_THROW(std::domain_error("cannot use emplace_back() with " + type_name()));\r
5427         }\r
5428 \r
5429         // transform null object into an array\r
5430         if (is_null())\r
5431         {\r
5432             m_type = value_t::array;\r
5433             m_value = value_t::array;\r
5434             assert_invariant();\r
5435         }\r
5436 \r
5437         // add element to array (perfect forwarding)\r
5438         m_value.array->emplace_back(std::forward<Args>(args)...);\r
5439     }\r
5440 \r
5441     /*!\r
5442     @brief add an object to an object if key does not exist\r
5443 \r
5444     Inserts a new element into a JSON object constructed in-place with the\r
5445     given @a args if there is no element with the key in the container. If the\r
5446     function is called on a JSON null value, an empty object is created before\r
5447     appending the value created from @a args.\r
5448 \r
5449     @param[in] args arguments to forward to a constructor of @ref basic_json\r
5450     @tparam Args compatible types to create a @ref basic_json object\r
5451 \r
5452     @return a pair consisting of an iterator to the inserted element, or the\r
5453             already-existing element if no insertion happened, and a bool\r
5454             denoting whether the insertion took place.\r
5455 \r
5456     @throw std::domain_error when called on a type other than JSON object or\r
5457     null; example: `"cannot use emplace() with number"`\r
5458 \r
5459     @complexity Logarithmic in the size of the container, O(log(`size()`)).\r
5460 \r
5461     @liveexample{The example shows how `emplace()` can be used to add elements\r
5462     to a JSON object. Note how the `null` value was silently converted to a\r
5463     JSON object. Further note how no value is added if there was already one\r
5464     value stored with the same key.,emplace}\r
5465 \r
5466     @since version 2.0.8\r
5467     */\r
5468     template<class... Args>\r
5469     std::pair<iterator, bool> emplace(Args&& ... args)\r
5470     {\r
5471         // emplace only works for null objects or arrays\r
5472         if (not(is_null() or is_object()))\r
5473         {\r
5474             JSON_THROW(std::domain_error("cannot use emplace() with " + type_name()));\r
5475         }\r
5476 \r
5477         // transform null object into an object\r
5478         if (is_null())\r
5479         {\r
5480             m_type = value_t::object;\r
5481             m_value = value_t::object;\r
5482             assert_invariant();\r
5483         }\r
5484 \r
5485         // add element to array (perfect forwarding)\r
5486         auto res = m_value.object->emplace(std::forward<Args>(args)...);\r
5487         // create result iterator and set iterator to the result of emplace\r
5488         auto it = begin();\r
5489         it.m_it.object_iterator = res.first;\r
5490 \r
5491         // return pair of iterator and boolean\r
5492         return {it, res.second};\r
5493     }\r
5494 \r
5495     /*!\r
5496     @brief inserts element\r
5497 \r
5498     Inserts element @a val before iterator @a pos.\r
5499 \r
5500     @param[in] pos iterator before which the content will be inserted; may be\r
5501     the end() iterator\r
5502     @param[in] val element to insert\r
5503     @return iterator pointing to the inserted @a val.\r
5504 \r
5505     @throw std::domain_error if called on JSON values other than arrays;\r
5506     example: `"cannot use insert() with string"`\r
5507     @throw std::domain_error if @a pos is not an iterator of *this; example:\r
5508     `"iterator does not fit current value"`\r
5509 \r
5510     @complexity Constant plus linear in the distance between @a pos and end of\r
5511     the container.\r
5512 \r
5513     @liveexample{The example shows how `insert()` is used.,insert}\r
5514 \r
5515     @since version 1.0.0\r
5516     */\r
5517     iterator insert(const_iterator pos, const basic_json& val)\r
5518     {\r
5519         // insert only works for arrays\r
5520         if (is_array())\r
5521         {\r
5522             // check if iterator pos fits to this JSON value\r
5523             if (pos.m_object != this)\r
5524             {\r
5525                 JSON_THROW(std::domain_error("iterator does not fit current value"));\r
5526             }\r
5527 \r
5528             // insert to array and return iterator\r
5529             iterator result(this);\r
5530             result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);\r
5531             return result;\r
5532         }\r
5533 \r
5534         JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));\r
5535     }\r
5536 \r
5537     /*!\r
5538     @brief inserts element\r
5539     @copydoc insert(const_iterator, const basic_json&)\r
5540     */\r
5541     iterator insert(const_iterator pos, basic_json&& val)\r
5542     {\r
5543         return insert(pos, val);\r
5544     }\r
5545 \r
5546     /*!\r
5547     @brief inserts elements\r
5548 \r
5549     Inserts @a cnt copies of @a val before iterator @a pos.\r
5550 \r
5551     @param[in] pos iterator before which the content will be inserted; may be\r
5552     the end() iterator\r
5553     @param[in] cnt number of copies of @a val to insert\r
5554     @param[in] val element to insert\r
5555     @return iterator pointing to the first element inserted, or @a pos if\r
5556     `cnt==0`\r
5557 \r
5558     @throw std::domain_error if called on JSON values other than arrays;\r
5559     example: `"cannot use insert() with string"`\r
5560     @throw std::domain_error if @a pos is not an iterator of *this; example:\r
5561     `"iterator does not fit current value"`\r
5562 \r
5563     @complexity Linear in @a cnt plus linear in the distance between @a pos\r
5564     and end of the container.\r
5565 \r
5566     @liveexample{The example shows how `insert()` is used.,insert__count}\r
5567 \r
5568     @since version 1.0.0\r
5569     */\r
5570     iterator insert(const_iterator pos, size_type cnt, const basic_json& val)\r
5571     {\r
5572         // insert only works for arrays\r
5573         if (is_array())\r
5574         {\r
5575             // check if iterator pos fits to this JSON value\r
5576             if (pos.m_object != this)\r
5577             {\r
5578                 JSON_THROW(std::domain_error("iterator does not fit current value"));\r
5579             }\r
5580 \r
5581             // insert to array and return iterator\r
5582             iterator result(this);\r
5583             result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);\r
5584             return result;\r
5585         }\r
5586 \r
5587         JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));\r
5588     }\r
5589 \r
5590     /*!\r
5591     @brief inserts elements\r
5592 \r
5593     Inserts elements from range `[first, last)` before iterator @a pos.\r
5594 \r
5595     @param[in] pos iterator before which the content will be inserted; may be\r
5596     the end() iterator\r
5597     @param[in] first begin of the range of elements to insert\r
5598     @param[in] last end of the range of elements to insert\r
5599 \r
5600     @throw std::domain_error if called on JSON values other than arrays;\r
5601     example: `"cannot use insert() with string"`\r
5602     @throw std::domain_error if @a pos is not an iterator of *this; example:\r
5603     `"iterator does not fit current value"`\r
5604     @throw std::domain_error if @a first and @a last do not belong to the same\r
5605     JSON value; example: `"iterators do not fit"`\r
5606     @throw std::domain_error if @a first or @a last are iterators into\r
5607     container for which insert is called; example: `"passed iterators may not\r
5608     belong to container"`\r
5609 \r
5610     @return iterator pointing to the first element inserted, or @a pos if\r
5611     `first==last`\r
5612 \r
5613     @complexity Linear in `std::distance(first, last)` plus linear in the\r
5614     distance between @a pos and end of the container.\r
5615 \r
5616     @liveexample{The example shows how `insert()` is used.,insert__range}\r
5617 \r
5618     @since version 1.0.0\r
5619     */\r
5620     iterator insert(const_iterator pos, const_iterator first, const_iterator last)\r
5621     {\r
5622         // insert only works for arrays\r
5623         if (not is_array())\r
5624         {\r
5625             JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));\r
5626         }\r
5627 \r
5628         // check if iterator pos fits to this JSON value\r
5629         if (pos.m_object != this)\r
5630         {\r
5631             JSON_THROW(std::domain_error("iterator does not fit current value"));\r
5632         }\r
5633 \r
5634         // check if range iterators belong to the same JSON object\r
5635         if (first.m_object != last.m_object)\r
5636         {\r
5637             JSON_THROW(std::domain_error("iterators do not fit"));\r
5638         }\r
5639 \r
5640         if (first.m_object == this or last.m_object == this)\r
5641         {\r
5642             JSON_THROW(std::domain_error("passed iterators may not belong to container"));\r
5643         }\r
5644 \r
5645         // insert to array and return iterator\r
5646         iterator result(this);\r
5647         result.m_it.array_iterator = m_value.array->insert(\r
5648                                          pos.m_it.array_iterator,\r
5649                                          first.m_it.array_iterator,\r
5650                                          last.m_it.array_iterator);\r
5651         return result;\r
5652     }\r
5653 \r
5654     /*!\r
5655     @brief inserts elements\r
5656 \r
5657     Inserts elements from initializer list @a ilist before iterator @a pos.\r
5658 \r
5659     @param[in] pos iterator before which the content will be inserted; may be\r
5660     the end() iterator\r
5661     @param[in] ilist initializer list to insert the values from\r
5662 \r
5663     @throw std::domain_error if called on JSON values other than arrays;\r
5664     example: `"cannot use insert() with string"`\r
5665     @throw std::domain_error if @a pos is not an iterator of *this; example:\r
5666     `"iterator does not fit current value"`\r
5667 \r
5668     @return iterator pointing to the first element inserted, or @a pos if\r
5669     `ilist` is empty\r
5670 \r
5671     @complexity Linear in `ilist.size()` plus linear in the distance between\r
5672     @a pos and end of the container.\r
5673 \r
5674     @liveexample{The example shows how `insert()` is used.,insert__ilist}\r
5675 \r
5676     @since version 1.0.0\r
5677     */\r
5678     iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)\r
5679     {\r
5680         // insert only works for arrays\r
5681         if (not is_array())\r
5682         {\r
5683             JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));\r
5684         }\r
5685 \r
5686         // check if iterator pos fits to this JSON value\r
5687         if (pos.m_object != this)\r
5688         {\r
5689             JSON_THROW(std::domain_error("iterator does not fit current value"));\r
5690         }\r
5691 \r
5692         // insert to array and return iterator\r
5693         iterator result(this);\r
5694         result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);\r
5695         return result;\r
5696     }\r
5697 \r
5698     /*!\r
5699     @brief exchanges the values\r
5700 \r
5701     Exchanges the contents of the JSON value with those of @a other. Does not\r
5702     invoke any move, copy, or swap operations on individual elements. All\r
5703     iterators and references remain valid. The past-the-end iterator is\r
5704     invalidated.\r
5705 \r
5706     @param[in,out] other JSON value to exchange the contents with\r
5707 \r
5708     @complexity Constant.\r
5709 \r
5710     @liveexample{The example below shows how JSON values can be swapped with\r
5711     `swap()`.,swap__reference}\r
5712 \r
5713     @since version 1.0.0\r
5714     */\r
5715     void swap(reference other) noexcept (\r
5716         std::is_nothrow_move_constructible<value_t>::value and\r
5717         std::is_nothrow_move_assignable<value_t>::value and\r
5718         std::is_nothrow_move_constructible<json_value>::value and\r
5719         std::is_nothrow_move_assignable<json_value>::value\r
5720     )\r
5721     {\r
5722         std::swap(m_type, other.m_type);\r
5723         std::swap(m_value, other.m_value);\r
5724         assert_invariant();\r
5725     }\r
5726 \r
5727     /*!\r
5728     @brief exchanges the values\r
5729 \r
5730     Exchanges the contents of a JSON array with those of @a other. Does not\r
5731     invoke any move, copy, or swap operations on individual elements. All\r
5732     iterators and references remain valid. The past-the-end iterator is\r
5733     invalidated.\r
5734 \r
5735     @param[in,out] other array to exchange the contents with\r
5736 \r
5737     @throw std::domain_error when JSON value is not an array; example:\r
5738     `"cannot use swap() with string"`\r
5739 \r
5740     @complexity Constant.\r
5741 \r
5742     @liveexample{The example below shows how arrays can be swapped with\r
5743     `swap()`.,swap__array_t}\r
5744 \r
5745     @since version 1.0.0\r
5746     */\r
5747     void swap(array_t& other)\r
5748     {\r
5749         // swap only works for arrays\r
5750         if (is_array())\r
5751         {\r
5752             std::swap(*(m_value.array), other);\r
5753         }\r
5754         else\r
5755         {\r
5756             JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));\r
5757         }\r
5758     }\r
5759 \r
5760     /*!\r
5761     @brief exchanges the values\r
5762 \r
5763     Exchanges the contents of a JSON object with those of @a other. Does not\r
5764     invoke any move, copy, or swap operations on individual elements. All\r
5765     iterators and references remain valid. The past-the-end iterator is\r
5766     invalidated.\r
5767 \r
5768     @param[in,out] other object to exchange the contents with\r
5769 \r
5770     @throw std::domain_error when JSON value is not an object; example:\r
5771     `"cannot use swap() with string"`\r
5772 \r
5773     @complexity Constant.\r
5774 \r
5775     @liveexample{The example below shows how objects can be swapped with\r
5776     `swap()`.,swap__object_t}\r
5777 \r
5778     @since version 1.0.0\r
5779     */\r
5780     void swap(object_t& other)\r
5781     {\r
5782         // swap only works for objects\r
5783         if (is_object())\r
5784         {\r
5785             std::swap(*(m_value.object), other);\r
5786         }\r
5787         else\r
5788         {\r
5789             JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));\r
5790         }\r
5791     }\r
5792 \r
5793     /*!\r
5794     @brief exchanges the values\r
5795 \r
5796     Exchanges the contents of a JSON string with those of @a other. Does not\r
5797     invoke any move, copy, or swap operations on individual elements. All\r
5798     iterators and references remain valid. The past-the-end iterator is\r
5799     invalidated.\r
5800 \r
5801     @param[in,out] other string to exchange the contents with\r
5802 \r
5803     @throw std::domain_error when JSON value is not a string; example: `"cannot\r
5804     use swap() with boolean"`\r
5805 \r
5806     @complexity Constant.\r
5807 \r
5808     @liveexample{The example below shows how strings can be swapped with\r
5809     `swap()`.,swap__string_t}\r
5810 \r
5811     @since version 1.0.0\r
5812     */\r
5813     void swap(string_t& other)\r
5814     {\r
5815         // swap only works for strings\r
5816         if (is_string())\r
5817         {\r
5818             std::swap(*(m_value.string), other);\r
5819         }\r
5820         else\r
5821         {\r
5822             JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));\r
5823         }\r
5824     }\r
5825 \r
5826     /// @}\r
5827 \r
5828   public:\r
5829     //////////////////////////////////////////\r
5830     // lexicographical comparison operators //\r
5831     //////////////////////////////////////////\r
5832 \r
5833     /// @name lexicographical comparison operators\r
5834     /// @{\r
5835 \r
5836     /*!\r
5837     @brief comparison: equal\r
5838 \r
5839     Compares two JSON values for equality according to the following rules:\r
5840     - Two JSON values are equal if (1) they are from the same type and (2)\r
5841       their stored values are the same.\r
5842     - Integer and floating-point numbers are automatically converted before\r
5843       comparison. Floating-point numbers are compared indirectly: two\r
5844       floating-point numbers `f1` and `f2` are considered equal if neither\r
5845       `f1 > f2` nor `f2 > f1` holds.\r
5846     - Two JSON null values are equal.\r
5847 \r
5848     @param[in] lhs  first JSON value to consider\r
5849     @param[in] rhs  second JSON value to consider\r
5850     @return whether the values @a lhs and @a rhs are equal\r
5851 \r
5852     @complexity Linear.\r
5853 \r
5854     @liveexample{The example demonstrates comparing several JSON\r
5855     types.,operator__equal}\r
5856 \r
5857     @since version 1.0.0\r
5858     */\r
5859     friend bool operator==(const_reference lhs, const_reference rhs) noexcept\r
5860     {\r
5861         const auto lhs_type = lhs.type();\r
5862         const auto rhs_type = rhs.type();\r
5863 \r
5864         if (lhs_type == rhs_type)\r
5865         {\r
5866             switch (lhs_type)\r
5867             {\r
5868                 case value_t::array:\r
5869                 {\r
5870                     return *lhs.m_value.array == *rhs.m_value.array;\r
5871                 }\r
5872                 case value_t::object:\r
5873                 {\r
5874                     return *lhs.m_value.object == *rhs.m_value.object;\r
5875                 }\r
5876                 case value_t::null:\r
5877                 {\r
5878                     return true;\r
5879                 }\r
5880                 case value_t::string:\r
5881                 {\r
5882                     return *lhs.m_value.string == *rhs.m_value.string;\r
5883                 }\r
5884                 case value_t::boolean:\r
5885                 {\r
5886                     return lhs.m_value.boolean == rhs.m_value.boolean;\r
5887                 }\r
5888                 case value_t::number_integer:\r
5889                 {\r
5890                     return lhs.m_value.number_integer == rhs.m_value.number_integer;\r
5891                 }\r
5892                 case value_t::number_unsigned:\r
5893                 {\r
5894                     return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;\r
5895                 }\r
5896                 case value_t::number_float:\r
5897                 {\r
5898                     return lhs.m_value.number_float == rhs.m_value.number_float;\r
5899                 }\r
5900                 default:\r
5901                 {\r
5902                     return false;\r
5903                 }\r
5904             }\r
5905         }\r
5906         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\r
5907         {\r
5908             return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;\r
5909         }\r
5910         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\r
5911         {\r
5912             return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);\r
5913         }\r
5914         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\r
5915         {\r
5916             return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;\r
5917         }\r
5918         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\r
5919         {\r
5920             return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);\r
5921         }\r
5922         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\r
5923         {\r
5924             return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;\r
5925         }\r
5926         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\r
5927         {\r
5928             return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);\r
5929         }\r
5930 \r
5931         return false;\r
5932     }\r
5933 \r
5934     /*!\r
5935     @brief comparison: equal\r
5936     @copydoc operator==(const_reference, const_reference)\r
5937     */\r
5938     template<typename ScalarType, typename std::enable_if<\r
5939                  std::is_scalar<ScalarType>::value, int>::type = 0>\r
5940     friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept\r
5941     {\r
5942         return (lhs == basic_json(rhs));\r
5943     }\r
5944 \r
5945     /*!\r
5946     @brief comparison: equal\r
5947     @copydoc operator==(const_reference, const_reference)\r
5948     */\r
5949     template<typename ScalarType, typename std::enable_if<\r
5950                  std::is_scalar<ScalarType>::value, int>::type = 0>\r
5951     friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept\r
5952     {\r
5953         return (basic_json(lhs) == rhs);\r
5954     }\r
5955 \r
5956     /*!\r
5957     @brief comparison: not equal\r
5958 \r
5959     Compares two JSON values for inequality by calculating `not (lhs == rhs)`.\r
5960 \r
5961     @param[in] lhs  first JSON value to consider\r
5962     @param[in] rhs  second JSON value to consider\r
5963     @return whether the values @a lhs and @a rhs are not equal\r
5964 \r
5965     @complexity Linear.\r
5966 \r
5967     @liveexample{The example demonstrates comparing several JSON\r
5968     types.,operator__notequal}\r
5969 \r
5970     @since version 1.0.0\r
5971     */\r
5972     friend bool operator!=(const_reference lhs, const_reference rhs) noexcept\r
5973     {\r
5974         return not (lhs == rhs);\r
5975     }\r
5976 \r
5977     /*!\r
5978     @brief comparison: not equal\r
5979     @copydoc operator!=(const_reference, const_reference)\r
5980     */\r
5981     template<typename ScalarType, typename std::enable_if<\r
5982                  std::is_scalar<ScalarType>::value, int>::type = 0>\r
5983     friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept\r
5984     {\r
5985         return (lhs != basic_json(rhs));\r
5986     }\r
5987 \r
5988     /*!\r
5989     @brief comparison: not equal\r
5990     @copydoc operator!=(const_reference, const_reference)\r
5991     */\r
5992     template<typename ScalarType, typename std::enable_if<\r
5993                  std::is_scalar<ScalarType>::value, int>::type = 0>\r
5994     friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept\r
5995     {\r
5996         return (basic_json(lhs) != rhs);\r
5997     }\r
5998 \r
5999     /*!\r
6000     @brief comparison: less than\r
6001 \r
6002     Compares whether one JSON value @a lhs is less than another JSON value @a\r
6003     rhs according to the following rules:\r
6004     - If @a lhs and @a rhs have the same type, the values are compared using\r
6005       the default `<` operator.\r
6006     - Integer and floating-point numbers are automatically converted before\r
6007       comparison\r
6008     - In case @a lhs and @a rhs have different types, the values are ignored\r
6009       and the order of the types is considered, see\r
6010       @ref operator<(const value_t, const value_t).\r
6011 \r
6012     @param[in] lhs  first JSON value to consider\r
6013     @param[in] rhs  second JSON value to consider\r
6014     @return whether @a lhs is less than @a rhs\r
6015 \r
6016     @complexity Linear.\r
6017 \r
6018     @liveexample{The example demonstrates comparing several JSON\r
6019     types.,operator__less}\r
6020 \r
6021     @since version 1.0.0\r
6022     */\r
6023     friend bool operator<(const_reference lhs, const_reference rhs) noexcept\r
6024     {\r
6025         const auto lhs_type = lhs.type();\r
6026         const auto rhs_type = rhs.type();\r
6027 \r
6028         if (lhs_type == rhs_type)\r
6029         {\r
6030             switch (lhs_type)\r
6031             {\r
6032                 case value_t::array:\r
6033                 {\r
6034                     return *lhs.m_value.array < *rhs.m_value.array;\r
6035                 }\r
6036                 case value_t::object:\r
6037                 {\r
6038                     return *lhs.m_value.object < *rhs.m_value.object;\r
6039                 }\r
6040                 case value_t::null:\r
6041                 {\r
6042                     return false;\r
6043                 }\r
6044                 case value_t::string:\r
6045                 {\r
6046                     return *lhs.m_value.string < *rhs.m_value.string;\r
6047                 }\r
6048                 case value_t::boolean:\r
6049                 {\r
6050                     return lhs.m_value.boolean < rhs.m_value.boolean;\r
6051                 }\r
6052                 case value_t::number_integer:\r
6053                 {\r
6054                     return lhs.m_value.number_integer < rhs.m_value.number_integer;\r
6055                 }\r
6056                 case value_t::number_unsigned:\r
6057                 {\r
6058                     return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;\r
6059                 }\r
6060                 case value_t::number_float:\r
6061                 {\r
6062                     return lhs.m_value.number_float < rhs.m_value.number_float;\r
6063                 }\r
6064                 default:\r
6065                 {\r
6066                     return false;\r
6067                 }\r
6068             }\r
6069         }\r
6070         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\r
6071         {\r
6072             return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;\r
6073         }\r
6074         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\r
6075         {\r
6076             return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);\r
6077         }\r
6078         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\r
6079         {\r
6080             return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;\r
6081         }\r
6082         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\r
6083         {\r
6084             return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);\r
6085         }\r
6086         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\r
6087         {\r
6088             return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);\r
6089         }\r
6090         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\r
6091         {\r
6092             return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;\r
6093         }\r
6094 \r
6095         // We only reach this line if we cannot compare values. In that case,\r
6096         // we compare types. Note we have to call the operator explicitly,\r
6097         // because MSVC has problems otherwise.\r
6098         return operator<(lhs_type, rhs_type);\r
6099     }\r
6100 \r
6101     /*!\r
6102     @brief comparison: less than or equal\r
6103 \r
6104     Compares whether one JSON value @a lhs is less than or equal to another\r
6105     JSON value by calculating `not (rhs < lhs)`.\r
6106 \r
6107     @param[in] lhs  first JSON value to consider\r
6108     @param[in] rhs  second JSON value to consider\r
6109     @return whether @a lhs is less than or equal to @a rhs\r
6110 \r
6111     @complexity Linear.\r
6112 \r
6113     @liveexample{The example demonstrates comparing several JSON\r
6114     types.,operator__greater}\r
6115 \r
6116     @since version 1.0.0\r
6117     */\r
6118     friend bool operator<=(const_reference lhs, const_reference rhs) noexcept\r
6119     {\r
6120         return not (rhs < lhs);\r
6121     }\r
6122 \r
6123     /*!\r
6124     @brief comparison: greater than\r
6125 \r
6126     Compares whether one JSON value @a lhs is greater than another\r
6127     JSON value by calculating `not (lhs <= rhs)`.\r
6128 \r
6129     @param[in] lhs  first JSON value to consider\r
6130     @param[in] rhs  second JSON value to consider\r
6131     @return whether @a lhs is greater than to @a rhs\r
6132 \r
6133     @complexity Linear.\r
6134 \r
6135     @liveexample{The example demonstrates comparing several JSON\r
6136     types.,operator__lessequal}\r
6137 \r
6138     @since version 1.0.0\r
6139     */\r
6140     friend bool operator>(const_reference lhs, const_reference rhs) noexcept\r
6141     {\r
6142         return not (lhs <= rhs);\r
6143     }\r
6144 \r
6145     /*!\r
6146     @brief comparison: greater than or equal\r
6147 \r
6148     Compares whether one JSON value @a lhs is greater than or equal to another\r
6149     JSON value by calculating `not (lhs < rhs)`.\r
6150 \r
6151     @param[in] lhs  first JSON value to consider\r
6152     @param[in] rhs  second JSON value to consider\r
6153     @return whether @a lhs is greater than or equal to @a rhs\r
6154 \r
6155     @complexity Linear.\r
6156 \r
6157     @liveexample{The example demonstrates comparing several JSON\r
6158     types.,operator__greaterequal}\r
6159 \r
6160     @since version 1.0.0\r
6161     */\r
6162     friend bool operator>=(const_reference lhs, const_reference rhs) noexcept\r
6163     {\r
6164         return not (lhs < rhs);\r
6165     }\r
6166 \r
6167     /// @}\r
6168 \r
6169 \r
6170     ///////////////////\r
6171     // serialization //\r
6172     ///////////////////\r
6173 \r
6174     /// @name serialization\r
6175     /// @{\r
6176 \r
6177     /*!\r
6178     @brief serialize to stream\r
6179 \r
6180     Serialize the given JSON value @a j to the output stream @a o. The JSON\r
6181     value will be serialized using the @ref dump member function. The\r
6182     indentation of the output can be controlled with the member variable\r
6183     `width` of the output stream @a o. For instance, using the manipulator\r
6184     `std::setw(4)` on @a o sets the indentation level to `4` and the\r
6185     serialization result is the same as calling `dump(4)`.\r
6186 \r
6187     @param[in,out] o  stream to serialize to\r
6188     @param[in] j  JSON value to serialize\r
6189 \r
6190     @return the stream @a o\r
6191 \r
6192     @complexity Linear.\r
6193 \r
6194     @liveexample{The example below shows the serialization with different\r
6195     parameters to `width` to adjust the indentation level.,operator_serialize}\r
6196 \r
6197     @since version 1.0.0\r
6198     */\r
6199     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)\r
6200     {\r
6201         // read width member and use it as indentation parameter if nonzero\r
6202         const bool pretty_print = (o.width() > 0);\r
6203         const auto indentation = (pretty_print ? o.width() : 0);\r
6204 \r
6205         // reset width to 0 for subsequent calls to this stream\r
6206         o.width(0);\r
6207 \r
6208         // do the actual serialization\r
6209         j.dump(o, pretty_print, static_cast<unsigned int>(indentation));\r
6210 \r
6211         return o;\r
6212     }\r
6213 \r
6214     /*!\r
6215     @brief serialize to stream\r
6216     @copydoc operator<<(std::ostream&, const basic_json&)\r
6217     */\r
6218     friend std::ostream& operator>>(const basic_json& j, std::ostream& o)\r
6219     {\r
6220         return o << j;\r
6221     }\r
6222 \r
6223     /// @}\r
6224 \r
6225 \r
6226     /////////////////////\r
6227     // deserialization //\r
6228     /////////////////////\r
6229 \r
6230     /// @name deserialization\r
6231     /// @{\r
6232 \r
6233     /*!\r
6234     @brief deserialize from an array\r
6235 \r
6236     This function reads from an array of 1-byte values.\r
6237 \r
6238     @pre Each element of the container has a size of 1 byte. Violating this\r
6239     precondition yields undefined behavior. **This precondition is enforced\r
6240     with a static assertion.**\r
6241 \r
6242     @param[in] array  array to read from\r
6243     @param[in] cb  a parser callback function of type @ref parser_callback_t\r
6244     which is used to control the deserialization by filtering unwanted values\r
6245     (optional)\r
6246 \r
6247     @return result of the deserialization\r
6248 \r
6249     @complexity Linear in the length of the input. The parser is a predictive\r
6250     LL(1) parser. The complexity can be higher if the parser callback function\r
6251     @a cb has a super-linear complexity.\r
6252 \r
6253     @note A UTF-8 byte order mark is silently ignored.\r
6254 \r
6255     @liveexample{The example below demonstrates the `parse()` function reading\r
6256     from an array.,parse__array__parser_callback_t}\r
6257 \r
6258     @since version 2.0.3\r
6259     */\r
6260     template<class T, std::size_t N>\r
6261     static basic_json parse(T (&array)[N],\r
6262                             const parser_callback_t cb = nullptr)\r
6263     {\r
6264         // delegate the call to the iterator-range parse overload\r
6265         return parse(std::begin(array), std::end(array), cb);\r
6266     }\r
6267 \r
6268     /*!\r
6269     @brief deserialize from string literal\r
6270 \r
6271     @tparam CharT character/literal type with size of 1 byte\r
6272     @param[in] s  string literal to read a serialized JSON value from\r
6273     @param[in] cb a parser callback function of type @ref parser_callback_t\r
6274     which is used to control the deserialization by filtering unwanted values\r
6275     (optional)\r
6276 \r
6277     @return result of the deserialization\r
6278 \r
6279     @complexity Linear in the length of the input. The parser is a predictive\r
6280     LL(1) parser. The complexity can be higher if the parser callback function\r
6281     @a cb has a super-linear complexity.\r
6282 \r
6283     @note A UTF-8 byte order mark is silently ignored.\r
6284     @note String containers like `std::string` or @ref string_t can be parsed\r
6285           with @ref parse(const ContiguousContainer&, const parser_callback_t)\r
6286 \r
6287     @liveexample{The example below demonstrates the `parse()` function with\r
6288     and without callback function.,parse__string__parser_callback_t}\r
6289 \r
6290     @sa @ref parse(std::istream&, const parser_callback_t) for a version that\r
6291     reads from an input stream\r
6292 \r
6293     @since version 1.0.0 (originally for @ref string_t)\r
6294     */\r
6295     template<typename CharT, typename std::enable_if<\r
6296                  std::is_pointer<CharT>::value and\r
6297                  std::is_integral<typename std::remove_pointer<CharT>::type>::value and\r
6298                  sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>\r
6299     static basic_json parse(const CharT s,\r
6300                             const parser_callback_t cb = nullptr)\r
6301     {\r
6302         return parser(reinterpret_cast<const char*>(s), cb).parse();\r
6303     }\r
6304 \r
6305     /*!\r
6306     @brief deserialize from stream\r
6307 \r
6308     @param[in,out] i  stream to read a serialized JSON value from\r
6309     @param[in] cb a parser callback function of type @ref parser_callback_t\r
6310     which is used to control the deserialization by filtering unwanted values\r
6311     (optional)\r
6312 \r
6313     @return result of the deserialization\r
6314 \r
6315     @complexity Linear in the length of the input. The parser is a predictive\r
6316     LL(1) parser. The complexity can be higher if the parser callback function\r
6317     @a cb has a super-linear complexity.\r
6318 \r
6319     @note A UTF-8 byte order mark is silently ignored.\r
6320 \r
6321     @liveexample{The example below demonstrates the `parse()` function with\r
6322     and without callback function.,parse__istream__parser_callback_t}\r
6323 \r
6324     @sa @ref parse(const CharT, const parser_callback_t) for a version\r
6325     that reads from a string\r
6326 \r
6327     @since version 1.0.0\r
6328     */\r
6329     static basic_json parse(std::istream& i,\r
6330                             const parser_callback_t cb = nullptr)\r
6331     {\r
6332         return parser(i, cb).parse();\r
6333     }\r
6334 \r
6335     /*!\r
6336     @copydoc parse(std::istream&, const parser_callback_t)\r
6337     */\r
6338     static basic_json parse(std::istream&& i,\r
6339                             const parser_callback_t cb = nullptr)\r
6340     {\r
6341         return parser(i, cb).parse();\r
6342     }\r
6343 \r
6344     /*!\r
6345     @brief deserialize from an iterator range with contiguous storage\r
6346 \r
6347     This function reads from an iterator range of a container with contiguous\r
6348     storage of 1-byte values. Compatible container types include\r
6349     `std::vector`, `std::string`, `std::array`, `std::valarray`, and\r
6350     `std::initializer_list`. Furthermore, C-style arrays can be used with\r
6351     `std::begin()`/`std::end()`. User-defined containers can be used as long\r
6352     as they implement random-access iterators and a contiguous storage.\r
6353 \r
6354     @pre The iterator range is contiguous. Violating this precondition yields\r
6355     undefined behavior. **This precondition is enforced with an assertion.**\r
6356     @pre Each element in the range has a size of 1 byte. Violating this\r
6357     precondition yields undefined behavior. **This precondition is enforced\r
6358     with a static assertion.**\r
6359 \r
6360     @warning There is no way to enforce all preconditions at compile-time. If\r
6361              the function is called with noncompliant iterators and with\r
6362              assertions switched off, the behavior is undefined and will most\r
6363              likely yield segmentation violation.\r
6364 \r
6365     @tparam IteratorType iterator of container with contiguous storage\r
6366     @param[in] first  begin of the range to parse (included)\r
6367     @param[in] last  end of the range to parse (excluded)\r
6368     @param[in] cb  a parser callback function of type @ref parser_callback_t\r
6369     which is used to control the deserialization by filtering unwanted values\r
6370     (optional)\r
6371 \r
6372     @return result of the deserialization\r
6373 \r
6374     @complexity Linear in the length of the input. The parser is a predictive\r
6375     LL(1) parser. The complexity can be higher if the parser callback function\r
6376     @a cb has a super-linear complexity.\r
6377 \r
6378     @note A UTF-8 byte order mark is silently ignored.\r
6379 \r
6380     @liveexample{The example below demonstrates the `parse()` function reading\r
6381     from an iterator range.,parse__iteratortype__parser_callback_t}\r
6382 \r
6383     @since version 2.0.3\r
6384     */\r
6385     template<class IteratorType, typename std::enable_if<\r
6386                  std::is_base_of<\r
6387                      std::random_access_iterator_tag,\r
6388                      typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>\r
6389     static basic_json parse(IteratorType first, IteratorType last,\r
6390                             const parser_callback_t cb = nullptr)\r
6391     {\r
6392         // assertion to check that the iterator range is indeed contiguous,\r
6393         // see http://stackoverflow.com/a/35008842/266378 for more discussion\r
6394         assert(std::accumulate(first, last, std::pair<bool, int>(true, 0),\r
6395                                [&first](std::pair<bool, int> res, decltype(*first) val)\r
6396         {\r
6397             res.first &= (val == *(std::next(std::addressof(*first), res.second++)));\r
6398             return res;\r
6399         }).first);\r
6400 \r
6401         // assertion to check that each element is 1 byte long\r
6402         static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,\r
6403                       "each element in the iterator range must have the size of 1 byte");\r
6404 \r
6405         // if iterator range is empty, create a parser with an empty string\r
6406         // to generate "unexpected EOF" error message\r
6407         if (std::distance(first, last) <= 0)\r
6408         {\r
6409             return parser("").parse();\r
6410         }\r
6411 \r
6412         return parser(first, last, cb).parse();\r
6413     }\r
6414 \r
6415     /*!\r
6416     @brief deserialize from a container with contiguous storage\r
6417 \r
6418     This function reads from a container with contiguous storage of 1-byte\r
6419     values. Compatible container types include `std::vector`, `std::string`,\r
6420     `std::array`, and `std::initializer_list`. User-defined containers can be\r
6421     used as long as they implement random-access iterators and a contiguous\r
6422     storage.\r
6423 \r
6424     @pre The container storage is contiguous. Violating this precondition\r
6425     yields undefined behavior. **This precondition is enforced with an\r
6426     assertion.**\r
6427     @pre Each element of the container has a size of 1 byte. Violating this\r
6428     precondition yields undefined behavior. **This precondition is enforced\r
6429     with a static assertion.**\r
6430 \r
6431     @warning There is no way to enforce all preconditions at compile-time. If\r
6432              the function is called with a noncompliant container and with\r
6433              assertions switched off, the behavior is undefined and will most\r
6434              likely yield segmentation violation.\r
6435 \r
6436     @tparam ContiguousContainer container type with contiguous storage\r
6437     @param[in] c  container to read from\r
6438     @param[in] cb  a parser callback function of type @ref parser_callback_t\r
6439     which is used to control the deserialization by filtering unwanted values\r
6440     (optional)\r
6441 \r
6442     @return result of the deserialization\r
6443 \r
6444     @complexity Linear in the length of the input. The parser is a predictive\r
6445     LL(1) parser. The complexity can be higher if the parser callback function\r
6446     @a cb has a super-linear complexity.\r
6447 \r
6448     @note A UTF-8 byte order mark is silently ignored.\r
6449 \r
6450     @liveexample{The example below demonstrates the `parse()` function reading\r
6451     from a contiguous container.,parse__contiguouscontainer__parser_callback_t}\r
6452 \r
6453     @since version 2.0.3\r
6454     */\r
6455     template<class ContiguousContainer, typename std::enable_if<\r
6456                  not std::is_pointer<ContiguousContainer>::value and\r
6457                  std::is_base_of<\r
6458                      std::random_access_iterator_tag,\r
6459                      typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value\r
6460                  , int>::type = 0>\r
6461     static basic_json parse(const ContiguousContainer& c,\r
6462                             const parser_callback_t cb = nullptr)\r
6463     {\r
6464         // delegate the call to the iterator-range parse overload\r
6465         return parse(std::begin(c), std::end(c), cb);\r
6466     }\r
6467 \r
6468     /*!\r
6469     @brief deserialize from stream\r
6470 \r
6471     Deserializes an input stream to a JSON value.\r
6472 \r
6473     @param[in,out] i  input stream to read a serialized JSON value from\r
6474     @param[in,out] j  JSON value to write the deserialized input to\r
6475 \r
6476     @throw std::invalid_argument in case of parse errors\r
6477 \r
6478     @complexity Linear in the length of the input. The parser is a predictive\r
6479     LL(1) parser.\r
6480 \r
6481     @note A UTF-8 byte order mark is silently ignored.\r
6482 \r
6483     @liveexample{The example below shows how a JSON value is constructed by\r
6484     reading a serialization from a stream.,operator_deserialize}\r
6485 \r
6486     @sa parse(std::istream&, const parser_callback_t) for a variant with a\r
6487     parser callback function to filter values while parsing\r
6488 \r
6489     @since version 1.0.0\r
6490     */\r
6491     friend std::istream& operator<<(basic_json& j, std::istream& i)\r
6492     {\r
6493         j = parser(i).parse();\r
6494         return i;\r
6495     }\r
6496 \r
6497     /*!\r
6498     @brief deserialize from stream\r
6499     @copydoc operator<<(basic_json&, std::istream&)\r
6500     */\r
6501     friend std::istream& operator>>(std::istream& i, basic_json& j)\r
6502     {\r
6503         j = parser(i).parse();\r
6504         return i;\r
6505     }\r
6506 \r
6507     /// @}\r
6508 \r
6509     //////////////////////////////////////////\r
6510     // binary serialization/deserialization //\r
6511     //////////////////////////////////////////\r
6512 \r
6513     /// @name binary serialization/deserialization support\r
6514     /// @{\r
6515 \r
6516   private:\r
6517     /*!\r
6518     @note Some code in the switch cases has been copied, because otherwise\r
6519           copilers would complain about implicit fallthrough and there is no\r
6520           portable attribute to mute such warnings.\r
6521     */\r
6522     template<typename T>\r
6523     static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)\r
6524     {\r
6525         assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);\r
6526 \r
6527         switch (bytes)\r
6528         {\r
6529             case 8:\r
6530             {\r
6531                 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 070) & 0xff));\r
6532                 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 060) & 0xff));\r
6533                 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 050) & 0xff));\r
6534                 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 040) & 0xff));\r
6535                 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));\r
6536                 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));\r
6537                 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));\r
6538                 vec.push_back(static_cast<uint8_t>(number & 0xff));\r
6539                 break;\r
6540             }\r
6541 \r
6542             case 4:\r
6543             {\r
6544                 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));\r
6545                 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));\r
6546                 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));\r
6547                 vec.push_back(static_cast<uint8_t>(number & 0xff));\r
6548                 break;\r
6549             }\r
6550 \r
6551             case 2:\r
6552             {\r
6553                 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));\r
6554                 vec.push_back(static_cast<uint8_t>(number & 0xff));\r
6555                 break;\r
6556             }\r
6557 \r
6558             case 1:\r
6559             {\r
6560                 vec.push_back(static_cast<uint8_t>(number & 0xff));\r
6561                 break;\r
6562             }\r
6563         }\r
6564     }\r
6565 \r
6566     /*!\r
6567     @brief take sufficient bytes from a vector to fill an integer variable\r
6568 \r
6569     In the context of binary serialization formats, we need to read several\r
6570     bytes from a byte vector and combine them to multi-byte integral data\r
6571     types.\r
6572 \r
6573     @param[in] vec  byte vector to read from\r
6574     @param[in] current_index  the position in the vector after which to read\r
6575 \r
6576     @return the next sizeof(T) bytes from @a vec, in reverse order as T\r
6577 \r
6578     @tparam T the integral return type\r
6579 \r
6580     @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the\r
6581            vector @a vec to read\r
6582 \r
6583     In the for loop, the bytes from the vector are copied in reverse order into\r
6584     the return value. In the figures below, let sizeof(T)=4 and `i` be the loop\r
6585     variable.\r
6586 \r
6587     Precondition:\r
6588 \r
6589     vec:   |   |   | a | b | c | d |      T: |   |   |   |   |\r
6590                  ^               ^             ^                ^\r
6591            current_index         i            ptr        sizeof(T)\r
6592 \r
6593     Postcondition:\r
6594 \r
6595     vec:   |   |   | a | b | c | d |      T: | d | c | b | a |\r
6596                  ^   ^                                     ^\r
6597                  |   i                                    ptr\r
6598            current_index\r
6599 \r
6600     @sa Code adapted from <http://stackoverflow.com/a/41031865/266378>.\r
6601     */\r
6602     template<typename T>\r
6603     static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)\r
6604     {\r
6605         if (current_index + sizeof(T) + 1 > vec.size())\r
6606         {\r
6607             JSON_THROW(std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector"));\r
6608         }\r
6609 \r
6610         T result;\r
6611         auto* ptr = reinterpret_cast<uint8_t*>(&result);\r
6612         for (size_t i = 0; i < sizeof(T); ++i)\r
6613         {\r
6614             *ptr++ = vec[current_index + sizeof(T) - i];\r
6615         }\r
6616         return result;\r
6617     }\r
6618 \r
6619     /*!\r
6620     @brief create a MessagePack serialization of a given JSON value\r
6621 \r
6622     This is a straightforward implementation of the MessagePack specification.\r
6623 \r
6624     @param[in] j  JSON value to serialize\r
6625     @param[in,out] v  byte vector to write the serialization to\r
6626 \r
6627     @sa https://github.com/msgpack/msgpack/blob/master/spec.md\r
6628     */\r
6629     static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)\r
6630     {\r
6631         switch (j.type())\r
6632         {\r
6633             case value_t::null:\r
6634             {\r
6635                 // nil\r
6636                 v.push_back(0xc0);\r
6637                 break;\r
6638             }\r
6639 \r
6640             case value_t::boolean:\r
6641             {\r
6642                 // true and false\r
6643                 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);\r
6644                 break;\r
6645             }\r
6646 \r
6647             case value_t::number_integer:\r
6648             {\r
6649                 if (j.m_value.number_integer >= 0)\r
6650                 {\r
6651                     // MessagePack does not differentiate between positive\r
6652                     // signed integers and unsigned integers. Therefore, we\r
6653                     // used the code from the value_t::number_unsigned case\r
6654                     // here.\r
6655                     if (j.m_value.number_unsigned < 128)\r
6656                     {\r
6657                         // positive fixnum\r
6658                         add_to_vector(v, 1, j.m_value.number_unsigned);\r
6659                     }\r
6660                     else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())\r
6661                     {\r
6662                         // uint 8\r
6663                         v.push_back(0xcc);\r
6664                         add_to_vector(v, 1, j.m_value.number_unsigned);\r
6665                     }\r
6666                     else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())\r
6667                     {\r
6668                         // uint 16\r
6669                         v.push_back(0xcd);\r
6670                         add_to_vector(v, 2, j.m_value.number_unsigned);\r
6671                     }\r
6672                     else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())\r
6673                     {\r
6674                         // uint 32\r
6675                         v.push_back(0xce);\r
6676                         add_to_vector(v, 4, j.m_value.number_unsigned);\r
6677                     }\r
6678                     else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())\r
6679                     {\r
6680                         // uint 64\r
6681                         v.push_back(0xcf);\r
6682                         add_to_vector(v, 8, j.m_value.number_unsigned);\r
6683                     }\r
6684                 }\r
6685                 else\r
6686                 {\r
6687                     if (j.m_value.number_integer >= -32)\r
6688                     {\r
6689                         // negative fixnum\r
6690                         add_to_vector(v, 1, j.m_value.number_integer);\r
6691                     }\r
6692                     else if (j.m_value.number_integer >= std::numeric_limits<int8_t>::min() and j.m_value.number_integer <= std::numeric_limits<int8_t>::max())\r
6693                     {\r
6694                         // int 8\r
6695                         v.push_back(0xd0);\r
6696                         add_to_vector(v, 1, j.m_value.number_integer);\r
6697                     }\r
6698                     else if (j.m_value.number_integer >= std::numeric_limits<int16_t>::min() and j.m_value.number_integer <= std::numeric_limits<int16_t>::max())\r
6699                     {\r
6700                         // int 16\r
6701                         v.push_back(0xd1);\r
6702                         add_to_vector(v, 2, j.m_value.number_integer);\r
6703                     }\r
6704                     else if (j.m_value.number_integer >= std::numeric_limits<int32_t>::min() and j.m_value.number_integer <= std::numeric_limits<int32_t>::max())\r
6705                     {\r
6706                         // int 32\r
6707                         v.push_back(0xd2);\r
6708                         add_to_vector(v, 4, j.m_value.number_integer);\r
6709                     }\r
6710                     else if (j.m_value.number_integer >= std::numeric_limits<int64_t>::min() and j.m_value.number_integer <= std::numeric_limits<int64_t>::max())\r
6711                     {\r
6712                         // int 64\r
6713                         v.push_back(0xd3);\r
6714                         add_to_vector(v, 8, j.m_value.number_integer);\r
6715                     }\r
6716                 }\r
6717                 break;\r
6718             }\r
6719 \r
6720             case value_t::number_unsigned:\r
6721             {\r
6722                 if (j.m_value.number_unsigned < 128)\r
6723                 {\r
6724                     // positive fixnum\r
6725                     add_to_vector(v, 1, j.m_value.number_unsigned);\r
6726                 }\r
6727                 else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())\r
6728                 {\r
6729                     // uint 8\r
6730                     v.push_back(0xcc);\r
6731                     add_to_vector(v, 1, j.m_value.number_unsigned);\r
6732                 }\r
6733                 else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())\r
6734                 {\r
6735                     // uint 16\r
6736                     v.push_back(0xcd);\r
6737                     add_to_vector(v, 2, j.m_value.number_unsigned);\r
6738                 }\r
6739                 else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())\r
6740                 {\r
6741                     // uint 32\r
6742                     v.push_back(0xce);\r
6743                     add_to_vector(v, 4, j.m_value.number_unsigned);\r
6744                 }\r
6745                 else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())\r
6746                 {\r
6747                     // uint 64\r
6748                     v.push_back(0xcf);\r
6749                     add_to_vector(v, 8, j.m_value.number_unsigned);\r
6750                 }\r
6751                 break;\r
6752             }\r
6753 \r
6754             case value_t::number_float:\r
6755             {\r
6756                 // float 64\r
6757                 v.push_back(0xcb);\r
6758                 const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));\r
6759                 for (size_t i = 0; i < 8; ++i)\r
6760                 {\r
6761                     v.push_back(helper[7 - i]);\r
6762                 }\r
6763                 break;\r
6764             }\r
6765 \r
6766             case value_t::string:\r
6767             {\r
6768                 const auto N = j.m_value.string->size();\r
6769                 if (N <= 31)\r
6770                 {\r
6771                     // fixstr\r
6772                     v.push_back(static_cast<uint8_t>(0xa0 | N));\r
6773                 }\r
6774                 else if (N <= 255)\r
6775                 {\r
6776                     // str 8\r
6777                     v.push_back(0xd9);\r
6778                     add_to_vector(v, 1, N);\r
6779                 }\r
6780                 else if (N <= 65535)\r
6781                 {\r
6782                     // str 16\r
6783                     v.push_back(0xda);\r
6784                     add_to_vector(v, 2, N);\r
6785                 }\r
6786                 else if (N <= 4294967295)\r
6787                 {\r
6788                     // str 32\r
6789                     v.push_back(0xdb);\r
6790                     add_to_vector(v, 4, N);\r
6791                 }\r
6792 \r
6793                 // append string\r
6794                 std::copy(j.m_value.string->begin(), j.m_value.string->end(),\r
6795                           std::back_inserter(v));\r
6796                 break;\r
6797             }\r
6798 \r
6799             case value_t::array:\r
6800             {\r
6801                 const auto N = j.m_value.array->size();\r
6802                 if (N <= 15)\r
6803                 {\r
6804                     // fixarray\r
6805                     v.push_back(static_cast<uint8_t>(0x90 | N));\r
6806                 }\r
6807                 else if (N <= 0xffff)\r
6808                 {\r
6809                     // array 16\r
6810                     v.push_back(0xdc);\r
6811                     add_to_vector(v, 2, N);\r
6812                 }\r
6813                 else if (N <= 0xffffffff)\r
6814                 {\r
6815                     // array 32\r
6816                     v.push_back(0xdd);\r
6817                     add_to_vector(v, 4, N);\r
6818                 }\r
6819 \r
6820                 // append each element\r
6821                 for (const auto& el : *j.m_value.array)\r
6822                 {\r
6823                     to_msgpack_internal(el, v);\r
6824                 }\r
6825                 break;\r
6826             }\r
6827 \r
6828             case value_t::object:\r
6829             {\r
6830                 const auto N = j.m_value.object->size();\r
6831                 if (N <= 15)\r
6832                 {\r
6833                     // fixmap\r
6834                     v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));\r
6835                 }\r
6836                 else if (N <= 65535)\r
6837                 {\r
6838                     // map 16\r
6839                     v.push_back(0xde);\r
6840                     add_to_vector(v, 2, N);\r
6841                 }\r
6842                 else if (N <= 4294967295)\r
6843                 {\r
6844                     // map 32\r
6845                     v.push_back(0xdf);\r
6846                     add_to_vector(v, 4, N);\r
6847                 }\r
6848 \r
6849                 // append each element\r
6850                 for (const auto& el : *j.m_value.object)\r
6851                 {\r
6852                     to_msgpack_internal(el.first, v);\r
6853                     to_msgpack_internal(el.second, v);\r
6854                 }\r
6855                 break;\r
6856             }\r
6857 \r
6858             default:\r
6859             {\r
6860                 break;\r
6861             }\r
6862         }\r
6863     }\r
6864 \r
6865     /*!\r
6866     @brief create a CBOR serialization of a given JSON value\r
6867 \r
6868     This is a straightforward implementation of the CBOR specification.\r
6869 \r
6870     @param[in] j  JSON value to serialize\r
6871     @param[in,out] v  byte vector to write the serialization to\r
6872 \r
6873     @sa https://tools.ietf.org/html/rfc7049\r
6874     */\r
6875     static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)\r
6876     {\r
6877         switch (j.type())\r
6878         {\r
6879             case value_t::null:\r
6880             {\r
6881                 v.push_back(0xf6);\r
6882                 break;\r
6883             }\r
6884 \r
6885             case value_t::boolean:\r
6886             {\r
6887                 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);\r
6888                 break;\r
6889             }\r
6890 \r
6891             case value_t::number_integer:\r
6892             {\r
6893                 if (j.m_value.number_integer >= 0)\r
6894                 {\r
6895                     // CBOR does not differentiate between positive signed\r
6896                     // integers and unsigned integers. Therefore, we used the\r
6897                     // code from the value_t::number_unsigned case here.\r
6898                     if (j.m_value.number_integer <= 0x17)\r
6899                     {\r
6900                         add_to_vector(v, 1, j.m_value.number_integer);\r
6901                     }\r
6902                     else if (j.m_value.number_integer <= std::numeric_limits<uint8_t>::max())\r
6903                     {\r
6904                         v.push_back(0x18);\r
6905                         // one-byte uint8_t\r
6906                         add_to_vector(v, 1, j.m_value.number_integer);\r
6907                     }\r
6908                     else if (j.m_value.number_integer <= std::numeric_limits<uint16_t>::max())\r
6909                     {\r
6910                         v.push_back(0x19);\r
6911                         // two-byte uint16_t\r
6912                         add_to_vector(v, 2, j.m_value.number_integer);\r
6913                     }\r
6914                     else if (j.m_value.number_integer <= std::numeric_limits<uint32_t>::max())\r
6915                     {\r
6916                         v.push_back(0x1a);\r
6917                         // four-byte uint32_t\r
6918                         add_to_vector(v, 4, j.m_value.number_integer);\r
6919                     }\r
6920                     else\r
6921                     {\r
6922                         v.push_back(0x1b);\r
6923                         // eight-byte uint64_t\r
6924                         add_to_vector(v, 8, j.m_value.number_integer);\r
6925                     }\r
6926                 }\r
6927                 else\r
6928                 {\r
6929                     // The conversions below encode the sign in the first\r
6930                     // byte, and the value is converted to a positive number.\r
6931                     const auto positive_number = -1 - j.m_value.number_integer;\r
6932                     if (j.m_value.number_integer >= -24)\r
6933                     {\r
6934                         v.push_back(static_cast<uint8_t>(0x20 + positive_number));\r
6935                     }\r
6936                     else if (positive_number <= std::numeric_limits<uint8_t>::max())\r
6937                     {\r
6938                         // int 8\r
6939                         v.push_back(0x38);\r
6940                         add_to_vector(v, 1, positive_number);\r
6941                     }\r
6942                     else if (positive_number <= std::numeric_limits<uint16_t>::max())\r
6943                     {\r
6944                         // int 16\r
6945                         v.push_back(0x39);\r
6946                         add_to_vector(v, 2, positive_number);\r
6947                     }\r
6948                     else if (positive_number <= std::numeric_limits<uint32_t>::max())\r
6949                     {\r
6950                         // int 32\r
6951                         v.push_back(0x3a);\r
6952                         add_to_vector(v, 4, positive_number);\r
6953                     }\r
6954                     else\r
6955                     {\r
6956                         // int 64\r
6957                         v.push_back(0x3b);\r
6958                         add_to_vector(v, 8, positive_number);\r
6959                     }\r
6960                 }\r
6961                 break;\r
6962             }\r
6963 \r
6964             case value_t::number_unsigned:\r
6965             {\r
6966                 if (j.m_value.number_unsigned <= 0x17)\r
6967                 {\r
6968                     v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));\r
6969                 }\r
6970                 else if (j.m_value.number_unsigned <= 0xff)\r
6971                 {\r
6972                     v.push_back(0x18);\r
6973                     // one-byte uint8_t\r
6974                     add_to_vector(v, 1, j.m_value.number_unsigned);\r
6975                 }\r
6976                 else if (j.m_value.number_unsigned <= 0xffff)\r
6977                 {\r
6978                     v.push_back(0x19);\r
6979                     // two-byte uint16_t\r
6980                     add_to_vector(v, 2, j.m_value.number_unsigned);\r
6981                 }\r
6982                 else if (j.m_value.number_unsigned <= 0xffffffff)\r
6983                 {\r
6984                     v.push_back(0x1a);\r
6985                     // four-byte uint32_t\r
6986                     add_to_vector(v, 4, j.m_value.number_unsigned);\r
6987                 }\r
6988                 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)\r
6989                 {\r
6990                     v.push_back(0x1b);\r
6991                     // eight-byte uint64_t\r
6992                     add_to_vector(v, 8, j.m_value.number_unsigned);\r
6993                 }\r
6994                 break;\r
6995             }\r
6996 \r
6997             case value_t::number_float:\r
6998             {\r
6999                 // Double-Precision Float\r
7000                 v.push_back(0xfb);\r
7001                 const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));\r
7002                 for (size_t i = 0; i < 8; ++i)\r
7003                 {\r
7004                     v.push_back(helper[7 - i]);\r
7005                 }\r
7006                 break;\r
7007             }\r
7008 \r
7009             case value_t::string:\r
7010             {\r
7011                 const auto N = j.m_value.string->size();\r
7012                 if (N <= 0x17)\r
7013                 {\r
7014                     v.push_back(0x60 + static_cast<uint8_t>(N));  // 1 byte for string + size\r
7015                 }\r
7016                 else if (N <= 0xff)\r
7017                 {\r
7018                     v.push_back(0x78);  // one-byte uint8_t for N\r
7019                     add_to_vector(v, 1, N);\r
7020                 }\r
7021                 else if (N <= 0xffff)\r
7022                 {\r
7023                     v.push_back(0x79);  // two-byte uint16_t for N\r
7024                     add_to_vector(v, 2, N);\r
7025                 }\r
7026                 else if (N <= 0xffffffff)\r
7027                 {\r
7028                     v.push_back(0x7a); // four-byte uint32_t for N\r
7029                     add_to_vector(v, 4, N);\r
7030                 }\r
7031                 // LCOV_EXCL_START\r
7032                 else if (N <= 0xffffffffffffffff)\r
7033                 {\r
7034                     v.push_back(0x7b);  // eight-byte uint64_t for N\r
7035                     add_to_vector(v, 8, N);\r
7036                 }\r
7037                 // LCOV_EXCL_STOP\r
7038 \r
7039                 // append string\r
7040                 std::copy(j.m_value.string->begin(), j.m_value.string->end(),\r
7041                           std::back_inserter(v));\r
7042                 break;\r
7043             }\r
7044 \r
7045             case value_t::array:\r
7046             {\r
7047                 const auto N = j.m_value.array->size();\r
7048                 if (N <= 0x17)\r
7049                 {\r
7050                     v.push_back(0x80 + static_cast<uint8_t>(N));  // 1 byte for array + size\r
7051                 }\r
7052                 else if (N <= 0xff)\r
7053                 {\r
7054                     v.push_back(0x98);  // one-byte uint8_t for N\r
7055                     add_to_vector(v, 1, N);\r
7056                 }\r
7057                 else if (N <= 0xffff)\r
7058                 {\r
7059                     v.push_back(0x99);  // two-byte uint16_t for N\r
7060                     add_to_vector(v, 2, N);\r
7061                 }\r
7062                 else if (N <= 0xffffffff)\r
7063                 {\r
7064                     v.push_back(0x9a);  // four-byte uint32_t for N\r
7065                     add_to_vector(v, 4, N);\r
7066                 }\r
7067                 // LCOV_EXCL_START\r
7068                 else if (N <= 0xffffffffffffffff)\r
7069                 {\r
7070                     v.push_back(0x9b);  // eight-byte uint64_t for N\r
7071                     add_to_vector(v, 8, N);\r
7072                 }\r
7073                 // LCOV_EXCL_STOP\r
7074 \r
7075                 // append each element\r
7076                 for (const auto& el : *j.m_value.array)\r
7077                 {\r
7078                     to_cbor_internal(el, v);\r
7079                 }\r
7080                 break;\r
7081             }\r
7082 \r
7083             case value_t::object:\r
7084             {\r
7085                 const auto N = j.m_value.object->size();\r
7086                 if (N <= 0x17)\r
7087                 {\r
7088                     v.push_back(0xa0 + static_cast<uint8_t>(N));  // 1 byte for object + size\r
7089                 }\r
7090                 else if (N <= 0xff)\r
7091                 {\r
7092                     v.push_back(0xb8);\r
7093                     add_to_vector(v, 1, N);  // one-byte uint8_t for N\r
7094                 }\r
7095                 else if (N <= 0xffff)\r
7096                 {\r
7097                     v.push_back(0xb9);\r
7098                     add_to_vector(v, 2, N);  // two-byte uint16_t for N\r
7099                 }\r
7100                 else if (N <= 0xffffffff)\r
7101                 {\r
7102                     v.push_back(0xba);\r
7103                     add_to_vector(v, 4, N);  // four-byte uint32_t for N\r
7104                 }\r
7105                 // LCOV_EXCL_START\r
7106                 else if (N <= 0xffffffffffffffff)\r
7107                 {\r
7108                     v.push_back(0xbb);\r
7109                     add_to_vector(v, 8, N);  // eight-byte uint64_t for N\r
7110                 }\r
7111                 // LCOV_EXCL_STOP\r
7112 \r
7113                 // append each element\r
7114                 for (const auto& el : *j.m_value.object)\r
7115                 {\r
7116                     to_cbor_internal(el.first, v);\r
7117                     to_cbor_internal(el.second, v);\r
7118                 }\r
7119                 break;\r
7120             }\r
7121 \r
7122             default:\r
7123             {\r
7124                 break;\r
7125             }\r
7126         }\r
7127     }\r
7128 \r
7129 \r
7130     /*\r
7131     @brief checks if given lengths do not exceed the size of a given vector\r
7132 \r
7133     To secure the access to the byte vector during CBOR/MessagePack\r
7134     deserialization, bytes are copied from the vector into buffers. This\r
7135     function checks if the number of bytes to copy (@a len) does not exceed\r
7136     the size @s size of the vector. Additionally, an @a offset is given from\r
7137     where to start reading the bytes.\r
7138 \r
7139     This function checks whether reading the bytes is safe; that is, offset is\r
7140     a valid index in the vector, offset+len\r
7141 \r
7142     @param[in] size    size of the byte vector\r
7143     @param[in] len     number of bytes to read\r
7144     @param[in] offset  offset where to start reading\r
7145 \r
7146     vec:  x x x x x X X X X X\r
7147           ^         ^         ^\r
7148           0         offset    len\r
7149 \r
7150     @throws out_of_range if `len > v.size()`\r
7151     */\r
7152     static void check_length(const size_t size, const size_t len, const size_t offset)\r
7153     {\r
7154         // simple case: requested length is greater than the vector's length\r
7155         if (len > size or offset > size)\r
7156         {\r
7157             JSON_THROW(std::out_of_range("len out of range"));\r
7158         }\r
7159 \r
7160         // second case: adding offset would result in overflow\r
7161         if ((size > (std::numeric_limits<size_t>::max() - offset)))\r
7162         {\r
7163             JSON_THROW(std::out_of_range("len+offset out of range"));\r
7164         }\r
7165 \r
7166         // last case: reading past the end of the vector\r
7167         if (len + offset > size)\r
7168         {\r
7169             JSON_THROW(std::out_of_range("len+offset out of range"));\r
7170         }\r
7171     }\r
7172 \r
7173     /*!\r
7174     @brief create a JSON value from a given MessagePack vector\r
7175 \r
7176     @param[in] v  MessagePack serialization\r
7177     @param[in] idx  byte index to start reading from @a v\r
7178 \r
7179     @return deserialized JSON value\r
7180 \r
7181     @throw std::invalid_argument if unsupported features from MessagePack were\r
7182     used in the given vector @a v or if the input is not valid MessagePack\r
7183     @throw std::out_of_range if the given vector ends prematurely\r
7184 \r
7185     @sa https://github.com/msgpack/msgpack/blob/master/spec.md\r
7186     */\r
7187     static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)\r
7188     {\r
7189         // make sure reading 1 byte is safe\r
7190         check_length(v.size(), 1, idx);\r
7191 \r
7192         // store and increment index\r
7193         const size_t current_idx = idx++;\r
7194 \r
7195         if (v[current_idx] <= 0xbf)\r
7196         {\r
7197             if (v[current_idx] <= 0x7f) // positive fixint\r
7198             {\r
7199                 return v[current_idx];\r
7200             }\r
7201             if (v[current_idx] <= 0x8f) // fixmap\r
7202             {\r
7203                 basic_json result = value_t::object;\r
7204                 const size_t len = v[current_idx] & 0x0f;\r
7205                 for (size_t i = 0; i < len; ++i)\r
7206                 {\r
7207                     std::string key = from_msgpack_internal(v, idx);\r
7208                     result[key] = from_msgpack_internal(v, idx);\r
7209                 }\r
7210                 return result;\r
7211             }\r
7212             else if (v[current_idx] <= 0x9f) // fixarray\r
7213             {\r
7214                 basic_json result = value_t::array;\r
7215                 const size_t len = v[current_idx] & 0x0f;\r
7216                 for (size_t i = 0; i < len; ++i)\r
7217                 {\r
7218                     result.push_back(from_msgpack_internal(v, idx));\r
7219                 }\r
7220                 return result;\r
7221             }\r
7222             else // fixstr\r
7223             {\r
7224                 const size_t len = v[current_idx] & 0x1f;\r
7225                 const size_t offset = current_idx + 1;\r
7226                 idx += len; // skip content bytes\r
7227                 check_length(v.size(), len, offset);\r
7228                 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7229             }\r
7230         }\r
7231         else if (v[current_idx] >= 0xe0) // negative fixint\r
7232         {\r
7233             return static_cast<int8_t>(v[current_idx]);\r
7234         }\r
7235         else\r
7236         {\r
7237             switch (v[current_idx])\r
7238             {\r
7239                 case 0xc0: // nil\r
7240                 {\r
7241                     return value_t::null;\r
7242                 }\r
7243 \r
7244                 case 0xc2: // false\r
7245                 {\r
7246                     return false;\r
7247                 }\r
7248 \r
7249                 case 0xc3: // true\r
7250                 {\r
7251                     return true;\r
7252                 }\r
7253 \r
7254                 case 0xca: // float 32\r
7255                 {\r
7256                     // copy bytes in reverse order into the double variable\r
7257                     float res;\r
7258                     for (size_t byte = 0; byte < sizeof(float); ++byte)\r
7259                     {\r
7260                         reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);\r
7261                     }\r
7262                     idx += sizeof(float); // skip content bytes\r
7263                     return res;\r
7264                 }\r
7265 \r
7266                 case 0xcb: // float 64\r
7267                 {\r
7268                     // copy bytes in reverse order into the double variable\r
7269                     double res;\r
7270                     for (size_t byte = 0; byte < sizeof(double); ++byte)\r
7271                     {\r
7272                         reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);\r
7273                     }\r
7274                     idx += sizeof(double); // skip content bytes\r
7275                     return res;\r
7276                 }\r
7277 \r
7278                 case 0xcc: // uint 8\r
7279                 {\r
7280                     idx += 1; // skip content byte\r
7281                     return get_from_vector<uint8_t>(v, current_idx);\r
7282                 }\r
7283 \r
7284                 case 0xcd: // uint 16\r
7285                 {\r
7286                     idx += 2; // skip 2 content bytes\r
7287                     return get_from_vector<uint16_t>(v, current_idx);\r
7288                 }\r
7289 \r
7290                 case 0xce: // uint 32\r
7291                 {\r
7292                     idx += 4; // skip 4 content bytes\r
7293                     return get_from_vector<uint32_t>(v, current_idx);\r
7294                 }\r
7295 \r
7296                 case 0xcf: // uint 64\r
7297                 {\r
7298                     idx += 8; // skip 8 content bytes\r
7299                     return get_from_vector<uint64_t>(v, current_idx);\r
7300                 }\r
7301 \r
7302                 case 0xd0: // int 8\r
7303                 {\r
7304                     idx += 1; // skip content byte\r
7305                     return get_from_vector<int8_t>(v, current_idx);\r
7306                 }\r
7307 \r
7308                 case 0xd1: // int 16\r
7309                 {\r
7310                     idx += 2; // skip 2 content bytes\r
7311                     return get_from_vector<int16_t>(v, current_idx);\r
7312                 }\r
7313 \r
7314                 case 0xd2: // int 32\r
7315                 {\r
7316                     idx += 4; // skip 4 content bytes\r
7317                     return get_from_vector<int32_t>(v, current_idx);\r
7318                 }\r
7319 \r
7320                 case 0xd3: // int 64\r
7321                 {\r
7322                     idx += 8; // skip 8 content bytes\r
7323                     return get_from_vector<int64_t>(v, current_idx);\r
7324                 }\r
7325 \r
7326                 case 0xd9: // str 8\r
7327                 {\r
7328                     const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));\r
7329                     const size_t offset = current_idx + 2;\r
7330                     idx += len + 1; // skip size byte + content bytes\r
7331                     check_length(v.size(), len, offset);\r
7332                     return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7333                 }\r
7334 \r
7335                 case 0xda: // str 16\r
7336                 {\r
7337                     const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));\r
7338                     const size_t offset = current_idx + 3;\r
7339                     idx += len + 2; // skip 2 size bytes + content bytes\r
7340                     check_length(v.size(), len, offset);\r
7341                     return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7342                 }\r
7343 \r
7344                 case 0xdb: // str 32\r
7345                 {\r
7346                     const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));\r
7347                     const size_t offset = current_idx + 5;\r
7348                     idx += len + 4; // skip 4 size bytes + content bytes\r
7349                     check_length(v.size(), len, offset);\r
7350                     return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7351                 }\r
7352 \r
7353                 case 0xdc: // array 16\r
7354                 {\r
7355                     basic_json result = value_t::array;\r
7356                     const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));\r
7357                     idx += 2; // skip 2 size bytes\r
7358                     for (size_t i = 0; i < len; ++i)\r
7359                     {\r
7360                         result.push_back(from_msgpack_internal(v, idx));\r
7361                     }\r
7362                     return result;\r
7363                 }\r
7364 \r
7365                 case 0xdd: // array 32\r
7366                 {\r
7367                     basic_json result = value_t::array;\r
7368                     const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));\r
7369                     idx += 4; // skip 4 size bytes\r
7370                     for (size_t i = 0; i < len; ++i)\r
7371                     {\r
7372                         result.push_back(from_msgpack_internal(v, idx));\r
7373                     }\r
7374                     return result;\r
7375                 }\r
7376 \r
7377                 case 0xde: // map 16\r
7378                 {\r
7379                     basic_json result = value_t::object;\r
7380                     const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));\r
7381                     idx += 2; // skip 2 size bytes\r
7382                     for (size_t i = 0; i < len; ++i)\r
7383                     {\r
7384                         std::string key = from_msgpack_internal(v, idx);\r
7385                         result[key] = from_msgpack_internal(v, idx);\r
7386                     }\r
7387                     return result;\r
7388                 }\r
7389 \r
7390                 case 0xdf: // map 32\r
7391                 {\r
7392                     basic_json result = value_t::object;\r
7393                     const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));\r
7394                     idx += 4; // skip 4 size bytes\r
7395                     for (size_t i = 0; i < len; ++i)\r
7396                     {\r
7397                         std::string key = from_msgpack_internal(v, idx);\r
7398                         result[key] = from_msgpack_internal(v, idx);\r
7399                     }\r
7400                     return result;\r
7401                 }\r
7402 \r
7403                 default:\r
7404                 {\r
7405                     JSON_THROW(std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));\r
7406                 }\r
7407             }\r
7408         }\r
7409     }\r
7410 \r
7411     /*!\r
7412     @brief create a JSON value from a given CBOR vector\r
7413 \r
7414     @param[in] v  CBOR serialization\r
7415     @param[in] idx  byte index to start reading from @a v\r
7416 \r
7417     @return deserialized JSON value\r
7418 \r
7419     @throw std::invalid_argument if unsupported features from CBOR were used in\r
7420     the given vector @a v or if the input is not valid CBOR\r
7421     @throw std::out_of_range if the given vector ends prematurely\r
7422 \r
7423     @sa https://tools.ietf.org/html/rfc7049\r
7424     */\r
7425     static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)\r
7426     {\r
7427         // store and increment index\r
7428         const size_t current_idx = idx++;\r
7429 \r
7430         switch (v.at(current_idx))\r
7431         {\r
7432             // Integer 0x00..0x17 (0..23)\r
7433             case 0x00:\r
7434             case 0x01:\r
7435             case 0x02:\r
7436             case 0x03:\r
7437             case 0x04:\r
7438             case 0x05:\r
7439             case 0x06:\r
7440             case 0x07:\r
7441             case 0x08:\r
7442             case 0x09:\r
7443             case 0x0a:\r
7444             case 0x0b:\r
7445             case 0x0c:\r
7446             case 0x0d:\r
7447             case 0x0e:\r
7448             case 0x0f:\r
7449             case 0x10:\r
7450             case 0x11:\r
7451             case 0x12:\r
7452             case 0x13:\r
7453             case 0x14:\r
7454             case 0x15:\r
7455             case 0x16:\r
7456             case 0x17:\r
7457             {\r
7458                 return v[current_idx];\r
7459             }\r
7460 \r
7461             case 0x18: // Unsigned integer (one-byte uint8_t follows)\r
7462             {\r
7463                 idx += 1; // skip content byte\r
7464                 return get_from_vector<uint8_t>(v, current_idx);\r
7465             }\r
7466 \r
7467             case 0x19: // Unsigned integer (two-byte uint16_t follows)\r
7468             {\r
7469                 idx += 2; // skip 2 content bytes\r
7470                 return get_from_vector<uint16_t>(v, current_idx);\r
7471             }\r
7472 \r
7473             case 0x1a: // Unsigned integer (four-byte uint32_t follows)\r
7474             {\r
7475                 idx += 4; // skip 4 content bytes\r
7476                 return get_from_vector<uint32_t>(v, current_idx);\r
7477             }\r
7478 \r
7479             case 0x1b: // Unsigned integer (eight-byte uint64_t follows)\r
7480             {\r
7481                 idx += 8; // skip 8 content bytes\r
7482                 return get_from_vector<uint64_t>(v, current_idx);\r
7483             }\r
7484 \r
7485             // Negative integer -1-0x00..-1-0x17 (-1..-24)\r
7486             case 0x20:\r
7487             case 0x21:\r
7488             case 0x22:\r
7489             case 0x23:\r
7490             case 0x24:\r
7491             case 0x25:\r
7492             case 0x26:\r
7493             case 0x27:\r
7494             case 0x28:\r
7495             case 0x29:\r
7496             case 0x2a:\r
7497             case 0x2b:\r
7498             case 0x2c:\r
7499             case 0x2d:\r
7500             case 0x2e:\r
7501             case 0x2f:\r
7502             case 0x30:\r
7503             case 0x31:\r
7504             case 0x32:\r
7505             case 0x33:\r
7506             case 0x34:\r
7507             case 0x35:\r
7508             case 0x36:\r
7509             case 0x37:\r
7510             {\r
7511                 return static_cast<int8_t>(0x20 - 1 - v[current_idx]);\r
7512             }\r
7513 \r
7514             case 0x38: // Negative integer (one-byte uint8_t follows)\r
7515             {\r
7516                 idx += 1; // skip content byte\r
7517                 // must be uint8_t !\r
7518                 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);\r
7519             }\r
7520 \r
7521             case 0x39: // Negative integer -1-n (two-byte uint16_t follows)\r
7522             {\r
7523                 idx += 2; // skip 2 content bytes\r
7524                 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);\r
7525             }\r
7526 \r
7527             case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)\r
7528             {\r
7529                 idx += 4; // skip 4 content bytes\r
7530                 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);\r
7531             }\r
7532 \r
7533             case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)\r
7534             {\r
7535                 idx += 8; // skip 8 content bytes\r
7536                 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));\r
7537             }\r
7538 \r
7539             // UTF-8 string (0x00..0x17 bytes follow)\r
7540             case 0x60:\r
7541             case 0x61:\r
7542             case 0x62:\r
7543             case 0x63:\r
7544             case 0x64:\r
7545             case 0x65:\r
7546             case 0x66:\r
7547             case 0x67:\r
7548             case 0x68:\r
7549             case 0x69:\r
7550             case 0x6a:\r
7551             case 0x6b:\r
7552             case 0x6c:\r
7553             case 0x6d:\r
7554             case 0x6e:\r
7555             case 0x6f:\r
7556             case 0x70:\r
7557             case 0x71:\r
7558             case 0x72:\r
7559             case 0x73:\r
7560             case 0x74:\r
7561             case 0x75:\r
7562             case 0x76:\r
7563             case 0x77:\r
7564             {\r
7565                 const auto len = static_cast<size_t>(v[current_idx] - 0x60);\r
7566                 const size_t offset = current_idx + 1;\r
7567                 idx += len; // skip content bytes\r
7568                 check_length(v.size(), len, offset);\r
7569                 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7570             }\r
7571 \r
7572             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)\r
7573             {\r
7574                 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));\r
7575                 const size_t offset = current_idx + 2;\r
7576                 idx += len + 1; // skip size byte + content bytes\r
7577                 check_length(v.size(), len, offset);\r
7578                 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7579             }\r
7580 \r
7581             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)\r
7582             {\r
7583                 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));\r
7584                 const size_t offset = current_idx + 3;\r
7585                 idx += len + 2; // skip 2 size bytes + content bytes\r
7586                 check_length(v.size(), len, offset);\r
7587                 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7588             }\r
7589 \r
7590             case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)\r
7591             {\r
7592                 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));\r
7593                 const size_t offset = current_idx + 5;\r
7594                 idx += len + 4; // skip 4 size bytes + content bytes\r
7595                 check_length(v.size(), len, offset);\r
7596                 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7597             }\r
7598 \r
7599             case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)\r
7600             {\r
7601                 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));\r
7602                 const size_t offset = current_idx + 9;\r
7603                 idx += len + 8; // skip 8 size bytes + content bytes\r
7604                 check_length(v.size(), len, offset);\r
7605                 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);\r
7606             }\r
7607 \r
7608             case 0x7f: // UTF-8 string (indefinite length)\r
7609             {\r
7610                 std::string result;\r
7611                 while (v.at(idx) != 0xff)\r
7612                 {\r
7613                     string_t s = from_cbor_internal(v, idx);\r
7614                     result += s;\r
7615                 }\r
7616                 // skip break byte (0xFF)\r
7617                 idx += 1;\r
7618                 return result;\r
7619             }\r
7620 \r
7621             // array (0x00..0x17 data items follow)\r
7622             case 0x80:\r
7623             case 0x81:\r
7624             case 0x82:\r
7625             case 0x83:\r
7626             case 0x84:\r
7627             case 0x85:\r
7628             case 0x86:\r
7629             case 0x87:\r
7630             case 0x88:\r
7631             case 0x89:\r
7632             case 0x8a:\r
7633             case 0x8b:\r
7634             case 0x8c:\r
7635             case 0x8d:\r
7636             case 0x8e:\r
7637             case 0x8f:\r
7638             case 0x90:\r
7639             case 0x91:\r
7640             case 0x92:\r
7641             case 0x93:\r
7642             case 0x94:\r
7643             case 0x95:\r
7644             case 0x96:\r
7645             case 0x97:\r
7646             {\r
7647                 basic_json result = value_t::array;\r
7648                 const auto len = static_cast<size_t>(v[current_idx] - 0x80);\r
7649                 for (size_t i = 0; i < len; ++i)\r
7650                 {\r
7651                     result.push_back(from_cbor_internal(v, idx));\r
7652                 }\r
7653                 return result;\r
7654             }\r
7655 \r
7656             case 0x98: // array (one-byte uint8_t for n follows)\r
7657             {\r
7658                 basic_json result = value_t::array;\r
7659                 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));\r
7660                 idx += 1; // skip 1 size byte\r
7661                 for (size_t i = 0; i < len; ++i)\r
7662                 {\r
7663                     result.push_back(from_cbor_internal(v, idx));\r
7664                 }\r
7665                 return result;\r
7666             }\r
7667 \r
7668             case 0x99: // array (two-byte uint16_t for n follow)\r
7669             {\r
7670                 basic_json result = value_t::array;\r
7671                 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));\r
7672                 idx += 2; // skip 4 size bytes\r
7673                 for (size_t i = 0; i < len; ++i)\r
7674                 {\r
7675                     result.push_back(from_cbor_internal(v, idx));\r
7676                 }\r
7677                 return result;\r
7678             }\r
7679 \r
7680             case 0x9a: // array (four-byte uint32_t for n follow)\r
7681             {\r
7682                 basic_json result = value_t::array;\r
7683                 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));\r
7684                 idx += 4; // skip 4 size bytes\r
7685                 for (size_t i = 0; i < len; ++i)\r
7686                 {\r
7687                     result.push_back(from_cbor_internal(v, idx));\r
7688                 }\r
7689                 return result;\r
7690             }\r
7691 \r
7692             case 0x9b: // array (eight-byte uint64_t for n follow)\r
7693             {\r
7694                 basic_json result = value_t::array;\r
7695                 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));\r
7696                 idx += 8; // skip 8 size bytes\r
7697                 for (size_t i = 0; i < len; ++i)\r
7698                 {\r
7699                     result.push_back(from_cbor_internal(v, idx));\r
7700                 }\r
7701                 return result;\r
7702             }\r
7703 \r
7704             case 0x9f: // array (indefinite length)\r
7705             {\r
7706                 basic_json result = value_t::array;\r
7707                 while (v.at(idx) != 0xff)\r
7708                 {\r
7709                     result.push_back(from_cbor_internal(v, idx));\r
7710                 }\r
7711                 // skip break byte (0xFF)\r
7712                 idx += 1;\r
7713                 return result;\r
7714             }\r
7715 \r
7716             // map (0x00..0x17 pairs of data items follow)\r
7717             case 0xa0:\r
7718             case 0xa1:\r
7719             case 0xa2:\r
7720             case 0xa3:\r
7721             case 0xa4:\r
7722             case 0xa5:\r
7723             case 0xa6:\r
7724             case 0xa7:\r
7725             case 0xa8:\r
7726             case 0xa9:\r
7727             case 0xaa:\r
7728             case 0xab:\r
7729             case 0xac:\r
7730             case 0xad:\r
7731             case 0xae:\r
7732             case 0xaf:\r
7733             case 0xb0:\r
7734             case 0xb1:\r
7735             case 0xb2:\r
7736             case 0xb3:\r
7737             case 0xb4:\r
7738             case 0xb5:\r
7739             case 0xb6:\r
7740             case 0xb7:\r
7741             {\r
7742                 basic_json result = value_t::object;\r
7743                 const auto len = static_cast<size_t>(v[current_idx] - 0xa0);\r
7744                 for (size_t i = 0; i < len; ++i)\r
7745                 {\r
7746                     std::string key = from_cbor_internal(v, idx);\r
7747                     result[key] = from_cbor_internal(v, idx);\r
7748                 }\r
7749                 return result;\r
7750             }\r
7751 \r
7752             case 0xb8: // map (one-byte uint8_t for n follows)\r
7753             {\r
7754                 basic_json result = value_t::object;\r
7755                 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));\r
7756                 idx += 1; // skip 1 size byte\r
7757                 for (size_t i = 0; i < len; ++i)\r
7758                 {\r
7759                     std::string key = from_cbor_internal(v, idx);\r
7760                     result[key] = from_cbor_internal(v, idx);\r
7761                 }\r
7762                 return result;\r
7763             }\r
7764 \r
7765             case 0xb9: // map (two-byte uint16_t for n follow)\r
7766             {\r
7767                 basic_json result = value_t::object;\r
7768                 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));\r
7769                 idx += 2; // skip 2 size bytes\r
7770                 for (size_t i = 0; i < len; ++i)\r
7771                 {\r
7772                     std::string key = from_cbor_internal(v, idx);\r
7773                     result[key] = from_cbor_internal(v, idx);\r
7774                 }\r
7775                 return result;\r
7776             }\r
7777 \r
7778             case 0xba: // map (four-byte uint32_t for n follow)\r
7779             {\r
7780                 basic_json result = value_t::object;\r
7781                 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));\r
7782                 idx += 4; // skip 4 size bytes\r
7783                 for (size_t i = 0; i < len; ++i)\r
7784                 {\r
7785                     std::string key = from_cbor_internal(v, idx);\r
7786                     result[key] = from_cbor_internal(v, idx);\r
7787                 }\r
7788                 return result;\r
7789             }\r
7790 \r
7791             case 0xbb: // map (eight-byte uint64_t for n follow)\r
7792             {\r
7793                 basic_json result = value_t::object;\r
7794                 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));\r
7795                 idx += 8; // skip 8 size bytes\r
7796                 for (size_t i = 0; i < len; ++i)\r
7797                 {\r
7798                     std::string key = from_cbor_internal(v, idx);\r
7799                     result[key] = from_cbor_internal(v, idx);\r
7800                 }\r
7801                 return result;\r
7802             }\r
7803 \r
7804             case 0xbf: // map (indefinite length)\r
7805             {\r
7806                 basic_json result = value_t::object;\r
7807                 while (v.at(idx) != 0xff)\r
7808                 {\r
7809                     std::string key = from_cbor_internal(v, idx);\r
7810                     result[key] = from_cbor_internal(v, idx);\r
7811                 }\r
7812                 // skip break byte (0xFF)\r
7813                 idx += 1;\r
7814                 return result;\r
7815             }\r
7816 \r
7817             case 0xf4: // false\r
7818             {\r
7819                 return false;\r
7820             }\r
7821 \r
7822             case 0xf5: // true\r
7823             {\r
7824                 return true;\r
7825             }\r
7826 \r
7827             case 0xf6: // null\r
7828             {\r
7829                 return value_t::null;\r
7830             }\r
7831 \r
7832             case 0xf9: // Half-Precision Float (two-byte IEEE 754)\r
7833             {\r
7834                 idx += 2; // skip two content bytes\r
7835 \r
7836                 // code from RFC 7049, Appendix D, Figure 3:\r
7837                 // As half-precision floating-point numbers were only added to\r
7838                 // IEEE 754 in 2008, today's programming platforms often still\r
7839                 // only have limited support for them. It is very easy to\r
7840                 // include at least decoding support for them even without such\r
7841                 // support. An example of a small decoder for half-precision\r
7842                 // floating-point numbers in the C language is shown in Fig. 3.\r
7843                 const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);\r
7844                 const int exp = (half >> 10) & 0x1f;\r
7845                 const int mant = half & 0x3ff;\r
7846                 double val;\r
7847                 if (exp == 0)\r
7848                 {\r
7849                     val = std::ldexp(mant, -24);\r
7850                 }\r
7851                 else if (exp != 31)\r
7852                 {\r
7853                     val = std::ldexp(mant + 1024, exp - 25);\r
7854                 }\r
7855                 else\r
7856                 {\r
7857                     val = mant == 0\r
7858                           ? std::numeric_limits<double>::infinity()\r
7859                           : std::numeric_limits<double>::quiet_NaN();\r
7860                 }\r
7861                 return (half & 0x8000) != 0 ? -val : val;\r
7862             }\r
7863 \r
7864             case 0xfa: // Single-Precision Float (four-byte IEEE 754)\r
7865             {\r
7866                 // copy bytes in reverse order into the float variable\r
7867                 float res;\r
7868                 for (size_t byte = 0; byte < sizeof(float); ++byte)\r
7869                 {\r
7870                     reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);\r
7871                 }\r
7872                 idx += sizeof(float); // skip content bytes\r
7873                 return res;\r
7874             }\r
7875 \r
7876             case 0xfb: // Double-Precision Float (eight-byte IEEE 754)\r
7877             {\r
7878                 // copy bytes in reverse order into the double variable\r
7879                 double res;\r
7880                 for (size_t byte = 0; byte < sizeof(double); ++byte)\r
7881                 {\r
7882                     reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);\r
7883                 }\r
7884                 idx += sizeof(double); // skip content bytes\r
7885                 return res;\r
7886             }\r
7887 \r
7888             default: // anything else (0xFF is handled inside the other types)\r
7889             {\r
7890                 JSON_THROW(std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));\r
7891             }\r
7892         }\r
7893     }\r
7894 \r
7895   public:\r
7896     /*!\r
7897     @brief create a MessagePack serialization of a given JSON value\r
7898 \r
7899     Serializes a given JSON value @a j to a byte vector using the MessagePack\r
7900     serialization format. MessagePack is a binary serialization format which\r
7901     aims to be more compact than JSON itself, yet more efficient to parse.\r
7902 \r
7903     @param[in] j  JSON value to serialize\r
7904     @return MessagePack serialization as byte vector\r
7905 \r
7906     @complexity Linear in the size of the JSON value @a j.\r
7907 \r
7908     @liveexample{The example shows the serialization of a JSON value to a byte\r
7909     vector in MessagePack format.,to_msgpack}\r
7910 \r
7911     @sa http://msgpack.org\r
7912     @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the\r
7913         analogous deserialization\r
7914     @sa @ref to_cbor(const basic_json& for the related CBOR format\r
7915 \r
7916     @since version 2.0.9\r
7917     */\r
7918     static std::vector<uint8_t> to_msgpack(const basic_json& j)\r
7919     {\r
7920         std::vector<uint8_t> result;\r
7921         to_msgpack_internal(j, result);\r
7922         return result;\r
7923     }\r
7924 \r
7925     /*!\r
7926     @brief create a JSON value from a byte vector in MessagePack format\r
7927 \r
7928     Deserializes a given byte vector @a v to a JSON value using the MessagePack\r
7929     serialization format.\r
7930 \r
7931     @param[in] v  a byte vector in MessagePack format\r
7932     @param[in] start_index the index to start reading from @a v (0 by default)\r
7933     @return deserialized JSON value\r
7934 \r
7935     @throw std::invalid_argument if unsupported features from MessagePack were\r
7936     used in the given vector @a v or if the input is not valid MessagePack\r
7937     @throw std::out_of_range if the given vector ends prematurely\r
7938 \r
7939     @complexity Linear in the size of the byte vector @a v.\r
7940 \r
7941     @liveexample{The example shows the deserialization of a byte vector in\r
7942     MessagePack format to a JSON value.,from_msgpack}\r
7943 \r
7944     @sa http://msgpack.org\r
7945     @sa @ref to_msgpack(const basic_json&) for the analogous serialization\r
7946     @sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the\r
7947         related CBOR format\r
7948 \r
7949     @since version 2.0.9, parameter @a start_index since 2.1.1\r
7950     */\r
7951     static basic_json from_msgpack(const std::vector<uint8_t>& v,\r
7952                                    const size_t start_index = 0)\r
7953     {\r
7954         size_t i = start_index;\r
7955         return from_msgpack_internal(v, i);\r
7956     }\r
7957 \r
7958     /*!\r
7959     @brief create a MessagePack serialization of a given JSON value\r
7960 \r
7961     Serializes a given JSON value @a j to a byte vector using the CBOR (Concise\r
7962     Binary Object Representation) serialization format. CBOR is a binary\r
7963     serialization format which aims to be more compact than JSON itself, yet\r
7964     more efficient to parse.\r
7965 \r
7966     @param[in] j  JSON value to serialize\r
7967     @return MessagePack serialization as byte vector\r
7968 \r
7969     @complexity Linear in the size of the JSON value @a j.\r
7970 \r
7971     @liveexample{The example shows the serialization of a JSON value to a byte\r
7972     vector in CBOR format.,to_cbor}\r
7973 \r
7974     @sa http://cbor.io\r
7975     @sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the\r
7976         analogous deserialization\r
7977     @sa @ref to_msgpack(const basic_json& for the related MessagePack format\r
7978 \r
7979     @since version 2.0.9\r
7980     */\r
7981     static std::vector<uint8_t> to_cbor(const basic_json& j)\r
7982     {\r
7983         std::vector<uint8_t> result;\r
7984         to_cbor_internal(j, result);\r
7985         return result;\r
7986     }\r
7987 \r
7988     /*!\r
7989     @brief create a JSON value from a byte vector in CBOR format\r
7990 \r
7991     Deserializes a given byte vector @a v to a JSON value using the CBOR\r
7992     (Concise Binary Object Representation) serialization format.\r
7993 \r
7994     @param[in] v  a byte vector in CBOR format\r
7995     @param[in] start_index the index to start reading from @a v (0 by default)\r
7996     @return deserialized JSON value\r
7997 \r
7998     @throw std::invalid_argument if unsupported features from CBOR were used in\r
7999     the given vector @a v or if the input is not valid MessagePack\r
8000     @throw std::out_of_range if the given vector ends prematurely\r
8001 \r
8002     @complexity Linear in the size of the byte vector @a v.\r
8003 \r
8004     @liveexample{The example shows the deserialization of a byte vector in CBOR\r
8005     format to a JSON value.,from_cbor}\r
8006 \r
8007     @sa http://cbor.io\r
8008     @sa @ref to_cbor(const basic_json&) for the analogous serialization\r
8009     @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the\r
8010         related MessagePack format\r
8011 \r
8012     @since version 2.0.9, parameter @a start_index since 2.1.1\r
8013     */\r
8014     static basic_json from_cbor(const std::vector<uint8_t>& v,\r
8015                                 const size_t start_index = 0)\r
8016     {\r
8017         size_t i = start_index;\r
8018         return from_cbor_internal(v, i);\r
8019     }\r
8020 \r
8021     /// @}\r
8022 \r
8023     ///////////////////////////\r
8024     // convenience functions //\r
8025     ///////////////////////////\r
8026 \r
8027     /*!\r
8028     @brief return the type as string\r
8029 \r
8030     Returns the type name as string to be used in error messages - usually to\r
8031     indicate that a function was called on a wrong JSON type.\r
8032 \r
8033     @return basically a string representation of a the @a m_type member\r
8034 \r
8035     @complexity Constant.\r
8036 \r
8037     @liveexample{The following code exemplifies `type_name()` for all JSON\r
8038     types.,type_name}\r
8039 \r
8040     @since version 1.0.0, public since 2.1.0\r
8041     */\r
8042     std::string type_name() const\r
8043     {\r
8044         {\r
8045             switch (m_type)\r
8046             {\r
8047                 case value_t::null:\r
8048                     return "null";\r
8049                 case value_t::object:\r
8050                     return "object";\r
8051                 case value_t::array:\r
8052                     return "array";\r
8053                 case value_t::string:\r
8054                     return "string";\r
8055                 case value_t::boolean:\r
8056                     return "boolean";\r
8057                 case value_t::discarded:\r
8058                     return "discarded";\r
8059                 default:\r
8060                     return "number";\r
8061             }\r
8062         }\r
8063     }\r
8064 \r
8065   private:\r
8066     /*!\r
8067     @brief calculates the extra space to escape a JSON string\r
8068 \r
8069     @param[in] s  the string to escape\r
8070     @return the number of characters required to escape string @a s\r
8071 \r
8072     @complexity Linear in the length of string @a s.\r
8073     */\r
8074     static std::size_t extra_space(const string_t& s) noexcept\r
8075     {\r
8076         return std::accumulate(s.begin(), s.end(), size_t{},\r
8077                                [](size_t res, typename string_t::value_type c)\r
8078         {\r
8079             switch (c)\r
8080             {\r
8081                 case '"':\r
8082                 case '\\':\r
8083                 case '\b':\r
8084                 case '\f':\r
8085                 case '\n':\r
8086                 case '\r':\r
8087                 case '\t':\r
8088                 {\r
8089                     // from c (1 byte) to \x (2 bytes)\r
8090                     return res + 1;\r
8091                 }\r
8092 \r
8093                 default:\r
8094                 {\r
8095                     if (c >= 0x00 and c <= 0x1f)\r
8096                     {\r
8097                         // from c (1 byte) to \uxxxx (6 bytes)\r
8098                         return res + 5;\r
8099                     }\r
8100 \r
8101                     return res;\r
8102                 }\r
8103             }\r
8104         });\r
8105     }\r
8106 \r
8107     /*!\r
8108     @brief escape a string\r
8109 \r
8110     Escape a string by replacing certain special characters by a sequence of\r
8111     an escape character (backslash) and another character and other control\r
8112     characters by a sequence of "\u" followed by a four-digit hex\r
8113     representation.\r
8114 \r
8115     @param[in] s  the string to escape\r
8116     @return  the escaped string\r
8117 \r
8118     @complexity Linear in the length of string @a s.\r
8119     */\r
8120     static string_t escape_string(const string_t& s)\r
8121     {\r
8122         const auto space = extra_space(s);\r
8123         if (space == 0)\r
8124         {\r
8125             return s;\r
8126         }\r
8127 \r
8128         // create a result string of necessary size\r
8129         string_t result(s.size() + space, '\\');\r
8130         std::size_t pos = 0;\r
8131 \r
8132         for (const auto& c : s)\r
8133         {\r
8134             switch (c)\r
8135             {\r
8136                 // quotation mark (0x22)\r
8137                 case '"':\r
8138                 {\r
8139                     result[pos + 1] = '"';\r
8140                     pos += 2;\r
8141                     break;\r
8142                 }\r
8143 \r
8144                 // reverse solidus (0x5c)\r
8145                 case '\\':\r
8146                 {\r
8147                     // nothing to change\r
8148                     pos += 2;\r
8149                     break;\r
8150                 }\r
8151 \r
8152                 // backspace (0x08)\r
8153                 case '\b':\r
8154                 {\r
8155                     result[pos + 1] = 'b';\r
8156                     pos += 2;\r
8157                     break;\r
8158                 }\r
8159 \r
8160                 // formfeed (0x0c)\r
8161                 case '\f':\r
8162                 {\r
8163                     result[pos + 1] = 'f';\r
8164                     pos += 2;\r
8165                     break;\r
8166                 }\r
8167 \r
8168                 // newline (0x0a)\r
8169                 case '\n':\r
8170                 {\r
8171                     result[pos + 1] = 'n';\r
8172                     pos += 2;\r
8173                     break;\r
8174                 }\r
8175 \r
8176                 // carriage return (0x0d)\r
8177                 case '\r':\r
8178                 {\r
8179                     result[pos + 1] = 'r';\r
8180                     pos += 2;\r
8181                     break;\r
8182                 }\r
8183 \r
8184                 // horizontal tab (0x09)\r
8185                 case '\t':\r
8186                 {\r
8187                     result[pos + 1] = 't';\r
8188                     pos += 2;\r
8189                     break;\r
8190                 }\r
8191 \r
8192                 default:\r
8193                 {\r
8194                     if (c >= 0x00 and c <= 0x1f)\r
8195                     {\r
8196                         // convert a number 0..15 to its hex representation\r
8197                         // (0..f)\r
8198                         static const char hexify[16] =\r
8199                         {\r
8200                             '0', '1', '2', '3', '4', '5', '6', '7',\r
8201                             '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'\r
8202                         };\r
8203 \r
8204                         // print character c as \uxxxx\r
8205                         for (const char m :\r
8206                     { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]\r
8207                         })\r
8208                         {\r
8209                             result[++pos] = m;\r
8210                         }\r
8211 \r
8212                         ++pos;\r
8213                     }\r
8214                     else\r
8215                     {\r
8216                         // all other characters are added as-is\r
8217                         result[pos++] = c;\r
8218                     }\r
8219                     break;\r
8220                 }\r
8221             }\r
8222         }\r
8223 \r
8224         return result;\r
8225     }\r
8226 \r
8227 \r
8228     /*!\r
8229     @brief locale-independent serialization for built-in arithmetic types\r
8230     */\r
8231     struct numtostr\r
8232     {\r
8233       public:\r
8234         template<typename NumberType>\r
8235         numtostr(NumberType value)\r
8236         {\r
8237             x_write(value, std::is_integral<NumberType>());\r
8238         }\r
8239 \r
8240         const char* c_str() const\r
8241         {\r
8242             return m_buf.data();\r
8243         }\r
8244 \r
8245       private:\r
8246         /// a (hopefully) large enough character buffer\r
8247         std::array < char, 64 > m_buf{{}};\r
8248 \r
8249         template<typename NumberType>\r
8250         void x_write(NumberType x, /*is_integral=*/std::true_type)\r
8251         {\r
8252             // special case for "0"\r
8253             if (x == 0)\r
8254             {\r
8255                 m_buf[0] = '0';\r
8256                 return;\r
8257             }\r
8258 \r
8259             const bool is_negative = x < 0;\r
8260             size_t i = 0;\r
8261 \r
8262             // spare 1 byte for '\0'\r
8263             while (x != 0 and i < m_buf.size() - 1)\r
8264             {\r
8265                 const auto digit = std::labs(static_cast<long>(x % 10));\r
8266                 m_buf[i++] = static_cast<char>('0' + digit);\r
8267                 x /= 10;\r
8268             }\r
8269 \r
8270             // make sure the number has been processed completely\r
8271             assert(x == 0);\r
8272 \r
8273             if (is_negative)\r
8274             {\r
8275                 // make sure there is capacity for the '-'\r
8276                 assert(i < m_buf.size() - 2);\r
8277                 m_buf[i++] = '-';\r
8278             }\r
8279 \r
8280             std::reverse(m_buf.begin(), m_buf.begin() + i);\r
8281         }\r
8282 \r
8283         template<typename NumberType>\r
8284         void x_write(NumberType x, /*is_integral=*/std::false_type)\r
8285         {\r
8286             // special case for 0.0 and -0.0\r
8287             if (x == 0)\r
8288             {\r
8289                 size_t i = 0;\r
8290                 if (std::signbit(x))\r
8291                 {\r
8292                     m_buf[i++] = '-';\r
8293                 }\r
8294                 m_buf[i++] = '0';\r
8295                 m_buf[i++] = '.';\r
8296                 m_buf[i] = '0';\r
8297                 return;\r
8298             }\r
8299 \r
8300             // get number of digits for a text -> float -> text round-trip\r
8301             static constexpr auto d = std::numeric_limits<NumberType>::digits10;\r
8302 \r
8303             // the actual conversion\r
8304             const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, (double)x);\r
8305 \r
8306             // negative value indicates an error\r
8307             assert(written_bytes > 0);\r
8308             // check if buffer was large enough\r
8309             assert(static_cast<size_t>(written_bytes) < m_buf.size());\r
8310 \r
8311             // read information from locale\r
8312             const auto loc = localeconv();\r
8313             assert(loc != nullptr);\r
8314             const char thousands_sep = !loc->thousands_sep ? '\0'\r
8315                                        : loc->thousands_sep[0];\r
8316 \r
8317             const char decimal_point = !loc->decimal_point ? '\0'\r
8318                                        : loc->decimal_point[0];\r
8319 \r
8320             // erase thousands separator\r
8321             if (thousands_sep != '\0')\r
8322             {\r
8323                 const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep);\r
8324                 std::fill(end, m_buf.end(), '\0');\r
8325             }\r
8326 \r
8327             // convert decimal point to '.'\r
8328             if (decimal_point != '\0' and decimal_point != '.')\r
8329             {\r
8330                 for (auto& c : m_buf)\r
8331                 {\r
8332                     if (c == decimal_point)\r
8333                     {\r
8334                         c = '.';\r
8335                         break;\r
8336                     }\r
8337                 }\r
8338             }\r
8339 \r
8340             // determine if need to append ".0"\r
8341             size_t i = 0;\r
8342             bool value_is_int_like = true;\r
8343             for (i = 0; i < m_buf.size(); ++i)\r
8344             {\r
8345                 // break when end of number is reached\r
8346                 if (m_buf[i] == '\0')\r
8347                 {\r
8348                     break;\r
8349                 }\r
8350 \r
8351                 // check if we find non-int character\r
8352                 value_is_int_like = value_is_int_like and m_buf[i] != '.' and\r
8353                                     m_buf[i] != 'e' and m_buf[i] != 'E';\r
8354             }\r
8355 \r
8356             if (value_is_int_like)\r
8357             {\r
8358                 // there must be 2 bytes left for ".0"\r
8359                 assert((i + 2) < m_buf.size());\r
8360                 // we write to the end of the number\r
8361                 assert(m_buf[i] == '\0');\r
8362                 assert(m_buf[i - 1] != '\0');\r
8363 \r
8364                 // add ".0"\r
8365                 m_buf[i] = '.';\r
8366                 m_buf[i + 1] = '0';\r
8367 \r
8368                 // the resulting string is properly terminated\r
8369                 assert(m_buf[i + 2] == '\0');\r
8370             }\r
8371         }\r
8372     };\r
8373 \r
8374 \r
8375     /*!\r
8376     @brief internal implementation of the serialization function\r
8377 \r
8378     This function is called by the public member function dump and organizes\r
8379     the serialization internally. The indentation level is propagated as\r
8380     additional parameter. In case of arrays and objects, the function is\r
8381     called recursively. Note that\r
8382 \r
8383     - strings and object keys are escaped using `escape_string()`\r
8384     - integer numbers are converted implicitly via `operator<<`\r
8385     - floating-point numbers are converted to a string using `"%g"` format\r
8386 \r
8387     @param[out] o              stream to write to\r
8388     @param[in] pretty_print    whether the output shall be pretty-printed\r
8389     @param[in] indent_step     the indent level\r
8390     @param[in] current_indent  the current indent level (only used internally)\r
8391     */\r
8392     void dump(std::ostream& o,\r
8393               const bool pretty_print,\r
8394               const unsigned int indent_step,\r
8395               const unsigned int current_indent = 0) const\r
8396     {\r
8397         // variable to hold indentation for recursive calls\r
8398         unsigned int new_indent = current_indent;\r
8399 \r
8400         switch (m_type)\r
8401         {\r
8402             case value_t::object:\r
8403             {\r
8404                 if (m_value.object->empty())\r
8405                 {\r
8406                     o << "{}";\r
8407                     return;\r
8408                 }\r
8409 \r
8410                 o << "{";\r
8411 \r
8412                 // increase indentation\r
8413                 if (pretty_print)\r
8414                 {\r
8415                     new_indent += indent_step;\r
8416                     o << "\n";\r
8417                 }\r
8418 \r
8419                 for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)\r
8420                 {\r
8421                     if (i != m_value.object->cbegin())\r
8422                     {\r
8423                         o << (pretty_print ? ",\n" : ",");\r
8424                     }\r
8425                     o << string_t(new_indent, ' ') << "\""\r
8426                       << escape_string(i->first) << "\":"\r
8427                       << (pretty_print ? " " : "");\r
8428                     i->second.dump(o, pretty_print, indent_step, new_indent);\r
8429                 }\r
8430 \r
8431                 // decrease indentation\r
8432                 if (pretty_print)\r
8433                 {\r
8434                     new_indent -= indent_step;\r
8435                     o << "\n";\r
8436                 }\r
8437 \r
8438                 o << string_t(new_indent, ' ') + "}";\r
8439                 return;\r
8440             }\r
8441 \r
8442             case value_t::array:\r
8443             {\r
8444                 if (m_value.array->empty())\r
8445                 {\r
8446                     o << "[]";\r
8447                     return;\r
8448                 }\r
8449 \r
8450                 o << "[";\r
8451 \r
8452                 // increase indentation\r
8453                 if (pretty_print)\r
8454                 {\r
8455                     new_indent += indent_step;\r
8456                     o << "\n";\r
8457                 }\r
8458 \r
8459                 for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)\r
8460                 {\r
8461                     if (i != m_value.array->cbegin())\r
8462                     {\r
8463                         o << (pretty_print ? ",\n" : ",");\r
8464                     }\r
8465                     o << string_t(new_indent, ' ');\r
8466                     i->dump(o, pretty_print, indent_step, new_indent);\r
8467                 }\r
8468 \r
8469                 // decrease indentation\r
8470                 if (pretty_print)\r
8471                 {\r
8472                     new_indent -= indent_step;\r
8473                     o << "\n";\r
8474                 }\r
8475 \r
8476                 o << string_t(new_indent, ' ') << "]";\r
8477                 return;\r
8478             }\r
8479 \r
8480             case value_t::string:\r
8481             {\r
8482                 o << string_t("\"") << escape_string(*m_value.string) << "\"";\r
8483                 return;\r
8484             }\r
8485 \r
8486             case value_t::boolean:\r
8487             {\r
8488                 o << (m_value.boolean ? "true" : "false");\r
8489                 return;\r
8490             }\r
8491 \r
8492             case value_t::number_integer:\r
8493             {\r
8494                 o << numtostr(m_value.number_integer).c_str();\r
8495                 return;\r
8496             }\r
8497 \r
8498             case value_t::number_unsigned:\r
8499             {\r
8500                 o << numtostr(m_value.number_unsigned).c_str();\r
8501                 return;\r
8502             }\r
8503 \r
8504             case value_t::number_float:\r
8505             {\r
8506                 o << numtostr(m_value.number_float).c_str();\r
8507                 return;\r
8508             }\r
8509 \r
8510             case value_t::discarded:\r
8511             {\r
8512                 o << "<discarded>";\r
8513                 return;\r
8514             }\r
8515 \r
8516             case value_t::null:\r
8517             {\r
8518                 o << "null";\r
8519                 return;\r
8520             }\r
8521         }\r
8522     }\r
8523 \r
8524   private:\r
8525     //////////////////////\r
8526     // member variables //\r
8527     //////////////////////\r
8528 \r
8529     /// the type of the current element\r
8530     value_t m_type = value_t::null;\r
8531 \r
8532     /// the value of the current element\r
8533     json_value m_value = {};\r
8534 \r
8535 \r
8536   private:\r
8537     ///////////////\r
8538     // iterators //\r
8539     ///////////////\r
8540 \r
8541     /*!\r
8542     @brief an iterator for primitive JSON types\r
8543 \r
8544     This class models an iterator for primitive JSON types (boolean, number,\r
8545     string). It's only purpose is to allow the iterator/const_iterator classes\r
8546     to "iterate" over primitive values. Internally, the iterator is modeled by\r
8547     a `difference_type` variable. Value begin_value (`0`) models the begin,\r
8548     end_value (`1`) models past the end.\r
8549     */\r
8550     class primitive_iterator_t\r
8551     {\r
8552       public:\r
8553 \r
8554         difference_type get_value() const noexcept\r
8555         {\r
8556             return m_it;\r
8557         }\r
8558         /// set iterator to a defined beginning\r
8559         void set_begin() noexcept\r
8560         {\r
8561             m_it = begin_value;\r
8562         }\r
8563 \r
8564         /// set iterator to a defined past the end\r
8565         void set_end() noexcept\r
8566         {\r
8567             m_it = end_value;\r
8568         }\r
8569 \r
8570         /// return whether the iterator can be dereferenced\r
8571         constexpr bool is_begin() const noexcept\r
8572         {\r
8573             return (m_it == begin_value);\r
8574         }\r
8575 \r
8576         /// return whether the iterator is at end\r
8577         constexpr bool is_end() const noexcept\r
8578         {\r
8579             return (m_it == end_value);\r
8580         }\r
8581 \r
8582         friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\r
8583         {\r
8584             return lhs.m_it == rhs.m_it;\r
8585         }\r
8586 \r
8587         friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\r
8588         {\r
8589             return !(lhs == rhs);\r
8590         }\r
8591 \r
8592         friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\r
8593         {\r
8594             return lhs.m_it < rhs.m_it;\r
8595         }\r
8596 \r
8597         friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\r
8598         {\r
8599             return lhs.m_it <= rhs.m_it;\r
8600         }\r
8601 \r
8602         friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\r
8603         {\r
8604             return lhs.m_it > rhs.m_it;\r
8605         }\r
8606 \r
8607         friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\r
8608         {\r
8609             return lhs.m_it >= rhs.m_it;\r
8610         }\r
8611 \r
8612         primitive_iterator_t operator+(difference_type i)\r
8613         {\r
8614             auto result = *this;\r
8615             result += i;\r
8616             return result;\r
8617         }\r
8618 \r
8619         friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\r
8620         {\r
8621             return lhs.m_it - rhs.m_it;\r
8622         }\r
8623 \r
8624         friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)\r
8625         {\r
8626             return os << it.m_it;\r
8627         }\r
8628 \r
8629         primitive_iterator_t& operator++()\r
8630         {\r
8631             ++m_it;\r
8632             return *this;\r
8633         }\r
8634 \r
8635         primitive_iterator_t operator++(int)\r
8636         {\r
8637             auto result = *this;\r
8638             m_it++;\r
8639             return result;\r
8640         }\r
8641 \r
8642         primitive_iterator_t& operator--()\r
8643         {\r
8644             --m_it;\r
8645             return *this;\r
8646         }\r
8647 \r
8648         primitive_iterator_t operator--(int)\r
8649         {\r
8650             auto result = *this;\r
8651             m_it--;\r
8652             return result;\r
8653         }\r
8654 \r
8655         primitive_iterator_t& operator+=(difference_type n)\r
8656         {\r
8657             m_it += n;\r
8658             return *this;\r
8659         }\r
8660 \r
8661         primitive_iterator_t& operator-=(difference_type n)\r
8662         {\r
8663             m_it -= n;\r
8664             return *this;\r
8665         }\r
8666 \r
8667       private:\r
8668         static constexpr difference_type begin_value = 0;\r
8669         static constexpr difference_type end_value = begin_value + 1;\r
8670 \r
8671         /// iterator as signed integer type\r
8672         difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();\r
8673     };\r
8674 \r
8675     /*!\r
8676     @brief an iterator value\r
8677 \r
8678     @note This structure could easily be a union, but MSVC currently does not\r
8679     allow unions members with complex constructors, see\r
8680     https://github.com/nlohmann/json/pull/105.\r
8681     */\r
8682     struct internal_iterator\r
8683     {\r
8684         /// iterator for JSON objects\r
8685         typename object_t::iterator object_iterator;\r
8686         /// iterator for JSON arrays\r
8687         typename array_t::iterator array_iterator;\r
8688         /// generic iterator for all other types\r
8689         primitive_iterator_t primitive_iterator;\r
8690 \r
8691         /// create an uninitialized internal_iterator\r
8692         internal_iterator() noexcept\r
8693             : object_iterator(), array_iterator(), primitive_iterator()\r
8694         {}\r
8695     };\r
8696 \r
8697     /// proxy class for the iterator_wrapper functions\r
8698     template<typename IteratorType>\r
8699     class iteration_proxy\r
8700     {\r
8701       private:\r
8702         /// helper class for iteration\r
8703         class iteration_proxy_internal\r
8704         {\r
8705           private:\r
8706             /// the iterator\r
8707             IteratorType anchor;\r
8708             /// an index for arrays (used to create key names)\r
8709             size_t array_index = 0;\r
8710 \r
8711           public:\r
8712             explicit iteration_proxy_internal(IteratorType it) noexcept\r
8713                 : anchor(it)\r
8714             {}\r
8715 \r
8716             /// dereference operator (needed for range-based for)\r
8717             iteration_proxy_internal& operator*()\r
8718             {\r
8719                 return *this;\r
8720             }\r
8721 \r
8722             /// increment operator (needed for range-based for)\r
8723             iteration_proxy_internal& operator++()\r
8724             {\r
8725                 ++anchor;\r
8726                 ++array_index;\r
8727 \r
8728                 return *this;\r
8729             }\r
8730 \r
8731             /// inequality operator (needed for range-based for)\r
8732             bool operator!= (const iteration_proxy_internal& o) const\r
8733             {\r
8734                 return anchor != o.anchor;\r
8735             }\r
8736 \r
8737             /// return key of the iterator\r
8738             typename basic_json::string_t key() const\r
8739             {\r
8740                 assert(anchor.m_object != nullptr);\r
8741 \r
8742                 switch (anchor.m_object->type())\r
8743                 {\r
8744                     // use integer array index as key\r
8745                     case value_t::array:\r
8746                     {\r
8747                         return std::to_string(array_index);\r
8748                     }\r
8749 \r
8750                     // use key from the object\r
8751                     case value_t::object:\r
8752                     {\r
8753                         return anchor.key();\r
8754                     }\r
8755 \r
8756                     // use an empty key for all primitive types\r
8757                     default:\r
8758                     {\r
8759                         return "";\r
8760                     }\r
8761                 }\r
8762             }\r
8763 \r
8764             /// return value of the iterator\r
8765             typename IteratorType::reference value() const\r
8766             {\r
8767                 return anchor.value();\r
8768             }\r
8769         };\r
8770 \r
8771         /// the container to iterate\r
8772         typename IteratorType::reference container;\r
8773 \r
8774       public:\r
8775         /// construct iteration proxy from a container\r
8776         explicit iteration_proxy(typename IteratorType::reference cont)\r
8777             : container(cont)\r
8778         {}\r
8779 \r
8780         /// return iterator begin (needed for range-based for)\r
8781         iteration_proxy_internal begin() noexcept\r
8782         {\r
8783             return iteration_proxy_internal(container.begin());\r
8784         }\r
8785 \r
8786         /// return iterator end (needed for range-based for)\r
8787         iteration_proxy_internal end() noexcept\r
8788         {\r
8789             return iteration_proxy_internal(container.end());\r
8790         }\r
8791     };\r
8792 \r
8793   public:\r
8794     /*!\r
8795     @brief a template for a random access iterator for the @ref basic_json class\r
8796 \r
8797     This class implements a both iterators (iterator and const_iterator) for the\r
8798     @ref basic_json class.\r
8799 \r
8800     @note An iterator is called *initialized* when a pointer to a JSON value\r
8801           has been set (e.g., by a constructor or a copy assignment). If the\r
8802           iterator is default-constructed, it is *uninitialized* and most\r
8803           methods are undefined. **The library uses assertions to detect calls\r
8804           on uninitialized iterators.**\r
8805 \r
8806     @requirement The class satisfies the following concept requirements:\r
8807     - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):\r
8808       The iterator that can be moved to point (forward and backward) to any\r
8809       element in constant time.\r
8810 \r
8811     @since version 1.0.0, simplified in version 2.0.9\r
8812     */\r
8813     template<typename U>\r
8814     class iter_impl : public std::iterator<std::random_access_iterator_tag, U>\r
8815     {\r
8816         /// allow basic_json to access private members\r
8817         friend class basic_json;\r
8818 \r
8819         // make sure U is basic_json or const basic_json\r
8820         static_assert(std::is_same<U, basic_json>::value\r
8821                       or std::is_same<U, const basic_json>::value,\r
8822                       "iter_impl only accepts (const) basic_json");\r
8823 \r
8824       public:\r
8825         /// the type of the values when the iterator is dereferenced\r
8826         using value_type = typename basic_json::value_type;\r
8827         /// a type to represent differences between iterators\r
8828         using difference_type = typename basic_json::difference_type;\r
8829         /// defines a pointer to the type iterated over (value_type)\r
8830         using pointer = typename std::conditional<std::is_const<U>::value,\r
8831               typename basic_json::const_pointer,\r
8832               typename basic_json::pointer>::type;\r
8833         /// defines a reference to the type iterated over (value_type)\r
8834         using reference = typename std::conditional<std::is_const<U>::value,\r
8835               typename basic_json::const_reference,\r
8836               typename basic_json::reference>::type;\r
8837         /// the category of the iterator\r
8838         using iterator_category = std::bidirectional_iterator_tag;\r
8839 \r
8840         /// default constructor\r
8841         iter_impl() = default;\r
8842 \r
8843         /*!\r
8844         @brief constructor for a given JSON instance\r
8845         @param[in] object  pointer to a JSON object for this iterator\r
8846         @pre object != nullptr\r
8847         @post The iterator is initialized; i.e. `m_object != nullptr`.\r
8848         */\r
8849         explicit iter_impl(pointer object) noexcept\r
8850             : m_object(object)\r
8851         {\r
8852             assert(m_object != nullptr);\r
8853 \r
8854             switch (m_object->m_type)\r
8855             {\r
8856                 case basic_json::value_t::object:\r
8857                 {\r
8858                     m_it.object_iterator = typename object_t::iterator();\r
8859                     break;\r
8860                 }\r
8861 \r
8862                 case basic_json::value_t::array:\r
8863                 {\r
8864                     m_it.array_iterator = typename array_t::iterator();\r
8865                     break;\r
8866                 }\r
8867 \r
8868                 default:\r
8869                 {\r
8870                     m_it.primitive_iterator = primitive_iterator_t();\r
8871                     break;\r
8872                 }\r
8873             }\r
8874         }\r
8875 \r
8876         /*\r
8877         Use operator `const_iterator` instead of `const_iterator(const iterator&\r
8878         other) noexcept` to avoid two class definitions for @ref iterator and\r
8879         @ref const_iterator.\r
8880 \r
8881         This function is only called if this class is an @ref iterator. If this\r
8882         class is a @ref const_iterator this function is not called.\r
8883         */\r
8884         operator const_iterator() const\r
8885         {\r
8886             const_iterator ret;\r
8887 \r
8888             if (m_object)\r
8889             {\r
8890                 ret.m_object = m_object;\r
8891                 ret.m_it = m_it;\r
8892             }\r
8893 \r
8894             return ret;\r
8895         }\r
8896 \r
8897         /*!\r
8898         @brief copy constructor\r
8899         @param[in] other  iterator to copy from\r
8900         @note It is not checked whether @a other is initialized.\r
8901         */\r
8902         iter_impl(const iter_impl& other) noexcept\r
8903             : m_object(other.m_object), m_it(other.m_it)\r
8904         {}\r
8905 \r
8906         /*!\r
8907         @brief copy assignment\r
8908         @param[in,out] other  iterator to copy from\r
8909         @note It is not checked whether @a other is initialized.\r
8910         */\r
8911         iter_impl& operator=(iter_impl other) noexcept(\r
8912             std::is_nothrow_move_constructible<pointer>::value and\r
8913             std::is_nothrow_move_assignable<pointer>::value and\r
8914             std::is_nothrow_move_constructible<internal_iterator>::value and\r
8915             std::is_nothrow_move_assignable<internal_iterator>::value\r
8916         )\r
8917         {\r
8918             std::swap(m_object, other.m_object);\r
8919             std::swap(m_it, other.m_it);\r
8920             return *this;\r
8921         }\r
8922 \r
8923       private:\r
8924         /*!\r
8925         @brief set the iterator to the first value\r
8926         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
8927         */\r
8928         void set_begin() noexcept\r
8929         {\r
8930             assert(m_object != nullptr);\r
8931 \r
8932             switch (m_object->m_type)\r
8933             {\r
8934                 case basic_json::value_t::object:\r
8935                 {\r
8936                     m_it.object_iterator = m_object->m_value.object->begin();\r
8937                     break;\r
8938                 }\r
8939 \r
8940                 case basic_json::value_t::array:\r
8941                 {\r
8942                     m_it.array_iterator = m_object->m_value.array->begin();\r
8943                     break;\r
8944                 }\r
8945 \r
8946                 case basic_json::value_t::null:\r
8947                 {\r
8948                     // set to end so begin()==end() is true: null is empty\r
8949                     m_it.primitive_iterator.set_end();\r
8950                     break;\r
8951                 }\r
8952 \r
8953                 default:\r
8954                 {\r
8955                     m_it.primitive_iterator.set_begin();\r
8956                     break;\r
8957                 }\r
8958             }\r
8959         }\r
8960 \r
8961         /*!\r
8962         @brief set the iterator past the last value\r
8963         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
8964         */\r
8965         void set_end() noexcept\r
8966         {\r
8967             assert(m_object != nullptr);\r
8968 \r
8969             switch (m_object->m_type)\r
8970             {\r
8971                 case basic_json::value_t::object:\r
8972                 {\r
8973                     m_it.object_iterator = m_object->m_value.object->end();\r
8974                     break;\r
8975                 }\r
8976 \r
8977                 case basic_json::value_t::array:\r
8978                 {\r
8979                     m_it.array_iterator = m_object->m_value.array->end();\r
8980                     break;\r
8981                 }\r
8982 \r
8983                 default:\r
8984                 {\r
8985                     m_it.primitive_iterator.set_end();\r
8986                     break;\r
8987                 }\r
8988             }\r
8989         }\r
8990 \r
8991       public:\r
8992         /*!\r
8993         @brief return a reference to the value pointed to by the iterator\r
8994         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
8995         */\r
8996         reference operator*() const\r
8997         {\r
8998             assert(m_object != nullptr);\r
8999 \r
9000             switch (m_object->m_type)\r
9001             {\r
9002                 case basic_json::value_t::object:\r
9003                 {\r
9004                     assert(m_it.object_iterator != m_object->m_value.object->end());\r
9005                     return m_it.object_iterator->second;\r
9006                 }\r
9007 \r
9008                 case basic_json::value_t::array:\r
9009                 {\r
9010                     assert(m_it.array_iterator != m_object->m_value.array->end());\r
9011                     return *m_it.array_iterator;\r
9012                 }\r
9013 \r
9014                 case basic_json::value_t::null:\r
9015                 {\r
9016                     JSON_THROW(std::out_of_range("cannot get value"));\r
9017                 }\r
9018 \r
9019                 default:\r
9020                 {\r
9021                     if (m_it.primitive_iterator.is_begin())\r
9022                     {\r
9023                         return *m_object;\r
9024                     }\r
9025 \r
9026                     JSON_THROW(std::out_of_range("cannot get value"));\r
9027                 }\r
9028             }\r
9029         }\r
9030 \r
9031         /*!\r
9032         @brief dereference the iterator\r
9033         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9034         */\r
9035         pointer operator->() const\r
9036         {\r
9037             assert(m_object != nullptr);\r
9038 \r
9039             switch (m_object->m_type)\r
9040             {\r
9041                 case basic_json::value_t::object:\r
9042                 {\r
9043                     assert(m_it.object_iterator != m_object->m_value.object->end());\r
9044                     return &(m_it.object_iterator->second);\r
9045                 }\r
9046 \r
9047                 case basic_json::value_t::array:\r
9048                 {\r
9049                     assert(m_it.array_iterator != m_object->m_value.array->end());\r
9050                     return &*m_it.array_iterator;\r
9051                 }\r
9052 \r
9053                 default:\r
9054                 {\r
9055                     if (m_it.primitive_iterator.is_begin())\r
9056                     {\r
9057                         return m_object;\r
9058                     }\r
9059 \r
9060                     JSON_THROW(std::out_of_range("cannot get value"));\r
9061                 }\r
9062             }\r
9063         }\r
9064 \r
9065         /*!\r
9066         @brief post-increment (it++)\r
9067         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9068         */\r
9069         iter_impl operator++(int)\r
9070         {\r
9071             auto result = *this;\r
9072             ++(*this);\r
9073             return result;\r
9074         }\r
9075 \r
9076         /*!\r
9077         @brief pre-increment (++it)\r
9078         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9079         */\r
9080         iter_impl& operator++()\r
9081         {\r
9082             assert(m_object != nullptr);\r
9083 \r
9084             switch (m_object->m_type)\r
9085             {\r
9086                 case basic_json::value_t::object:\r
9087                 {\r
9088                     std::advance(m_it.object_iterator, 1);\r
9089                     break;\r
9090                 }\r
9091 \r
9092                 case basic_json::value_t::array:\r
9093                 {\r
9094                     std::advance(m_it.array_iterator, 1);\r
9095                     break;\r
9096                 }\r
9097 \r
9098                 default:\r
9099                 {\r
9100                     ++m_it.primitive_iterator;\r
9101                     break;\r
9102                 }\r
9103             }\r
9104 \r
9105             return *this;\r
9106         }\r
9107 \r
9108         /*!\r
9109         @brief post-decrement (it--)\r
9110         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9111         */\r
9112         iter_impl operator--(int)\r
9113         {\r
9114             auto result = *this;\r
9115             --(*this);\r
9116             return result;\r
9117         }\r
9118 \r
9119         /*!\r
9120         @brief pre-decrement (--it)\r
9121         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9122         */\r
9123         iter_impl& operator--()\r
9124         {\r
9125             assert(m_object != nullptr);\r
9126 \r
9127             switch (m_object->m_type)\r
9128             {\r
9129                 case basic_json::value_t::object:\r
9130                 {\r
9131                     std::advance(m_it.object_iterator, -1);\r
9132                     break;\r
9133                 }\r
9134 \r
9135                 case basic_json::value_t::array:\r
9136                 {\r
9137                     std::advance(m_it.array_iterator, -1);\r
9138                     break;\r
9139                 }\r
9140 \r
9141                 default:\r
9142                 {\r
9143                     --m_it.primitive_iterator;\r
9144                     break;\r
9145                 }\r
9146             }\r
9147 \r
9148             return *this;\r
9149         }\r
9150 \r
9151         /*!\r
9152         @brief  comparison: equal\r
9153         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9154         */\r
9155         bool operator==(const iter_impl& other) const\r
9156         {\r
9157             // if objects are not the same, the comparison is undefined\r
9158             if (m_object != other.m_object)\r
9159             {\r
9160                 JSON_THROW(std::domain_error("cannot compare iterators of different containers"));\r
9161             }\r
9162 \r
9163             assert(m_object != nullptr);\r
9164 \r
9165             switch (m_object->m_type)\r
9166             {\r
9167                 case basic_json::value_t::object:\r
9168                 {\r
9169                     return (m_it.object_iterator == other.m_it.object_iterator);\r
9170                 }\r
9171 \r
9172                 case basic_json::value_t::array:\r
9173                 {\r
9174                     return (m_it.array_iterator == other.m_it.array_iterator);\r
9175                 }\r
9176 \r
9177                 default:\r
9178                 {\r
9179                     return (m_it.primitive_iterator == other.m_it.primitive_iterator);\r
9180                 }\r
9181             }\r
9182         }\r
9183 \r
9184         /*!\r
9185         @brief  comparison: not equal\r
9186         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9187         */\r
9188         bool operator!=(const iter_impl& other) const\r
9189         {\r
9190             return not operator==(other);\r
9191         }\r
9192 \r
9193         /*!\r
9194         @brief  comparison: smaller\r
9195         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9196         */\r
9197         bool operator<(const iter_impl& other) const\r
9198         {\r
9199             // if objects are not the same, the comparison is undefined\r
9200             if (m_object != other.m_object)\r
9201             {\r
9202                 JSON_THROW(std::domain_error("cannot compare iterators of different containers"));\r
9203             }\r
9204 \r
9205             assert(m_object != nullptr);\r
9206 \r
9207             switch (m_object->m_type)\r
9208             {\r
9209                 case basic_json::value_t::object:\r
9210                 {\r
9211                     JSON_THROW(std::domain_error("cannot compare order of object iterators"));\r
9212                 }\r
9213 \r
9214                 case basic_json::value_t::array:\r
9215                 {\r
9216                     return (m_it.array_iterator < other.m_it.array_iterator);\r
9217                 }\r
9218 \r
9219                 default:\r
9220                 {\r
9221                     return (m_it.primitive_iterator < other.m_it.primitive_iterator);\r
9222                 }\r
9223             }\r
9224         }\r
9225 \r
9226         /*!\r
9227         @brief  comparison: less than or equal\r
9228         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9229         */\r
9230         bool operator<=(const iter_impl& other) const\r
9231         {\r
9232             return not other.operator < (*this);\r
9233         }\r
9234 \r
9235         /*!\r
9236         @brief  comparison: greater than\r
9237         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9238         */\r
9239         bool operator>(const iter_impl& other) const\r
9240         {\r
9241             return not operator<=(other);\r
9242         }\r
9243 \r
9244         /*!\r
9245         @brief  comparison: greater than or equal\r
9246         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9247         */\r
9248         bool operator>=(const iter_impl& other) const\r
9249         {\r
9250             return not operator<(other);\r
9251         }\r
9252 \r
9253         /*!\r
9254         @brief  add to iterator\r
9255         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9256         */\r
9257         iter_impl& operator+=(difference_type i)\r
9258         {\r
9259             assert(m_object != nullptr);\r
9260 \r
9261             switch (m_object->m_type)\r
9262             {\r
9263                 case basic_json::value_t::object:\r
9264                 {\r
9265                     JSON_THROW(std::domain_error("cannot use offsets with object iterators"));\r
9266                 }\r
9267 \r
9268                 case basic_json::value_t::array:\r
9269                 {\r
9270                     std::advance(m_it.array_iterator, i);\r
9271                     break;\r
9272                 }\r
9273 \r
9274                 default:\r
9275                 {\r
9276                     m_it.primitive_iterator += i;\r
9277                     break;\r
9278                 }\r
9279             }\r
9280 \r
9281             return *this;\r
9282         }\r
9283 \r
9284         /*!\r
9285         @brief  subtract from iterator\r
9286         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9287         */\r
9288         iter_impl& operator-=(difference_type i)\r
9289         {\r
9290             return operator+=(-i);\r
9291         }\r
9292 \r
9293         /*!\r
9294         @brief  add to iterator\r
9295         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9296         */\r
9297         iter_impl operator+(difference_type i)\r
9298         {\r
9299             auto result = *this;\r
9300             result += i;\r
9301             return result;\r
9302         }\r
9303 \r
9304         /*!\r
9305         @brief  subtract from iterator\r
9306         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9307         */\r
9308         iter_impl operator-(difference_type i)\r
9309         {\r
9310             auto result = *this;\r
9311             result -= i;\r
9312             return result;\r
9313         }\r
9314 \r
9315         /*!\r
9316         @brief  return difference\r
9317         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9318         */\r
9319         difference_type operator-(const iter_impl& other) const\r
9320         {\r
9321             assert(m_object != nullptr);\r
9322 \r
9323             switch (m_object->m_type)\r
9324             {\r
9325                 case basic_json::value_t::object:\r
9326                 {\r
9327                     JSON_THROW(std::domain_error("cannot use offsets with object iterators"));\r
9328                 }\r
9329 \r
9330                 case basic_json::value_t::array:\r
9331                 {\r
9332                     return m_it.array_iterator - other.m_it.array_iterator;\r
9333                 }\r
9334 \r
9335                 default:\r
9336                 {\r
9337                     return m_it.primitive_iterator - other.m_it.primitive_iterator;\r
9338                 }\r
9339             }\r
9340         }\r
9341 \r
9342         /*!\r
9343         @brief  access to successor\r
9344         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9345         */\r
9346         reference operator[](difference_type n) const\r
9347         {\r
9348             assert(m_object != nullptr);\r
9349 \r
9350             switch (m_object->m_type)\r
9351             {\r
9352                 case basic_json::value_t::object:\r
9353                 {\r
9354                     JSON_THROW(std::domain_error("cannot use operator[] for object iterators"));\r
9355                 }\r
9356 \r
9357                 case basic_json::value_t::array:\r
9358                 {\r
9359                     return *std::next(m_it.array_iterator, n);\r
9360                 }\r
9361 \r
9362                 case basic_json::value_t::null:\r
9363                 {\r
9364                     JSON_THROW(std::out_of_range("cannot get value"));\r
9365                 }\r
9366 \r
9367                 default:\r
9368                 {\r
9369                     if (m_it.primitive_iterator.get_value() == -n)\r
9370                     {\r
9371                         return *m_object;\r
9372                     }\r
9373 \r
9374                     JSON_THROW(std::out_of_range("cannot get value"));\r
9375                 }\r
9376             }\r
9377         }\r
9378 \r
9379         /*!\r
9380         @brief  return the key of an object iterator\r
9381         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9382         */\r
9383         typename object_t::key_type key() const\r
9384         {\r
9385             assert(m_object != nullptr);\r
9386 \r
9387             if (m_object->is_object())\r
9388             {\r
9389                 return m_it.object_iterator->first;\r
9390             }\r
9391 \r
9392             JSON_THROW(std::domain_error("cannot use key() for non-object iterators"));\r
9393         }\r
9394 \r
9395         /*!\r
9396         @brief  return the value of an iterator\r
9397         @pre The iterator is initialized; i.e. `m_object != nullptr`.\r
9398         */\r
9399         reference value() const\r
9400         {\r
9401             return operator*();\r
9402         }\r
9403 \r
9404       private:\r
9405         /// associated JSON instance\r
9406         pointer m_object = nullptr;\r
9407         /// the actual iterator of the associated instance\r
9408         internal_iterator m_it = internal_iterator();\r
9409     };\r
9410 \r
9411     /*!\r
9412     @brief a template for a reverse iterator class\r
9413 \r
9414     @tparam Base the base iterator type to reverse. Valid types are @ref\r
9415     iterator (to create @ref reverse_iterator) and @ref const_iterator (to\r
9416     create @ref const_reverse_iterator).\r
9417 \r
9418     @requirement The class satisfies the following concept requirements:\r
9419     - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):\r
9420       The iterator that can be moved to point (forward and backward) to any\r
9421       element in constant time.\r
9422     - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):\r
9423       It is possible to write to the pointed-to element (only if @a Base is\r
9424       @ref iterator).\r
9425 \r
9426     @since version 1.0.0\r
9427     */\r
9428     template<typename Base>\r
9429     class json_reverse_iterator : public std::reverse_iterator<Base>\r
9430     {\r
9431       public:\r
9432         /// shortcut to the reverse iterator adaptor\r
9433         using base_iterator = std::reverse_iterator<Base>;\r
9434         /// the reference type for the pointed-to element\r
9435         using reference = typename Base::reference;\r
9436 \r
9437         /// create reverse iterator from iterator\r
9438         json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept\r
9439             : base_iterator(it)\r
9440         {}\r
9441 \r
9442         /// create reverse iterator from base class\r
9443         json_reverse_iterator(const base_iterator& it) noexcept\r
9444             : base_iterator(it)\r
9445         {}\r
9446 \r
9447         /// post-increment (it++)\r
9448         json_reverse_iterator operator++(int)\r
9449         {\r
9450             return base_iterator::operator++(1);\r
9451         }\r
9452 \r
9453         /// pre-increment (++it)\r
9454         json_reverse_iterator& operator++()\r
9455         {\r
9456             base_iterator::operator++();\r
9457             return *this;\r
9458         }\r
9459 \r
9460         /// post-decrement (it--)\r
9461         json_reverse_iterator operator--(int)\r
9462         {\r
9463             return base_iterator::operator--(1);\r
9464         }\r
9465 \r
9466         /// pre-decrement (--it)\r
9467         json_reverse_iterator& operator--()\r
9468         {\r
9469             base_iterator::operator--();\r
9470             return *this;\r
9471         }\r
9472 \r
9473         /// add to iterator\r
9474         json_reverse_iterator& operator+=(difference_type i)\r
9475         {\r
9476             base_iterator::operator+=(i);\r
9477             return *this;\r
9478         }\r
9479 \r
9480         /// add to iterator\r
9481         json_reverse_iterator operator+(difference_type i) const\r
9482         {\r
9483             auto result = *this;\r
9484             result += i;\r
9485             return result;\r
9486         }\r
9487 \r
9488         /// subtract from iterator\r
9489         json_reverse_iterator operator-(difference_type i) const\r
9490         {\r
9491             auto result = *this;\r
9492             result -= i;\r
9493             return result;\r
9494         }\r
9495 \r
9496         /// return difference\r
9497         difference_type operator-(const json_reverse_iterator& other) const\r
9498         {\r
9499             return this->base() - other.base();\r
9500         }\r
9501 \r
9502         /// access to successor\r
9503         reference operator[](difference_type n) const\r
9504         {\r
9505             return *(this->operator+(n));\r
9506         }\r
9507 \r
9508         /// return the key of an object iterator\r
9509         typename object_t::key_type key() const\r
9510         {\r
9511             auto it = --this->base();\r
9512             return it.key();\r
9513         }\r
9514 \r
9515         /// return the value of an iterator\r
9516         reference value() const\r
9517         {\r
9518             auto it = --this->base();\r
9519             return it.operator * ();\r
9520         }\r
9521     };\r
9522 \r
9523 \r
9524   private:\r
9525     //////////////////////\r
9526     // lexer and parser //\r
9527     //////////////////////\r
9528 \r
9529     /*!\r
9530     @brief lexical analysis\r
9531 \r
9532     This class organizes the lexical analysis during JSON deserialization. The\r
9533     core of it is a scanner generated by [re2c](http://re2c.org) that\r
9534     processes a buffer and recognizes tokens according to RFC 7159.\r
9535     */\r
9536     class lexer\r
9537     {\r
9538       public:\r
9539         /// token types for the parser\r
9540         enum class token_type\r
9541         {\r
9542             uninitialized,   ///< indicating the scanner is uninitialized\r
9543             literal_true,    ///< the `true` literal\r
9544             literal_false,   ///< the `false` literal\r
9545             literal_null,    ///< the `null` literal\r
9546             value_string,    ///< a string -- use get_string() for actual value\r
9547             value_unsigned,  ///< an unsigned integer -- use get_number() for actual value\r
9548             value_integer,   ///< a signed integer -- use get_number() for actual value\r
9549             value_float,     ///< an floating point number -- use get_number() for actual value\r
9550             begin_array,     ///< the character for array begin `[`\r
9551             begin_object,    ///< the character for object begin `{`\r
9552             end_array,       ///< the character for array end `]`\r
9553             end_object,      ///< the character for object end `}`\r
9554             name_separator,  ///< the name separator `:`\r
9555             value_separator, ///< the value separator `,`\r
9556             parse_error,     ///< indicating a parse error\r
9557             end_of_input     ///< indicating the end of the input buffer\r
9558         };\r
9559 \r
9560         /// the char type to use in the lexer\r
9561         using lexer_char_t = unsigned char;\r
9562 \r
9563         /// a lexer from a buffer with given length\r
9564         lexer(const lexer_char_t* buff, const size_t len) noexcept\r
9565             : m_content(buff)\r
9566         {\r
9567             assert(m_content != nullptr);\r
9568             m_start = m_cursor = m_content;\r
9569             m_limit = m_content + len;\r
9570         }\r
9571 \r
9572         /// a lexer from an input stream\r
9573         explicit lexer(std::istream& s)\r
9574             : m_stream(&s), m_line_buffer()\r
9575         {\r
9576             // immediately abort if stream is erroneous\r
9577             if (s.fail())\r
9578             {\r
9579                 JSON_THROW(std::invalid_argument("stream error"));\r
9580             }\r
9581 \r
9582             // fill buffer\r
9583             fill_line_buffer();\r
9584 \r
9585             // skip UTF-8 byte-order mark\r
9586             if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")\r
9587             {\r
9588                 m_line_buffer[0] = ' ';\r
9589                 m_line_buffer[1] = ' ';\r
9590                 m_line_buffer[2] = ' ';\r
9591             }\r
9592         }\r
9593 \r
9594         // switch off unwanted functions (due to pointer members)\r
9595         lexer() = delete;\r
9596         lexer(const lexer&) = delete;\r
9597         lexer operator=(const lexer&) = delete;\r
9598 \r
9599         /*!\r
9600         @brief create a string from one or two Unicode code points\r
9601 \r
9602         There are two cases: (1) @a codepoint1 is in the Basic Multilingual\r
9603         Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2)\r
9604         @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to\r
9605         represent a code point above U+FFFF.\r
9606 \r
9607         @param[in] codepoint1  the code point (can be high surrogate)\r
9608         @param[in] codepoint2  the code point (can be low surrogate or 0)\r
9609 \r
9610         @return string representation of the code point; the length of the\r
9611         result string is between 1 and 4 characters.\r
9612 \r
9613         @throw std::out_of_range if code point is > 0x10ffff; example: `"code\r
9614         points above 0x10FFFF are invalid"`\r
9615         @throw std::invalid_argument if the low surrogate is invalid; example:\r
9616         `""missing or wrong low surrogate""`\r
9617 \r
9618         @complexity Constant.\r
9619 \r
9620         @see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>\r
9621         */\r
9622         static string_t to_unicode(const std::size_t codepoint1,\r
9623                                    const std::size_t codepoint2 = 0)\r
9624         {\r
9625             // calculate the code point from the given code points\r
9626             std::size_t codepoint = codepoint1;\r
9627 \r
9628             // check if codepoint1 is a high surrogate\r
9629             if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)\r
9630             {\r
9631                 // check if codepoint2 is a low surrogate\r
9632                 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)\r
9633                 {\r
9634                     codepoint =\r
9635                         // high surrogate occupies the most significant 22 bits\r
9636                         (codepoint1 << 10)\r
9637                         // low surrogate occupies the least significant 15 bits\r
9638                         + codepoint2\r
9639                         // there is still the 0xD800, 0xDC00 and 0x10000 noise\r
9640                         // in the result so we have to subtract with:\r
9641                         // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00\r
9642                         - 0x35FDC00;\r
9643                 }\r
9644                 else\r
9645                 {\r
9646                     JSON_THROW(std::invalid_argument("missing or wrong low surrogate"));\r
9647                 }\r
9648             }\r
9649 \r
9650             string_t result;\r
9651 \r
9652             if (codepoint < 0x80)\r
9653             {\r
9654                 // 1-byte characters: 0xxxxxxx (ASCII)\r
9655                 result.append(1, static_cast<typename string_t::value_type>(codepoint));\r
9656             }\r
9657             else if (codepoint <= 0x7ff)\r
9658             {\r
9659                 // 2-byte characters: 110xxxxx 10xxxxxx\r
9660                 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));\r
9661                 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));\r
9662             }\r
9663             else if (codepoint <= 0xffff)\r
9664             {\r
9665                 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx\r
9666                 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));\r
9667                 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));\r
9668                 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));\r
9669             }\r
9670             else if (codepoint <= 0x10ffff)\r
9671             {\r
9672                 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\r
9673                 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));\r
9674                 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));\r
9675                 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));\r
9676                 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));\r
9677             }\r
9678             else\r
9679             {\r
9680                 JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid"));\r
9681             }\r
9682 \r
9683             return result;\r
9684         }\r
9685 \r
9686         /// return name of values of type token_type (only used for errors)\r
9687         static std::string token_type_name(const token_type t)\r
9688         {\r
9689             switch (t)\r
9690             {\r
9691                 case token_type::uninitialized:\r
9692                     return "<uninitialized>";\r
9693                 case token_type::literal_true:\r
9694                     return "true literal";\r
9695                 case token_type::literal_false:\r
9696                     return "false literal";\r
9697                 case token_type::literal_null:\r
9698                     return "null literal";\r
9699                 case token_type::value_string:\r
9700                     return "string literal";\r
9701                 case lexer::token_type::value_unsigned:\r
9702                 case lexer::token_type::value_integer:\r
9703                 case lexer::token_type::value_float:\r
9704                     return "number literal";\r
9705                 case token_type::begin_array:\r
9706                     return "'['";\r
9707                 case token_type::begin_object:\r
9708                     return "'{'";\r
9709                 case token_type::end_array:\r
9710                     return "']'";\r
9711                 case token_type::end_object:\r
9712                     return "'}'";\r
9713                 case token_type::name_separator:\r
9714                     return "':'";\r
9715                 case token_type::value_separator:\r
9716                     return "','";\r
9717                 case token_type::parse_error:\r
9718                     return "<parse error>";\r
9719                 case token_type::end_of_input:\r
9720                     return "end of input";\r
9721                 default:\r
9722                 {\r
9723                     // catch non-enum values\r
9724                     return "unknown token"; // LCOV_EXCL_LINE\r
9725                 }\r
9726             }\r
9727         }\r
9728 \r
9729         /*!\r
9730         This function implements a scanner for JSON. It is specified using\r
9731         regular expressions that try to follow RFC 7159 as close as possible.\r
9732         These regular expressions are then translated into a minimized\r
9733         deterministic finite automaton (DFA) by the tool\r
9734         [re2c](http://re2c.org). As a result, the translated code for this\r
9735         function consists of a large block of code with `goto` jumps.\r
9736 \r
9737         @return the class of the next token read from the buffer\r
9738 \r
9739         @complexity Linear in the length of the input.\n\r
9740 \r
9741         Proposition: The loop below will always terminate for finite input.\n\r
9742 \r
9743         Proof (by contradiction): Assume a finite input. To loop forever, the\r
9744         loop must never hit code with a `break` statement. The only code\r
9745         snippets without a `break` statement are the continue statements for\r
9746         whitespace and byte-order-marks. To loop forever, the input must be an\r
9747         infinite sequence of whitespace or byte-order-marks. This contradicts\r
9748         the assumption of finite input, q.e.d.\r
9749         */\r
9750         token_type scan()\r
9751         {\r
9752             while (true)\r
9753             {\r
9754                 // pointer for backtracking information\r
9755                 m_marker = nullptr;\r
9756 \r
9757                 // remember the begin of the token\r
9758                 m_start = m_cursor;\r
9759                 assert(m_start != nullptr);\r
9760 \r
9761 \r
9762                 {\r
9763                     lexer_char_t yych;\r
9764                     unsigned int yyaccept = 0;\r
9765                     static const unsigned char yybm[] =\r
9766                     {\r
9767                         0,   0,   0,   0,   0,   0,   0,   0,\r
9768                         0,  32,  32,   0,   0,  32,   0,   0,\r
9769                         0,   0,   0,   0,   0,   0,   0,   0,\r
9770                         0,   0,   0,   0,   0,   0,   0,   0,\r
9771                         160, 128,   0, 128, 128, 128, 128, 128,\r
9772                         128, 128, 128, 128, 128, 128, 128, 128,\r
9773                         192, 192, 192, 192, 192, 192, 192, 192,\r
9774                         192, 192, 128, 128, 128, 128, 128, 128,\r
9775                         128, 128, 128, 128, 128, 128, 128, 128,\r
9776                         128, 128, 128, 128, 128, 128, 128, 128,\r
9777                         128, 128, 128, 128, 128, 128, 128, 128,\r
9778                         128, 128, 128, 128,   0, 128, 128, 128,\r
9779                         128, 128, 128, 128, 128, 128, 128, 128,\r
9780                         128, 128, 128, 128, 128, 128, 128, 128,\r
9781                         128, 128, 128, 128, 128, 128, 128, 128,\r
9782                         128, 128, 128, 128, 128, 128, 128, 128,\r
9783                         0,   0,   0,   0,   0,   0,   0,   0,\r
9784                         0,   0,   0,   0,   0,   0,   0,   0,\r
9785                         0,   0,   0,   0,   0,   0,   0,   0,\r
9786                         0,   0,   0,   0,   0,   0,   0,   0,\r
9787                         0,   0,   0,   0,   0,   0,   0,   0,\r
9788                         0,   0,   0,   0,   0,   0,   0,   0,\r
9789                         0,   0,   0,   0,   0,   0,   0,   0,\r
9790                         0,   0,   0,   0,   0,   0,   0,   0,\r
9791                         0,   0,   0,   0,   0,   0,   0,   0,\r
9792                         0,   0,   0,   0,   0,   0,   0,   0,\r
9793                         0,   0,   0,   0,   0,   0,   0,   0,\r
9794                         0,   0,   0,   0,   0,   0,   0,   0,\r
9795                         0,   0,   0,   0,   0,   0,   0,   0,\r
9796                         0,   0,   0,   0,   0,   0,   0,   0,\r
9797                         0,   0,   0,   0,   0,   0,   0,   0,\r
9798                         0,   0,   0,   0,   0,   0,   0,   0,\r
9799                     };\r
9800                     if ((m_limit - m_cursor) < 5)\r
9801                     {\r
9802                         fill_line_buffer(5);    // LCOV_EXCL_LINE\r
9803                     }\r
9804                     yych = *m_cursor;\r
9805                     if (yybm[0 + yych] & 32)\r
9806                     {\r
9807                         goto basic_json_parser_6;\r
9808                     }\r
9809                     if (yych <= '[')\r
9810                     {\r
9811                         if (yych <= '-')\r
9812                         {\r
9813                             if (yych <= '"')\r
9814                             {\r
9815                                 if (yych <= 0x00)\r
9816                                 {\r
9817                                     goto basic_json_parser_2;\r
9818                                 }\r
9819                                 if (yych <= '!')\r
9820                                 {\r
9821                                     goto basic_json_parser_4;\r
9822                                 }\r
9823                                 goto basic_json_parser_9;\r
9824                             }\r
9825                             else\r
9826                             {\r
9827                                 if (yych <= '+')\r
9828                                 {\r
9829                                     goto basic_json_parser_4;\r
9830                                 }\r
9831                                 if (yych <= ',')\r
9832                                 {\r
9833                                     goto basic_json_parser_10;\r
9834                                 }\r
9835                                 goto basic_json_parser_12;\r
9836                             }\r
9837                         }\r
9838                         else\r
9839                         {\r
9840                             if (yych <= '9')\r
9841                             {\r
9842                                 if (yych <= '/')\r
9843                                 {\r
9844                                     goto basic_json_parser_4;\r
9845                                 }\r
9846                                 if (yych <= '0')\r
9847                                 {\r
9848                                     goto basic_json_parser_13;\r
9849                                 }\r
9850                                 goto basic_json_parser_15;\r
9851                             }\r
9852                             else\r
9853                             {\r
9854                                 if (yych <= ':')\r
9855                                 {\r
9856                                     goto basic_json_parser_17;\r
9857                                 }\r
9858                                 if (yych <= 'Z')\r
9859                                 {\r
9860                                     goto basic_json_parser_4;\r
9861                                 }\r
9862                                 goto basic_json_parser_19;\r
9863                             }\r
9864                         }\r
9865                     }\r
9866                     else\r
9867                     {\r
9868                         if (yych <= 'n')\r
9869                         {\r
9870                             if (yych <= 'e')\r
9871                             {\r
9872                                 if (yych == ']')\r
9873                                 {\r
9874                                     goto basic_json_parser_21;\r
9875                                 }\r
9876                                 goto basic_json_parser_4;\r
9877                             }\r
9878                             else\r
9879                             {\r
9880                                 if (yych <= 'f')\r
9881                                 {\r
9882                                     goto basic_json_parser_23;\r
9883                                 }\r
9884                                 if (yych <= 'm')\r
9885                                 {\r
9886                                     goto basic_json_parser_4;\r
9887                                 }\r
9888                                 goto basic_json_parser_24;\r
9889                             }\r
9890                         }\r
9891                         else\r
9892                         {\r
9893                             if (yych <= 'z')\r
9894                             {\r
9895                                 if (yych == 't')\r
9896                                 {\r
9897                                     goto basic_json_parser_25;\r
9898                                 }\r
9899                                 goto basic_json_parser_4;\r
9900                             }\r
9901                             else\r
9902                             {\r
9903                                 if (yych <= '{')\r
9904                                 {\r
9905                                     goto basic_json_parser_26;\r
9906                                 }\r
9907                                 if (yych == '}')\r
9908                                 {\r
9909                                     goto basic_json_parser_28;\r
9910                                 }\r
9911                                 goto basic_json_parser_4;\r
9912                             }\r
9913                         }\r
9914                     }\r
9915 basic_json_parser_2:\r
9916                     ++m_cursor;\r
9917                     {\r
9918                         last_token_type = token_type::end_of_input;\r
9919                         break;\r
9920                     }\r
9921 basic_json_parser_4:\r
9922                     ++m_cursor;\r
9923 basic_json_parser_5:\r
9924                     {\r
9925                         last_token_type = token_type::parse_error;\r
9926                         break;\r
9927                     }\r
9928 basic_json_parser_6:\r
9929                     ++m_cursor;\r
9930                     if (m_limit <= m_cursor)\r
9931                     {\r
9932                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
9933                     }\r
9934                     yych = *m_cursor;\r
9935                     if (yybm[0 + yych] & 32)\r
9936                     {\r
9937                         goto basic_json_parser_6;\r
9938                     }\r
9939                     {\r
9940                         continue;\r
9941                     }\r
9942 basic_json_parser_9:\r
9943                     yyaccept = 0;\r
9944                     yych = *(m_marker = ++m_cursor);\r
9945                     if (yych <= 0x1F)\r
9946                     {\r
9947                         goto basic_json_parser_5;\r
9948                     }\r
9949                     if (yych <= 0x7F)\r
9950                     {\r
9951                         goto basic_json_parser_31;\r
9952                     }\r
9953                     if (yych <= 0xC1)\r
9954                     {\r
9955                         goto basic_json_parser_5;\r
9956                     }\r
9957                     if (yych <= 0xF4)\r
9958                     {\r
9959                         goto basic_json_parser_31;\r
9960                     }\r
9961                     goto basic_json_parser_5;\r
9962 basic_json_parser_10:\r
9963                     ++m_cursor;\r
9964                     {\r
9965                         last_token_type = token_type::value_separator;\r
9966                         break;\r
9967                     }\r
9968 basic_json_parser_12:\r
9969                     yych = *++m_cursor;\r
9970                     if (yych <= '/')\r
9971                     {\r
9972                         goto basic_json_parser_5;\r
9973                     }\r
9974                     if (yych <= '0')\r
9975                     {\r
9976                         goto basic_json_parser_43;\r
9977                     }\r
9978                     if (yych <= '9')\r
9979                     {\r
9980                         goto basic_json_parser_45;\r
9981                     }\r
9982                     goto basic_json_parser_5;\r
9983 basic_json_parser_13:\r
9984                     yyaccept = 1;\r
9985                     yych = *(m_marker = ++m_cursor);\r
9986                     if (yych <= '9')\r
9987                     {\r
9988                         if (yych == '.')\r
9989                         {\r
9990                             goto basic_json_parser_47;\r
9991                         }\r
9992                         if (yych >= '0')\r
9993                         {\r
9994                             goto basic_json_parser_48;\r
9995                         }\r
9996                     }\r
9997                     else\r
9998                     {\r
9999                         if (yych <= 'E')\r
10000                         {\r
10001                             if (yych >= 'E')\r
10002                             {\r
10003                                 goto basic_json_parser_51;\r
10004                             }\r
10005                         }\r
10006                         else\r
10007                         {\r
10008                             if (yych == 'e')\r
10009                             {\r
10010                                 goto basic_json_parser_51;\r
10011                             }\r
10012                         }\r
10013                     }\r
10014 basic_json_parser_14:\r
10015                     {\r
10016                         last_token_type = token_type::value_unsigned;\r
10017                         break;\r
10018                     }\r
10019 basic_json_parser_15:\r
10020                     yyaccept = 1;\r
10021                     m_marker = ++m_cursor;\r
10022                     if ((m_limit - m_cursor) < 3)\r
10023                     {\r
10024                         fill_line_buffer(3);    // LCOV_EXCL_LINE\r
10025                     }\r
10026                     yych = *m_cursor;\r
10027                     if (yybm[0 + yych] & 64)\r
10028                     {\r
10029                         goto basic_json_parser_15;\r
10030                     }\r
10031                     if (yych <= 'D')\r
10032                     {\r
10033                         if (yych == '.')\r
10034                         {\r
10035                             goto basic_json_parser_47;\r
10036                         }\r
10037                         goto basic_json_parser_14;\r
10038                     }\r
10039                     else\r
10040                     {\r
10041                         if (yych <= 'E')\r
10042                         {\r
10043                             goto basic_json_parser_51;\r
10044                         }\r
10045                         if (yych == 'e')\r
10046                         {\r
10047                             goto basic_json_parser_51;\r
10048                         }\r
10049                         goto basic_json_parser_14;\r
10050                     }\r
10051 basic_json_parser_17:\r
10052                     ++m_cursor;\r
10053                     {\r
10054                         last_token_type = token_type::name_separator;\r
10055                         break;\r
10056                     }\r
10057 basic_json_parser_19:\r
10058                     ++m_cursor;\r
10059                     {\r
10060                         last_token_type = token_type::begin_array;\r
10061                         break;\r
10062                     }\r
10063 basic_json_parser_21:\r
10064                     ++m_cursor;\r
10065                     {\r
10066                         last_token_type = token_type::end_array;\r
10067                         break;\r
10068                     }\r
10069 basic_json_parser_23:\r
10070                     yyaccept = 0;\r
10071                     yych = *(m_marker = ++m_cursor);\r
10072                     if (yych == 'a')\r
10073                     {\r
10074                         goto basic_json_parser_52;\r
10075                     }\r
10076                     goto basic_json_parser_5;\r
10077 basic_json_parser_24:\r
10078                     yyaccept = 0;\r
10079                     yych = *(m_marker = ++m_cursor);\r
10080                     if (yych == 'u')\r
10081                     {\r
10082                         goto basic_json_parser_53;\r
10083                     }\r
10084                     goto basic_json_parser_5;\r
10085 basic_json_parser_25:\r
10086                     yyaccept = 0;\r
10087                     yych = *(m_marker = ++m_cursor);\r
10088                     if (yych == 'r')\r
10089                     {\r
10090                         goto basic_json_parser_54;\r
10091                     }\r
10092                     goto basic_json_parser_5;\r
10093 basic_json_parser_26:\r
10094                     ++m_cursor;\r
10095                     {\r
10096                         last_token_type = token_type::begin_object;\r
10097                         break;\r
10098                     }\r
10099 basic_json_parser_28:\r
10100                     ++m_cursor;\r
10101                     {\r
10102                         last_token_type = token_type::end_object;\r
10103                         break;\r
10104                     }\r
10105 basic_json_parser_30:\r
10106                     ++m_cursor;\r
10107                     if (m_limit <= m_cursor)\r
10108                     {\r
10109                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10110                     }\r
10111                     yych = *m_cursor;\r
10112 basic_json_parser_31:\r
10113                     if (yybm[0 + yych] & 128)\r
10114                     {\r
10115                         goto basic_json_parser_30;\r
10116                     }\r
10117                     if (yych <= 0xE0)\r
10118                     {\r
10119                         if (yych <= '\\')\r
10120                         {\r
10121                             if (yych <= 0x1F)\r
10122                             {\r
10123                                 goto basic_json_parser_32;\r
10124                             }\r
10125                             if (yych <= '"')\r
10126                             {\r
10127                                 goto basic_json_parser_33;\r
10128                             }\r
10129                             goto basic_json_parser_35;\r
10130                         }\r
10131                         else\r
10132                         {\r
10133                             if (yych <= 0xC1)\r
10134                             {\r
10135                                 goto basic_json_parser_32;\r
10136                             }\r
10137                             if (yych <= 0xDF)\r
10138                             {\r
10139                                 goto basic_json_parser_36;\r
10140                             }\r
10141                             goto basic_json_parser_37;\r
10142                         }\r
10143                     }\r
10144                     else\r
10145                     {\r
10146                         if (yych <= 0xEF)\r
10147                         {\r
10148                             if (yych == 0xED)\r
10149                             {\r
10150                                 goto basic_json_parser_39;\r
10151                             }\r
10152                             goto basic_json_parser_38;\r
10153                         }\r
10154                         else\r
10155                         {\r
10156                             if (yych <= 0xF0)\r
10157                             {\r
10158                                 goto basic_json_parser_40;\r
10159                             }\r
10160                             if (yych <= 0xF3)\r
10161                             {\r
10162                                 goto basic_json_parser_41;\r
10163                             }\r
10164                             if (yych <= 0xF4)\r
10165                             {\r
10166                                 goto basic_json_parser_42;\r
10167                             }\r
10168                         }\r
10169                     }\r
10170 basic_json_parser_32:\r
10171                     m_cursor = m_marker;\r
10172                     if (yyaccept <= 1)\r
10173                     {\r
10174                         if (yyaccept == 0)\r
10175                         {\r
10176                             goto basic_json_parser_5;\r
10177                         }\r
10178                         else\r
10179                         {\r
10180                             goto basic_json_parser_14;\r
10181                         }\r
10182                     }\r
10183                     else\r
10184                     {\r
10185                         if (yyaccept == 2)\r
10186                         {\r
10187                             goto basic_json_parser_44;\r
10188                         }\r
10189                         else\r
10190                         {\r
10191                             goto basic_json_parser_58;\r
10192                         }\r
10193                     }\r
10194 basic_json_parser_33:\r
10195                     ++m_cursor;\r
10196                     {\r
10197                         last_token_type = token_type::value_string;\r
10198                         break;\r
10199                     }\r
10200 basic_json_parser_35:\r
10201                     ++m_cursor;\r
10202                     if (m_limit <= m_cursor)\r
10203                     {\r
10204                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10205                     }\r
10206                     yych = *m_cursor;\r
10207                     if (yych <= 'e')\r
10208                     {\r
10209                         if (yych <= '/')\r
10210                         {\r
10211                             if (yych == '"')\r
10212                             {\r
10213                                 goto basic_json_parser_30;\r
10214                             }\r
10215                             if (yych <= '.')\r
10216                             {\r
10217                                 goto basic_json_parser_32;\r
10218                             }\r
10219                             goto basic_json_parser_30;\r
10220                         }\r
10221                         else\r
10222                         {\r
10223                             if (yych <= '\\')\r
10224                             {\r
10225                                 if (yych <= '[')\r
10226                                 {\r
10227                                     goto basic_json_parser_32;\r
10228                                 }\r
10229                                 goto basic_json_parser_30;\r
10230                             }\r
10231                             else\r
10232                             {\r
10233                                 if (yych == 'b')\r
10234                                 {\r
10235                                     goto basic_json_parser_30;\r
10236                                 }\r
10237                                 goto basic_json_parser_32;\r
10238                             }\r
10239                         }\r
10240                     }\r
10241                     else\r
10242                     {\r
10243                         if (yych <= 'q')\r
10244                         {\r
10245                             if (yych <= 'f')\r
10246                             {\r
10247                                 goto basic_json_parser_30;\r
10248                             }\r
10249                             if (yych == 'n')\r
10250                             {\r
10251                                 goto basic_json_parser_30;\r
10252                             }\r
10253                             goto basic_json_parser_32;\r
10254                         }\r
10255                         else\r
10256                         {\r
10257                             if (yych <= 's')\r
10258                             {\r
10259                                 if (yych <= 'r')\r
10260                                 {\r
10261                                     goto basic_json_parser_30;\r
10262                                 }\r
10263                                 goto basic_json_parser_32;\r
10264                             }\r
10265                             else\r
10266                             {\r
10267                                 if (yych <= 't')\r
10268                                 {\r
10269                                     goto basic_json_parser_30;\r
10270                                 }\r
10271                                 if (yych <= 'u')\r
10272                                 {\r
10273                                     goto basic_json_parser_55;\r
10274                                 }\r
10275                                 goto basic_json_parser_32;\r
10276                             }\r
10277                         }\r
10278                     }\r
10279 basic_json_parser_36:\r
10280                     ++m_cursor;\r
10281                     if (m_limit <= m_cursor)\r
10282                     {\r
10283                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10284                     }\r
10285                     yych = *m_cursor;\r
10286                     if (yych <= 0x7F)\r
10287                     {\r
10288                         goto basic_json_parser_32;\r
10289                     }\r
10290                     if (yych <= 0xBF)\r
10291                     {\r
10292                         goto basic_json_parser_30;\r
10293                     }\r
10294                     goto basic_json_parser_32;\r
10295 basic_json_parser_37:\r
10296                     ++m_cursor;\r
10297                     if (m_limit <= m_cursor)\r
10298                     {\r
10299                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10300                     }\r
10301                     yych = *m_cursor;\r
10302                     if (yych <= 0x9F)\r
10303                     {\r
10304                         goto basic_json_parser_32;\r
10305                     }\r
10306                     if (yych <= 0xBF)\r
10307                     {\r
10308                         goto basic_json_parser_36;\r
10309                     }\r
10310                     goto basic_json_parser_32;\r
10311 basic_json_parser_38:\r
10312                     ++m_cursor;\r
10313                     if (m_limit <= m_cursor)\r
10314                     {\r
10315                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10316                     }\r
10317                     yych = *m_cursor;\r
10318                     if (yych <= 0x7F)\r
10319                     {\r
10320                         goto basic_json_parser_32;\r
10321                     }\r
10322                     if (yych <= 0xBF)\r
10323                     {\r
10324                         goto basic_json_parser_36;\r
10325                     }\r
10326                     goto basic_json_parser_32;\r
10327 basic_json_parser_39:\r
10328                     ++m_cursor;\r
10329                     if (m_limit <= m_cursor)\r
10330                     {\r
10331                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10332                     }\r
10333                     yych = *m_cursor;\r
10334                     if (yych <= 0x7F)\r
10335                     {\r
10336                         goto basic_json_parser_32;\r
10337                     }\r
10338                     if (yych <= 0x9F)\r
10339                     {\r
10340                         goto basic_json_parser_36;\r
10341                     }\r
10342                     goto basic_json_parser_32;\r
10343 basic_json_parser_40:\r
10344                     ++m_cursor;\r
10345                     if (m_limit <= m_cursor)\r
10346                     {\r
10347                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10348                     }\r
10349                     yych = *m_cursor;\r
10350                     if (yych <= 0x8F)\r
10351                     {\r
10352                         goto basic_json_parser_32;\r
10353                     }\r
10354                     if (yych <= 0xBF)\r
10355                     {\r
10356                         goto basic_json_parser_38;\r
10357                     }\r
10358                     goto basic_json_parser_32;\r
10359 basic_json_parser_41:\r
10360                     ++m_cursor;\r
10361                     if (m_limit <= m_cursor)\r
10362                     {\r
10363                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10364                     }\r
10365                     yych = *m_cursor;\r
10366                     if (yych <= 0x7F)\r
10367                     {\r
10368                         goto basic_json_parser_32;\r
10369                     }\r
10370                     if (yych <= 0xBF)\r
10371                     {\r
10372                         goto basic_json_parser_38;\r
10373                     }\r
10374                     goto basic_json_parser_32;\r
10375 basic_json_parser_42:\r
10376                     ++m_cursor;\r
10377                     if (m_limit <= m_cursor)\r
10378                     {\r
10379                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10380                     }\r
10381                     yych = *m_cursor;\r
10382                     if (yych <= 0x7F)\r
10383                     {\r
10384                         goto basic_json_parser_32;\r
10385                     }\r
10386                     if (yych <= 0x8F)\r
10387                     {\r
10388                         goto basic_json_parser_38;\r
10389                     }\r
10390                     goto basic_json_parser_32;\r
10391 basic_json_parser_43:\r
10392                     yyaccept = 2;\r
10393                     yych = *(m_marker = ++m_cursor);\r
10394                     if (yych <= '9')\r
10395                     {\r
10396                         if (yych == '.')\r
10397                         {\r
10398                             goto basic_json_parser_47;\r
10399                         }\r
10400                         if (yych >= '0')\r
10401                         {\r
10402                             goto basic_json_parser_48;\r
10403                         }\r
10404                     }\r
10405                     else\r
10406                     {\r
10407                         if (yych <= 'E')\r
10408                         {\r
10409                             if (yych >= 'E')\r
10410                             {\r
10411                                 goto basic_json_parser_51;\r
10412                             }\r
10413                         }\r
10414                         else\r
10415                         {\r
10416                             if (yych == 'e')\r
10417                             {\r
10418                                 goto basic_json_parser_51;\r
10419                             }\r
10420                         }\r
10421                     }\r
10422 basic_json_parser_44:\r
10423                     {\r
10424                         last_token_type = token_type::value_integer;\r
10425                         break;\r
10426                     }\r
10427 basic_json_parser_45:\r
10428                     yyaccept = 2;\r
10429                     m_marker = ++m_cursor;\r
10430                     if ((m_limit - m_cursor) < 3)\r
10431                     {\r
10432                         fill_line_buffer(3);    // LCOV_EXCL_LINE\r
10433                     }\r
10434                     yych = *m_cursor;\r
10435                     if (yych <= '9')\r
10436                     {\r
10437                         if (yych == '.')\r
10438                         {\r
10439                             goto basic_json_parser_47;\r
10440                         }\r
10441                         if (yych <= '/')\r
10442                         {\r
10443                             goto basic_json_parser_44;\r
10444                         }\r
10445                         goto basic_json_parser_45;\r
10446                     }\r
10447                     else\r
10448                     {\r
10449                         if (yych <= 'E')\r
10450                         {\r
10451                             if (yych <= 'D')\r
10452                             {\r
10453                                 goto basic_json_parser_44;\r
10454                             }\r
10455                             goto basic_json_parser_51;\r
10456                         }\r
10457                         else\r
10458                         {\r
10459                             if (yych == 'e')\r
10460                             {\r
10461                                 goto basic_json_parser_51;\r
10462                             }\r
10463                             goto basic_json_parser_44;\r
10464                         }\r
10465                     }\r
10466 basic_json_parser_47:\r
10467                     yych = *++m_cursor;\r
10468                     if (yych <= '/')\r
10469                     {\r
10470                         goto basic_json_parser_32;\r
10471                     }\r
10472                     if (yych <= '9')\r
10473                     {\r
10474                         goto basic_json_parser_56;\r
10475                     }\r
10476                     goto basic_json_parser_32;\r
10477 basic_json_parser_48:\r
10478                     ++m_cursor;\r
10479                     if (m_limit <= m_cursor)\r
10480                     {\r
10481                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10482                     }\r
10483                     yych = *m_cursor;\r
10484                     if (yych <= '/')\r
10485                     {\r
10486                         goto basic_json_parser_50;\r
10487                     }\r
10488                     if (yych <= '9')\r
10489                     {\r
10490                         goto basic_json_parser_48;\r
10491                     }\r
10492 basic_json_parser_50:\r
10493                     {\r
10494                         last_token_type = token_type::parse_error;\r
10495                         break;\r
10496                     }\r
10497 basic_json_parser_51:\r
10498                     yych = *++m_cursor;\r
10499                     if (yych <= ',')\r
10500                     {\r
10501                         if (yych == '+')\r
10502                         {\r
10503                             goto basic_json_parser_59;\r
10504                         }\r
10505                         goto basic_json_parser_32;\r
10506                     }\r
10507                     else\r
10508                     {\r
10509                         if (yych <= '-')\r
10510                         {\r
10511                             goto basic_json_parser_59;\r
10512                         }\r
10513                         if (yych <= '/')\r
10514                         {\r
10515                             goto basic_json_parser_32;\r
10516                         }\r
10517                         if (yych <= '9')\r
10518                         {\r
10519                             goto basic_json_parser_60;\r
10520                         }\r
10521                         goto basic_json_parser_32;\r
10522                     }\r
10523 basic_json_parser_52:\r
10524                     yych = *++m_cursor;\r
10525                     if (yych == 'l')\r
10526                     {\r
10527                         goto basic_json_parser_62;\r
10528                     }\r
10529                     goto basic_json_parser_32;\r
10530 basic_json_parser_53:\r
10531                     yych = *++m_cursor;\r
10532                     if (yych == 'l')\r
10533                     {\r
10534                         goto basic_json_parser_63;\r
10535                     }\r
10536                     goto basic_json_parser_32;\r
10537 basic_json_parser_54:\r
10538                     yych = *++m_cursor;\r
10539                     if (yych == 'u')\r
10540                     {\r
10541                         goto basic_json_parser_64;\r
10542                     }\r
10543                     goto basic_json_parser_32;\r
10544 basic_json_parser_55:\r
10545                     ++m_cursor;\r
10546                     if (m_limit <= m_cursor)\r
10547                     {\r
10548                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10549                     }\r
10550                     yych = *m_cursor;\r
10551                     if (yych <= '@')\r
10552                     {\r
10553                         if (yych <= '/')\r
10554                         {\r
10555                             goto basic_json_parser_32;\r
10556                         }\r
10557                         if (yych <= '9')\r
10558                         {\r
10559                             goto basic_json_parser_65;\r
10560                         }\r
10561                         goto basic_json_parser_32;\r
10562                     }\r
10563                     else\r
10564                     {\r
10565                         if (yych <= 'F')\r
10566                         {\r
10567                             goto basic_json_parser_65;\r
10568                         }\r
10569                         if (yych <= '`')\r
10570                         {\r
10571                             goto basic_json_parser_32;\r
10572                         }\r
10573                         if (yych <= 'f')\r
10574                         {\r
10575                             goto basic_json_parser_65;\r
10576                         }\r
10577                         goto basic_json_parser_32;\r
10578                     }\r
10579 basic_json_parser_56:\r
10580                     yyaccept = 3;\r
10581                     m_marker = ++m_cursor;\r
10582                     if ((m_limit - m_cursor) < 3)\r
10583                     {\r
10584                         fill_line_buffer(3);    // LCOV_EXCL_LINE\r
10585                     }\r
10586                     yych = *m_cursor;\r
10587                     if (yych <= 'D')\r
10588                     {\r
10589                         if (yych <= '/')\r
10590                         {\r
10591                             goto basic_json_parser_58;\r
10592                         }\r
10593                         if (yych <= '9')\r
10594                         {\r
10595                             goto basic_json_parser_56;\r
10596                         }\r
10597                     }\r
10598                     else\r
10599                     {\r
10600                         if (yych <= 'E')\r
10601                         {\r
10602                             goto basic_json_parser_51;\r
10603                         }\r
10604                         if (yych == 'e')\r
10605                         {\r
10606                             goto basic_json_parser_51;\r
10607                         }\r
10608                     }\r
10609 basic_json_parser_58:\r
10610                     {\r
10611                         last_token_type = token_type::value_float;\r
10612                         break;\r
10613                     }\r
10614 basic_json_parser_59:\r
10615                     yych = *++m_cursor;\r
10616                     if (yych <= '/')\r
10617                     {\r
10618                         goto basic_json_parser_32;\r
10619                     }\r
10620                     if (yych >= ':')\r
10621                     {\r
10622                         goto basic_json_parser_32;\r
10623                     }\r
10624 basic_json_parser_60:\r
10625                     ++m_cursor;\r
10626                     if (m_limit <= m_cursor)\r
10627                     {\r
10628                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10629                     }\r
10630                     yych = *m_cursor;\r
10631                     if (yych <= '/')\r
10632                     {\r
10633                         goto basic_json_parser_58;\r
10634                     }\r
10635                     if (yych <= '9')\r
10636                     {\r
10637                         goto basic_json_parser_60;\r
10638                     }\r
10639                     goto basic_json_parser_58;\r
10640 basic_json_parser_62:\r
10641                     yych = *++m_cursor;\r
10642                     if (yych == 's')\r
10643                     {\r
10644                         goto basic_json_parser_66;\r
10645                     }\r
10646                     goto basic_json_parser_32;\r
10647 basic_json_parser_63:\r
10648                     yych = *++m_cursor;\r
10649                     if (yych == 'l')\r
10650                     {\r
10651                         goto basic_json_parser_67;\r
10652                     }\r
10653                     goto basic_json_parser_32;\r
10654 basic_json_parser_64:\r
10655                     yych = *++m_cursor;\r
10656                     if (yych == 'e')\r
10657                     {\r
10658                         goto basic_json_parser_69;\r
10659                     }\r
10660                     goto basic_json_parser_32;\r
10661 basic_json_parser_65:\r
10662                     ++m_cursor;\r
10663                     if (m_limit <= m_cursor)\r
10664                     {\r
10665                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10666                     }\r
10667                     yych = *m_cursor;\r
10668                     if (yych <= '@')\r
10669                     {\r
10670                         if (yych <= '/')\r
10671                         {\r
10672                             goto basic_json_parser_32;\r
10673                         }\r
10674                         if (yych <= '9')\r
10675                         {\r
10676                             goto basic_json_parser_71;\r
10677                         }\r
10678                         goto basic_json_parser_32;\r
10679                     }\r
10680                     else\r
10681                     {\r
10682                         if (yych <= 'F')\r
10683                         {\r
10684                             goto basic_json_parser_71;\r
10685                         }\r
10686                         if (yych <= '`')\r
10687                         {\r
10688                             goto basic_json_parser_32;\r
10689                         }\r
10690                         if (yych <= 'f')\r
10691                         {\r
10692                             goto basic_json_parser_71;\r
10693                         }\r
10694                         goto basic_json_parser_32;\r
10695                     }\r
10696 basic_json_parser_66:\r
10697                     yych = *++m_cursor;\r
10698                     if (yych == 'e')\r
10699                     {\r
10700                         goto basic_json_parser_72;\r
10701                     }\r
10702                     goto basic_json_parser_32;\r
10703 basic_json_parser_67:\r
10704                     ++m_cursor;\r
10705                     {\r
10706                         last_token_type = token_type::literal_null;\r
10707                         break;\r
10708                     }\r
10709 basic_json_parser_69:\r
10710                     ++m_cursor;\r
10711                     {\r
10712                         last_token_type = token_type::literal_true;\r
10713                         break;\r
10714                     }\r
10715 basic_json_parser_71:\r
10716                     ++m_cursor;\r
10717                     if (m_limit <= m_cursor)\r
10718                     {\r
10719                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10720                     }\r
10721                     yych = *m_cursor;\r
10722                     if (yych <= '@')\r
10723                     {\r
10724                         if (yych <= '/')\r
10725                         {\r
10726                             goto basic_json_parser_32;\r
10727                         }\r
10728                         if (yych <= '9')\r
10729                         {\r
10730                             goto basic_json_parser_74;\r
10731                         }\r
10732                         goto basic_json_parser_32;\r
10733                     }\r
10734                     else\r
10735                     {\r
10736                         if (yych <= 'F')\r
10737                         {\r
10738                             goto basic_json_parser_74;\r
10739                         }\r
10740                         if (yych <= '`')\r
10741                         {\r
10742                             goto basic_json_parser_32;\r
10743                         }\r
10744                         if (yych <= 'f')\r
10745                         {\r
10746                             goto basic_json_parser_74;\r
10747                         }\r
10748                         goto basic_json_parser_32;\r
10749                     }\r
10750 basic_json_parser_72:\r
10751                     ++m_cursor;\r
10752                     {\r
10753                         last_token_type = token_type::literal_false;\r
10754                         break;\r
10755                     }\r
10756 basic_json_parser_74:\r
10757                     ++m_cursor;\r
10758                     if (m_limit <= m_cursor)\r
10759                     {\r
10760                         fill_line_buffer(1);    // LCOV_EXCL_LINE\r
10761                     }\r
10762                     yych = *m_cursor;\r
10763                     if (yych <= '@')\r
10764                     {\r
10765                         if (yych <= '/')\r
10766                         {\r
10767                             goto basic_json_parser_32;\r
10768                         }\r
10769                         if (yych <= '9')\r
10770                         {\r
10771                             goto basic_json_parser_30;\r
10772                         }\r
10773                         goto basic_json_parser_32;\r
10774                     }\r
10775                     else\r
10776                     {\r
10777                         if (yych <= 'F')\r
10778                         {\r
10779                             goto basic_json_parser_30;\r
10780                         }\r
10781                         if (yych <= '`')\r
10782                         {\r
10783                             goto basic_json_parser_32;\r
10784                         }\r
10785                         if (yych <= 'f')\r
10786                         {\r
10787                             goto basic_json_parser_30;\r
10788                         }\r
10789                         goto basic_json_parser_32;\r
10790                     }\r
10791                 }\r
10792 \r
10793             }\r
10794 \r
10795             return last_token_type;\r
10796         }\r
10797 \r
10798         /*!\r
10799         @brief append data from the stream to the line buffer\r
10800 \r
10801         This function is called by the scan() function when the end of the\r
10802         buffer (`m_limit`) is reached and the `m_cursor` pointer cannot be\r
10803         incremented without leaving the limits of the line buffer. Note re2c\r
10804         decides when to call this function.\r
10805 \r
10806         If the lexer reads from contiguous storage, there is no trailing null\r
10807         byte. Therefore, this function must make sure to add these padding\r
10808         null bytes.\r
10809 \r
10810         If the lexer reads from an input stream, this function reads the next\r
10811         line of the input.\r
10812 \r
10813         @pre\r
10814             p p p p p p u u u u u x . . . . . .\r
10815             ^           ^       ^   ^\r
10816             m_content   m_start |   m_limit\r
10817                                 m_cursor\r
10818 \r
10819         @post\r
10820             u u u u u x x x x x x x . . . . . .\r
10821             ^       ^               ^\r
10822             |       m_cursor        m_limit\r
10823             m_start\r
10824             m_content\r
10825         */\r
10826         void fill_line_buffer(size_t n = 0)\r
10827         {\r
10828             // if line buffer is used, m_content points to its data\r
10829             assert(m_line_buffer.empty()\r
10830                    or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));\r
10831 \r
10832             // if line buffer is used, m_limit is set past the end of its data\r
10833             assert(m_line_buffer.empty()\r
10834                    or m_limit == m_content + m_line_buffer.size());\r
10835 \r
10836             // pointer relationships\r
10837             assert(m_content <= m_start);\r
10838             assert(m_start <= m_cursor);\r
10839             assert(m_cursor <= m_limit);\r
10840             assert(m_marker == nullptr or m_marker  <= m_limit);\r
10841 \r
10842             // number of processed characters (p)\r
10843             const auto num_processed_chars = static_cast<size_t>(m_start - m_content);\r
10844             // offset for m_marker wrt. to m_start\r
10845             const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;\r
10846             // number of unprocessed characters (u)\r
10847             const auto offset_cursor = m_cursor - m_start;\r
10848 \r
10849             // no stream is used or end of file is reached\r
10850             if (m_stream == nullptr or m_stream->eof())\r
10851             {\r
10852                 // m_start may or may not be pointing into m_line_buffer at\r
10853                 // this point. We trust the standard library to do the right\r
10854                 // thing. See http://stackoverflow.com/q/28142011/266378\r
10855                 m_line_buffer.assign(m_start, m_limit);\r
10856 \r
10857                 // append n characters to make sure that there is sufficient\r
10858                 // space between m_cursor and m_limit\r
10859                 m_line_buffer.append(1, '\x00');\r
10860                 if (n > 0)\r
10861                 {\r
10862                     m_line_buffer.append(n - 1, '\x01');\r
10863                 }\r
10864             }\r
10865             else\r
10866             {\r
10867                 // delete processed characters from line buffer\r
10868                 m_line_buffer.erase(0, num_processed_chars);\r
10869                 // read next line from input stream\r
10870                 m_line_buffer_tmp.clear();\r
10871                 std::getline(*m_stream, m_line_buffer_tmp, '\n');\r
10872 \r
10873                 // add line with newline symbol to the line buffer\r
10874                 m_line_buffer += m_line_buffer_tmp;\r
10875                 m_line_buffer.push_back('\n');\r
10876             }\r
10877 \r
10878             // set pointers\r
10879             m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());\r
10880             assert(m_content != nullptr);\r
10881             m_start  = m_content;\r
10882             m_marker = m_start + offset_marker;\r
10883             m_cursor = m_start + offset_cursor;\r
10884             m_limit  = m_start + m_line_buffer.size();\r
10885         }\r
10886 \r
10887         /// return string representation of last read token\r
10888         string_t get_token_string() const\r
10889         {\r
10890             assert(m_start != nullptr);\r
10891             return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),\r
10892                             static_cast<size_t>(m_cursor - m_start));\r
10893         }\r
10894 \r
10895         /*!\r
10896         @brief return string value for string tokens\r
10897 \r
10898         The function iterates the characters between the opening and closing\r
10899         quotes of the string value. The complete string is the range\r
10900         [m_start,m_cursor). Consequently, we iterate from m_start+1 to\r
10901         m_cursor-1.\r
10902 \r
10903         We differentiate two cases:\r
10904 \r
10905         1. Escaped characters. In this case, a new character is constructed\r
10906            according to the nature of the escape. Some escapes create new\r
10907            characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied\r
10908            as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape\r
10909            `"\\uxxxx"` need special care. In this case, to_unicode takes care\r
10910            of the construction of the values.\r
10911         2. Unescaped characters are copied as is.\r
10912 \r
10913         @pre `m_cursor - m_start >= 2`, meaning the length of the last token\r
10914         is at least 2 bytes which is trivially true for any string (which\r
10915         consists of at least two quotes).\r
10916 \r
10917             " c1 c2 c3 ... "\r
10918             ^                ^\r
10919             m_start          m_cursor\r
10920 \r
10921         @complexity Linear in the length of the string.\n\r
10922 \r
10923         Lemma: The loop body will always terminate.\n\r
10924 \r
10925         Proof (by contradiction): Assume the loop body does not terminate. As\r
10926         the loop body does not contain another loop, one of the called\r
10927         functions must never return. The called functions are `std::strtoul`\r
10928         and to_unicode. Neither function can loop forever, so the loop body\r
10929         will never loop forever which contradicts the assumption that the loop\r
10930         body does not terminate, q.e.d.\n\r
10931 \r
10932         Lemma: The loop condition for the for loop is eventually false.\n\r
10933 \r
10934         Proof (by contradiction): Assume the loop does not terminate. Due to\r
10935         the above lemma, this can only be due to a tautological loop\r
10936         condition; that is, the loop condition i < m_cursor - 1 must always be\r
10937         true. Let x be the change of i for any loop iteration. Then\r
10938         m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This\r
10939         can be rephrased to m_cursor - m_start - 2 > x. With the\r
10940         precondition, we x <= 0, meaning that the loop condition holds\r
10941         indefinitely if i is always decreased. However, observe that the value\r
10942         of i is strictly increasing with each iteration, as it is incremented\r
10943         by 1 in the iteration expression and never decremented inside the loop\r
10944         body. Hence, the loop condition will eventually be false which\r
10945         contradicts the assumption that the loop condition is a tautology,\r
10946         q.e.d.\r
10947 \r
10948         @return string value of current token without opening and closing\r
10949         quotes\r
10950         @throw std::out_of_range if to_unicode fails\r
10951         */\r
10952         string_t get_string() const\r
10953         {\r
10954             assert(m_cursor - m_start >= 2);\r
10955 \r
10956             string_t result;\r
10957             result.reserve(static_cast<size_t>(m_cursor - m_start - 2));\r
10958 \r
10959             // iterate the result between the quotes\r
10960             for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)\r
10961             {\r
10962                 // find next escape character\r
10963                 auto e = std::find(i, m_cursor - 1, '\\');\r
10964                 if (e != i)\r
10965                 {\r
10966                     // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705\r
10967                     for (auto k = i; k < e; k++)\r
10968                     {\r
10969                         result.push_back(static_cast<typename string_t::value_type>(*k));\r
10970                     }\r
10971                     i = e - 1; // -1 because of ++i\r
10972                 }\r
10973                 else\r
10974                 {\r
10975                     // processing escaped character\r
10976                     // read next character\r
10977                     ++i;\r
10978 \r
10979                     switch (*i)\r
10980                     {\r
10981                         // the default escapes\r
10982                         case 't':\r
10983                         {\r
10984                             result += "\t";\r
10985                             break;\r
10986                         }\r
10987                         case 'b':\r
10988                         {\r
10989                             result += "\b";\r
10990                             break;\r
10991                         }\r
10992                         case 'f':\r
10993                         {\r
10994                             result += "\f";\r
10995                             break;\r
10996                         }\r
10997                         case 'n':\r
10998                         {\r
10999                             result += "\n";\r
11000                             break;\r
11001                         }\r
11002                         case 'r':\r
11003                         {\r
11004                             result += "\r";\r
11005                             break;\r
11006                         }\r
11007                         case '\\':\r
11008                         {\r
11009                             result += "\\";\r
11010                             break;\r
11011                         }\r
11012                         case '/':\r
11013                         {\r
11014                             result += "/";\r
11015                             break;\r
11016                         }\r
11017                         case '"':\r
11018                         {\r
11019                             result += "\"";\r
11020                             break;\r
11021                         }\r
11022 \r
11023                         // unicode\r
11024                         case 'u':\r
11025                         {\r
11026                             // get code xxxx from uxxxx\r
11027                             auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),\r
11028                                                           4).c_str(), nullptr, 16);\r
11029 \r
11030                             // check if codepoint is a high surrogate\r
11031                             if (codepoint >= 0xD800 and codepoint <= 0xDBFF)\r
11032                             {\r
11033                                 // make sure there is a subsequent unicode\r
11034                                 if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')\r
11035                                 {\r
11036                                     JSON_THROW(std::invalid_argument("missing low surrogate"));\r
11037                                 }\r
11038 \r
11039                                 // get code yyyy from uxxxx\uyyyy\r
11040                                 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>\r
11041                                                                (i + 7), 4).c_str(), nullptr, 16);\r
11042                                 result += to_unicode(codepoint, codepoint2);\r
11043                                 // skip the next 10 characters (xxxx\uyyyy)\r
11044                                 i += 10;\r
11045                             }\r
11046                             else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)\r
11047                             {\r
11048                                 // we found a lone low surrogate\r
11049                                 JSON_THROW(std::invalid_argument("missing high surrogate"));\r
11050                             }\r
11051                             else\r
11052                             {\r
11053                                 // add unicode character(s)\r
11054                                 result += to_unicode(codepoint);\r
11055                                 // skip the next four characters (xxxx)\r
11056                                 i += 4;\r
11057                             }\r
11058                             break;\r
11059                         }\r
11060                     }\r
11061                 }\r
11062             }\r
11063 \r
11064             return result;\r
11065         }\r
11066 \r
11067 \r
11068         /*!\r
11069         @brief parse string into a built-in arithmetic type as if the current\r
11070                locale is POSIX.\r
11071 \r
11072         @note in floating-point case strtod may parse past the token's end -\r
11073               this is not an error\r
11074 \r
11075         @note any leading blanks are not handled\r
11076         */\r
11077         struct strtonum\r
11078         {\r
11079           public:\r
11080             strtonum(const char* start, const char* end)\r
11081                 : m_start(start), m_end(end)\r
11082             {}\r
11083 \r
11084             /*!\r
11085             @return true iff parsed successfully as number of type T\r
11086 \r
11087             @param[in,out] val shall contain parsed value, or undefined value\r
11088             if could not parse\r
11089             */\r
11090             template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>\r
11091             bool to(T& val) const\r
11092             {\r
11093                 return parse(val, std::is_integral<T>());\r
11094             }\r
11095 \r
11096           private:\r
11097             const char* const m_start = nullptr;\r
11098             const char* const m_end = nullptr;\r
11099 \r
11100             // floating-point conversion\r
11101 \r
11102             // overloaded wrappers for strtod/strtof/strtold\r
11103             // that will be called from parse<floating_point_t>\r
11104             static void strtof(float& f, const char* str, char** endptr)\r
11105             {\r
11106                 f = std::strtof(str, endptr);\r
11107             }\r
11108 \r
11109             static void strtof(double& f, const char* str, char** endptr)\r
11110             {\r
11111                 f = std::strtod(str, endptr);\r
11112             }\r
11113 \r
11114             static void strtof(long double& f, const char* str, char** endptr)\r
11115             {\r
11116                 f = std::strtold(str, endptr);\r
11117             }\r
11118 \r
11119             template<typename T>\r
11120             bool parse(T& value, /*is_integral=*/std::false_type) const\r
11121             {\r
11122                 // replace decimal separator with locale-specific version,\r
11123                 // when necessary; data will point to either the original\r
11124                 // string, or buf, or tempstr containing the fixed string.\r
11125                 std::string tempstr;\r
11126                 std::array<char, 64> buf;\r
11127                 const size_t len = static_cast<size_t>(m_end - m_start);\r
11128 \r
11129                 // lexer will reject empty numbers\r
11130                 assert(len > 0);\r
11131 \r
11132                 // since dealing with strtod family of functions, we're\r
11133                 // getting the decimal point char from the C locale facilities\r
11134                 // instead of C++'s numpunct facet of the current std::locale\r
11135                 const auto loc = localeconv();\r
11136                 assert(loc != nullptr);\r
11137                 const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];\r
11138 \r
11139                 const char* data = m_start;\r
11140 \r
11141                 if (decimal_point_char != '.')\r
11142                 {\r
11143                     const size_t ds_pos = static_cast<size_t>(std::find(m_start, m_end, '.') - m_start);\r
11144 \r
11145                     if (ds_pos != len)\r
11146                     {\r
11147                         // copy the data into the local buffer or tempstr, if\r
11148                         // buffer is too small; replace decimal separator, and\r
11149                         // update data to point to the modified bytes\r
11150                         if ((len + 1) < buf.size())\r
11151                         {\r
11152                             std::copy(m_start, m_end, buf.begin());\r
11153                             buf[len] = 0;\r
11154                             buf[ds_pos] = decimal_point_char;\r
11155                             data = buf.data();\r
11156                         }\r
11157                         else\r
11158                         {\r
11159                             tempstr.assign(m_start, m_end);\r
11160                             tempstr[ds_pos] = decimal_point_char;\r
11161                             data = tempstr.c_str();\r
11162                         }\r
11163                     }\r
11164                 }\r
11165 \r
11166                 char* endptr = nullptr;\r
11167                 value = 0;\r
11168                 // this calls appropriate overload depending on T\r
11169                 strtof(value, data, &endptr);\r
11170 \r
11171                 // parsing was successful iff strtof parsed exactly the number\r
11172                 // of characters determined by the lexer (len)\r
11173                 const bool ok = (endptr == (data + len));\r
11174 \r
11175                 if (ok and (value == static_cast<T>(0.0)) and (*data == '-'))\r
11176                 {\r
11177                     // some implementations forget to negate the zero\r
11178                     value = -0.0;\r
11179                 }\r
11180 \r
11181                 return ok;\r
11182             }\r
11183 \r
11184             // integral conversion\r
11185 \r
11186             signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const\r
11187             {\r
11188                 return std::strtoll(m_start, endptr, 10);\r
11189             }\r
11190 \r
11191             unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const\r
11192             {\r
11193                 return std::strtoull(m_start, endptr, 10);\r
11194             }\r
11195 \r
11196             template<typename T>\r
11197             bool parse(T& value, /*is_integral=*/std::true_type) const\r
11198             {\r
11199                 char* endptr = nullptr;\r
11200                 errno = 0; // these are thread-local\r
11201                 const auto x = parse_integral(&endptr, std::is_signed<T>());\r
11202 \r
11203                 // called right overload?\r
11204                 static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(), "");\r
11205 \r
11206                 value = static_cast<T>(x);\r
11207 \r
11208                 return (x == static_cast<decltype(x)>(value)) // x fits into destination T\r
11209                        and (x < 0) == (value < 0)             // preserved sign\r
11210                        //and ((x != 0) or is_integral())        // strto[u]ll did nto fail\r
11211                        and (errno == 0)                       // strto[u]ll did not overflow\r
11212                        and (m_start < m_end)                  // token was not empty\r
11213                        and (endptr == m_end);                 // parsed entire token exactly\r
11214             }\r
11215         };\r
11216 \r
11217         /*!\r
11218         @brief return number value for number tokens\r
11219 \r
11220         This function translates the last token into the most appropriate\r
11221         number type (either integer, unsigned integer or floating point),\r
11222         which is passed back to the caller via the result parameter.\r
11223 \r
11224         integral numbers that don't fit into the the range of the respective\r
11225         type are parsed as number_float_t\r
11226 \r
11227         floating-point values do not satisfy std::isfinite predicate\r
11228         are converted to value_t::null\r
11229 \r
11230         throws if the entire string [m_start .. m_cursor) cannot be\r
11231         interpreted as a number\r
11232 \r
11233         @param[out] result  @ref basic_json object to receive the number.\r
11234         @param[in]  token   the type of the number token\r
11235         */\r
11236         bool get_number(basic_json& result, const token_type token) const\r
11237         {\r
11238             assert(m_start != nullptr);\r
11239             assert(m_start < m_cursor);\r
11240             assert((token == token_type::value_unsigned) or\r
11241                    (token == token_type::value_integer) or\r
11242                    (token == token_type::value_float));\r
11243 \r
11244             strtonum num_converter(reinterpret_cast<const char*>(m_start),\r
11245                                    reinterpret_cast<const char*>(m_cursor));\r
11246 \r
11247             switch (token)\r
11248             {\r
11249                 case lexer::token_type::value_unsigned:\r
11250                 {\r
11251                     number_unsigned_t val;\r
11252                     if (num_converter.to(val))\r
11253                     {\r
11254                         // parsing successful\r
11255                         result.m_type = value_t::number_unsigned;\r
11256                         result.m_value = val;\r
11257                         return true;\r
11258                     }\r
11259                     break;\r
11260                 }\r
11261 \r
11262                 case lexer::token_type::value_integer:\r
11263                 {\r
11264                     number_integer_t val;\r
11265                     if (num_converter.to(val))\r
11266                     {\r
11267                         // parsing successful\r
11268                         result.m_type = value_t::number_integer;\r
11269                         result.m_value = val;\r
11270                         return true;\r
11271                     }\r
11272                     break;\r
11273                 }\r
11274 \r
11275                 default:\r
11276                 {\r
11277                     break;\r
11278                 }\r
11279             }\r
11280 \r
11281             // parse float (either explicitly or because a previous conversion\r
11282             // failed)\r
11283             number_float_t val;\r
11284             if (num_converter.to(val))\r
11285             {\r
11286                 // parsing successful\r
11287                 result.m_type = value_t::number_float;\r
11288                 result.m_value = val;\r
11289 \r
11290                 // replace infinity and NAN by null\r
11291                 if (not std::isfinite(result.m_value.number_float))\r
11292                 {\r
11293                     result.m_type  = value_t::null;\r
11294                     result.m_value = basic_json::json_value();\r
11295                 }\r
11296 \r
11297                 return true;\r
11298             }\r
11299 \r
11300             // couldn't parse number in any format\r
11301             return false;\r
11302         }\r
11303 \r
11304       private:\r
11305         /// optional input stream\r
11306         std::istream* m_stream = nullptr;\r
11307         /// line buffer buffer for m_stream\r
11308         string_t m_line_buffer {};\r
11309         /// used for filling m_line_buffer\r
11310         string_t m_line_buffer_tmp {};\r
11311         /// the buffer pointer\r
11312         const lexer_char_t* m_content = nullptr;\r
11313         /// pointer to the beginning of the current symbol\r
11314         const lexer_char_t* m_start = nullptr;\r
11315         /// pointer for backtracking information\r
11316         const lexer_char_t* m_marker = nullptr;\r
11317         /// pointer to the current symbol\r
11318         const lexer_char_t* m_cursor = nullptr;\r
11319         /// pointer to the end of the buffer\r
11320         const lexer_char_t* m_limit = nullptr;\r
11321         /// the last token type\r
11322         token_type last_token_type = token_type::end_of_input;\r
11323     };\r
11324 \r
11325     /*!\r
11326     @brief syntax analysis\r
11327 \r
11328     This class implements a recursive decent parser.\r
11329     */\r
11330     class parser\r
11331     {\r
11332       public:\r
11333         /// a parser reading from a string literal\r
11334         parser(const char* buff, const parser_callback_t cb = nullptr)\r
11335             : callback(cb),\r
11336               m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))\r
11337         {}\r
11338 \r
11339         /// a parser reading from an input stream\r
11340         parser(std::istream& is, const parser_callback_t cb = nullptr)\r
11341             : callback(cb), m_lexer(is)\r
11342         {}\r
11343 \r
11344         /// a parser reading from an iterator range with contiguous storage\r
11345         template<class IteratorType, typename std::enable_if<\r
11346                      std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value\r
11347                      , int>::type\r
11348                  = 0>\r
11349         parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)\r
11350             : callback(cb),\r
11351               m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),\r
11352                       static_cast<size_t>(std::distance(first, last)))\r
11353         {}\r
11354 \r
11355         /// public parser interface\r
11356         basic_json parse()\r
11357         {\r
11358             // read first token\r
11359             get_token();\r
11360 \r
11361             basic_json result = parse_internal(true);\r
11362             result.assert_invariant();\r
11363 \r
11364             expect(lexer::token_type::end_of_input);\r
11365 \r
11366             // return parser result and replace it with null in case the\r
11367             // top-level value was discarded by the callback function\r
11368             return result.is_discarded() ? basic_json() : std::move(result);\r
11369         }\r
11370 \r
11371       private:\r
11372         /// the actual parser\r
11373         basic_json parse_internal(bool keep)\r
11374         {\r
11375             auto result = basic_json(value_t::discarded);\r
11376 \r
11377             switch (last_token)\r
11378             {\r
11379                 case lexer::token_type::begin_object:\r
11380                 {\r
11381                     if (keep and (not callback\r
11382                                   or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))\r
11383                     {\r
11384                         // explicitly set result to object to cope with {}\r
11385                         result.m_type = value_t::object;\r
11386                         result.m_value = value_t::object;\r
11387                     }\r
11388 \r
11389                     // read next token\r
11390                     get_token();\r
11391 \r
11392                     // closing } -> we are done\r
11393                     if (last_token == lexer::token_type::end_object)\r
11394                     {\r
11395                         get_token();\r
11396                         if (keep and callback and not callback(--depth, parse_event_t::object_end, result))\r
11397                         {\r
11398                             result = basic_json(value_t::discarded);\r
11399                         }\r
11400                         return result;\r
11401                     }\r
11402 \r
11403                     // no comma is expected here\r
11404                     unexpect(lexer::token_type::value_separator);\r
11405 \r
11406                     // otherwise: parse key-value pairs\r
11407                     do\r
11408                     {\r
11409                         // ugly, but could be fixed with loop reorganization\r
11410                         if (last_token == lexer::token_type::value_separator)\r
11411                         {\r
11412                             get_token();\r
11413                         }\r
11414 \r
11415                         // store key\r
11416                         expect(lexer::token_type::value_string);\r
11417                         const auto key = m_lexer.get_string();\r
11418 \r
11419                         bool keep_tag = false;\r
11420                         if (keep)\r
11421                         {\r
11422                             if (callback)\r
11423                             {\r
11424                                 basic_json k(key);\r
11425                                 keep_tag = callback(depth, parse_event_t::key, k);\r
11426                             }\r
11427                             else\r
11428                             {\r
11429                                 keep_tag = true;\r
11430                             }\r
11431                         }\r
11432 \r
11433                         // parse separator (:)\r
11434                         get_token();\r
11435                         expect(lexer::token_type::name_separator);\r
11436 \r
11437                         // parse and add value\r
11438                         get_token();\r
11439                         auto value = parse_internal(keep);\r
11440                         if (keep and keep_tag and not value.is_discarded())\r
11441                         {\r
11442                             result[key] = std::move(value);\r
11443                         }\r
11444                     }\r
11445                     while (last_token == lexer::token_type::value_separator);\r
11446 \r
11447                     // closing }\r
11448                     expect(lexer::token_type::end_object);\r
11449                     get_token();\r
11450                     if (keep and callback and not callback(--depth, parse_event_t::object_end, result))\r
11451                     {\r
11452                         result = basic_json(value_t::discarded);\r
11453                     }\r
11454 \r
11455                     return result;\r
11456                 }\r
11457 \r
11458                 case lexer::token_type::begin_array:\r
11459                 {\r
11460                     if (keep and (not callback\r
11461                                   or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))\r
11462                     {\r
11463                         // explicitly set result to object to cope with []\r
11464                         result.m_type = value_t::array;\r
11465                         result.m_value = value_t::array;\r
11466                     }\r
11467 \r
11468                     // read next token\r
11469                     get_token();\r
11470 \r
11471                     // closing ] -> we are done\r
11472                     if (last_token == lexer::token_type::end_array)\r
11473                     {\r
11474                         get_token();\r
11475                         if (callback and not callback(--depth, parse_event_t::array_end, result))\r
11476                         {\r
11477                             result = basic_json(value_t::discarded);\r
11478                         }\r
11479                         return result;\r
11480                     }\r
11481 \r
11482                     // no comma is expected here\r
11483                     unexpect(lexer::token_type::value_separator);\r
11484 \r
11485                     // otherwise: parse values\r
11486                     do\r
11487                     {\r
11488                         // ugly, but could be fixed with loop reorganization\r
11489                         if (last_token == lexer::token_type::value_separator)\r
11490                         {\r
11491                             get_token();\r
11492                         }\r
11493 \r
11494                         // parse value\r
11495                         auto value = parse_internal(keep);\r
11496                         if (keep and not value.is_discarded())\r
11497                         {\r
11498                             result.push_back(std::move(value));\r
11499                         }\r
11500                     }\r
11501                     while (last_token == lexer::token_type::value_separator);\r
11502 \r
11503                     // closing ]\r
11504                     expect(lexer::token_type::end_array);\r
11505                     get_token();\r
11506                     if (keep and callback and not callback(--depth, parse_event_t::array_end, result))\r
11507                     {\r
11508                         result = basic_json(value_t::discarded);\r
11509                     }\r
11510 \r
11511                     return result;\r
11512                 }\r
11513 \r
11514                 case lexer::token_type::literal_null:\r
11515                 {\r
11516                     get_token();\r
11517                     result.m_type = value_t::null;\r
11518                     break;\r
11519                 }\r
11520 \r
11521                 case lexer::token_type::value_string:\r
11522                 {\r
11523                     const auto s = m_lexer.get_string();\r
11524                     get_token();\r
11525                     result = basic_json(s);\r
11526                     break;\r
11527                 }\r
11528 \r
11529                 case lexer::token_type::literal_true:\r
11530                 {\r
11531                     get_token();\r
11532                     result.m_type = value_t::boolean;\r
11533                     result.m_value = true;\r
11534                     break;\r
11535                 }\r
11536 \r
11537                 case lexer::token_type::literal_false:\r
11538                 {\r
11539                     get_token();\r
11540                     result.m_type = value_t::boolean;\r
11541                     result.m_value = false;\r
11542                     break;\r
11543                 }\r
11544 \r
11545                 case lexer::token_type::value_unsigned:\r
11546                 case lexer::token_type::value_integer:\r
11547                 case lexer::token_type::value_float:\r
11548                 {\r
11549                     m_lexer.get_number(result, last_token);\r
11550                     get_token();\r
11551                     break;\r
11552                 }\r
11553 \r
11554                 default:\r
11555                 {\r
11556                     // the last token was unexpected\r
11557                     unexpect(last_token);\r
11558                 }\r
11559             }\r
11560 \r
11561             if (keep and callback and not callback(depth, parse_event_t::value, result))\r
11562             {\r
11563                 result = basic_json(value_t::discarded);\r
11564             }\r
11565             return result;\r
11566         }\r
11567 \r
11568         /// get next token from lexer\r
11569         typename lexer::token_type get_token()\r
11570         {\r
11571             last_token = m_lexer.scan();\r
11572             return last_token;\r
11573         }\r
11574 \r
11575         void expect(typename lexer::token_type t) const\r
11576         {\r
11577             if (t != last_token)\r
11578             {\r
11579                 std::string error_msg = "parse error - unexpected ";\r
11580                 error_msg += (last_token == lexer::token_type::parse_error ? ("'" +  m_lexer.get_token_string() +\r
11581                               "'") :\r
11582                               lexer::token_type_name(last_token));\r
11583                 error_msg += "; expected " + lexer::token_type_name(t);\r
11584                 JSON_THROW(std::invalid_argument(error_msg));\r
11585             }\r
11586         }\r
11587 \r
11588         void unexpect(typename lexer::token_type t) const\r
11589         {\r
11590             if (t == last_token)\r
11591             {\r
11592                 std::string error_msg = "parse error - unexpected ";\r
11593                 error_msg += (last_token == lexer::token_type::parse_error ? ("'" +  m_lexer.get_token_string() +\r
11594                               "'") :\r
11595                               lexer::token_type_name(last_token));\r
11596                 JSON_THROW(std::invalid_argument(error_msg));\r
11597             }\r
11598         }\r
11599 \r
11600       private:\r
11601         /// current level of recursion\r
11602         int depth = 0;\r
11603         /// callback function\r
11604         const parser_callback_t callback = nullptr;\r
11605         /// the type of the last read token\r
11606         typename lexer::token_type last_token = lexer::token_type::uninitialized;\r
11607         /// the lexer\r
11608         lexer m_lexer;\r
11609     };\r
11610 \r
11611   public:\r
11612     /*!\r
11613     @brief JSON Pointer\r
11614 \r
11615     A JSON pointer defines a string syntax for identifying a specific value\r
11616     within a JSON document. It can be used with functions `at` and\r
11617     `operator[]`. Furthermore, JSON pointers are the base for JSON patches.\r
11618 \r
11619     @sa [RFC 6901](https://tools.ietf.org/html/rfc6901)\r
11620 \r
11621     @since version 2.0.0\r
11622     */\r
11623     class json_pointer\r
11624     {\r
11625         /// allow basic_json to access private members\r
11626         friend class basic_json;\r
11627 \r
11628       public:\r
11629         /*!\r
11630         @brief create JSON pointer\r
11631 \r
11632         Create a JSON pointer according to the syntax described in\r
11633         [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).\r
11634 \r
11635         @param[in] s  string representing the JSON pointer; if omitted, the\r
11636                       empty string is assumed which references the whole JSON\r
11637                       value\r
11638 \r
11639         @throw std::domain_error if reference token is nonempty and does not\r
11640         begin with a slash (`/`); example: `"JSON pointer must be empty or\r
11641         begin with /"`\r
11642         @throw std::domain_error if a tilde (`~`) is not followed by `0`\r
11643         (representing `~`) or `1` (representing `/`); example: `"escape error:\r
11644         ~ must be followed with 0 or 1"`\r
11645 \r
11646         @liveexample{The example shows the construction several valid JSON\r
11647         pointers as well as the exceptional behavior.,json_pointer}\r
11648 \r
11649         @since version 2.0.0\r
11650         */\r
11651         explicit json_pointer(const std::string& s = "")\r
11652             : reference_tokens(split(s))\r
11653         {}\r
11654 \r
11655         /*!\r
11656         @brief return a string representation of the JSON pointer\r
11657 \r
11658         @invariant For each JSON pointer `ptr`, it holds:\r
11659         @code {.cpp}\r
11660         ptr == json_pointer(ptr.to_string());\r
11661         @endcode\r
11662 \r
11663         @return a string representation of the JSON pointer\r
11664 \r
11665         @liveexample{The example shows the result of `to_string`.,\r
11666         json_pointer__to_string}\r
11667 \r
11668         @since version 2.0.0\r
11669         */\r
11670         std::string to_string() const noexcept\r
11671         {\r
11672             return std::accumulate(reference_tokens.begin(),\r
11673                                    reference_tokens.end(), std::string{},\r
11674                                    [](const std::string & a, const std::string & b)\r
11675             {\r
11676                 return a + "/" + escape(b);\r
11677             });\r
11678         }\r
11679 \r
11680         /// @copydoc to_string()\r
11681         operator std::string() const\r
11682         {\r
11683             return to_string();\r
11684         }\r
11685 \r
11686       private:\r
11687         /// remove and return last reference pointer\r
11688         std::string pop_back()\r
11689         {\r
11690             if (is_root())\r
11691             {\r
11692                 JSON_THROW(std::domain_error("JSON pointer has no parent"));\r
11693             }\r
11694 \r
11695             auto last = reference_tokens.back();\r
11696             reference_tokens.pop_back();\r
11697             return last;\r
11698         }\r
11699 \r
11700         /// return whether pointer points to the root document\r
11701         bool is_root() const\r
11702         {\r
11703             return reference_tokens.empty();\r
11704         }\r
11705 \r
11706         json_pointer top() const\r
11707         {\r
11708             if (is_root())\r
11709             {\r
11710                 JSON_THROW(std::domain_error("JSON pointer has no parent"));\r
11711             }\r
11712 \r
11713             json_pointer result = *this;\r
11714             result.reference_tokens = {reference_tokens[0]};\r
11715             return result;\r
11716         }\r
11717 \r
11718         /*!\r
11719         @brief create and return a reference to the pointed to value\r
11720 \r
11721         @complexity Linear in the number of reference tokens.\r
11722         */\r
11723         reference get_and_create(reference j) const\r
11724         {\r
11725             pointer result = &j;\r
11726 \r
11727             // in case no reference tokens exist, return a reference to the\r
11728             // JSON value j which will be overwritten by a primitive value\r
11729             for (const auto& reference_token : reference_tokens)\r
11730             {\r
11731                 switch (result->m_type)\r
11732                 {\r
11733                     case value_t::null:\r
11734                     {\r
11735                         if (reference_token == "0")\r
11736                         {\r
11737                             // start a new array if reference token is 0\r
11738                             result = &result->operator[](0);\r
11739                         }\r
11740                         else\r
11741                         {\r
11742                             // start a new object otherwise\r
11743                             result = &result->operator[](reference_token);\r
11744                         }\r
11745                         break;\r
11746                     }\r
11747 \r
11748                     case value_t::object:\r
11749                     {\r
11750                         // create an entry in the object\r
11751                         result = &result->operator[](reference_token);\r
11752                         break;\r
11753                     }\r
11754 \r
11755                     case value_t::array:\r
11756                     {\r
11757                         // create an entry in the array\r
11758                         result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));\r
11759                         break;\r
11760                     }\r
11761 \r
11762                     /*\r
11763                     The following code is only reached if there exists a\r
11764                     reference token _and_ the current value is primitive. In\r
11765                     this case, we have an error situation, because primitive\r
11766                     values may only occur as single value; that is, with an\r
11767                     empty list of reference tokens.\r
11768                     */\r
11769                     default:\r
11770                     {\r
11771                         JSON_THROW(std::domain_error("invalid value to unflatten"));\r
11772                     }\r
11773                 }\r
11774             }\r
11775 \r
11776             return *result;\r
11777         }\r
11778 \r
11779         /*!\r
11780         @brief return a reference to the pointed to value\r
11781 \r
11782         @note This version does not throw if a value is not present, but tries\r
11783         to create nested values instead. For instance, calling this function\r
11784         with pointer `"/this/that"` on a null value is equivalent to calling\r
11785         `operator[]("this").operator[]("that")` on that value, effectively\r
11786         changing the null value to an object.\r
11787 \r
11788         @param[in] ptr  a JSON value\r
11789 \r
11790         @return reference to the JSON value pointed to by the JSON pointer\r
11791 \r
11792         @complexity Linear in the length of the JSON pointer.\r
11793 \r
11794         @throw std::out_of_range      if the JSON pointer can not be resolved\r
11795         @throw std::domain_error      if an array index begins with '0'\r
11796         @throw std::invalid_argument  if an array index was not a number\r
11797         */\r
11798         reference get_unchecked(pointer ptr) const\r
11799         {\r
11800             for (const auto& reference_token : reference_tokens)\r
11801             {\r
11802                 // convert null values to arrays or objects before continuing\r
11803                 if (ptr->m_type == value_t::null)\r
11804                 {\r
11805                     // check if reference token is a number\r
11806                     const bool nums = std::all_of(reference_token.begin(),\r
11807                                                   reference_token.end(),\r
11808                                                   [](const char x)\r
11809                     {\r
11810                         return std::isdigit(x);\r
11811                     });\r
11812 \r
11813                     // change value to array for numbers or "-" or to object\r
11814                     // otherwise\r
11815                     if (nums or reference_token == "-")\r
11816                     {\r
11817                         *ptr = value_t::array;\r
11818                     }\r
11819                     else\r
11820                     {\r
11821                         *ptr = value_t::object;\r
11822                     }\r
11823                 }\r
11824 \r
11825                 switch (ptr->m_type)\r
11826                 {\r
11827                     case value_t::object:\r
11828                     {\r
11829                         // use unchecked object access\r
11830                         ptr = &ptr->operator[](reference_token);\r
11831                         break;\r
11832                     }\r
11833 \r
11834                     case value_t::array:\r
11835                     {\r
11836                         // error condition (cf. RFC 6901, Sect. 4)\r
11837                         if (reference_token.size() > 1 and reference_token[0] == '0')\r
11838                         {\r
11839                             JSON_THROW(std::domain_error("array index must not begin with '0'"));\r
11840                         }\r
11841 \r
11842                         if (reference_token == "-")\r
11843                         {\r
11844                             // explicitly treat "-" as index beyond the end\r
11845                             ptr = &ptr->operator[](ptr->m_value.array->size());\r
11846                         }\r
11847                         else\r
11848                         {\r
11849                             // convert array index to number; unchecked access\r
11850                             ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));\r
11851                         }\r
11852                         break;\r
11853                     }\r
11854 \r
11855                     default:\r
11856                     {\r
11857                         JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));\r
11858                     }\r
11859                 }\r
11860             }\r
11861 \r
11862             return *ptr;\r
11863         }\r
11864 \r
11865         reference get_checked(pointer ptr) const\r
11866         {\r
11867             for (const auto& reference_token : reference_tokens)\r
11868             {\r
11869                 switch (ptr->m_type)\r
11870                 {\r
11871                     case value_t::object:\r
11872                     {\r
11873                         // note: at performs range check\r
11874                         ptr = &ptr->at(reference_token);\r
11875                         break;\r
11876                     }\r
11877 \r
11878                     case value_t::array:\r
11879                     {\r
11880                         if (reference_token == "-")\r
11881                         {\r
11882                             // "-" always fails the range check\r
11883                             JSON_THROW(std::out_of_range("array index '-' (" +\r
11884                                                          std::to_string(ptr->m_value.array->size()) +\r
11885                                                          ") is out of range"));\r
11886                         }\r
11887 \r
11888                         // error condition (cf. RFC 6901, Sect. 4)\r
11889                         if (reference_token.size() > 1 and reference_token[0] == '0')\r
11890                         {\r
11891                             JSON_THROW(std::domain_error("array index must not begin with '0'"));\r
11892                         }\r
11893 \r
11894                         // note: at performs range check\r
11895                         ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));\r
11896                         break;\r
11897                     }\r
11898 \r
11899                     default:\r
11900                     {\r
11901                         JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));\r
11902                     }\r
11903                 }\r
11904             }\r
11905 \r
11906             return *ptr;\r
11907         }\r
11908 \r
11909         /*!\r
11910         @brief return a const reference to the pointed to value\r
11911 \r
11912         @param[in] ptr  a JSON value\r
11913 \r
11914         @return const reference to the JSON value pointed to by the JSON\r
11915                 pointer\r
11916         */\r
11917         const_reference get_unchecked(const_pointer ptr) const\r
11918         {\r
11919             for (const auto& reference_token : reference_tokens)\r
11920             {\r
11921                 switch (ptr->m_type)\r
11922                 {\r
11923                     case value_t::object:\r
11924                     {\r
11925                         // use unchecked object access\r
11926                         ptr = &ptr->operator[](reference_token);\r
11927                         break;\r
11928                     }\r
11929 \r
11930                     case value_t::array:\r
11931                     {\r
11932                         if (reference_token == "-")\r
11933                         {\r
11934                             // "-" cannot be used for const access\r
11935                             JSON_THROW(std::out_of_range("array index '-' (" +\r
11936                                                          std::to_string(ptr->m_value.array->size()) +\r
11937                                                          ") is out of range"));\r
11938                         }\r
11939 \r
11940                         // error condition (cf. RFC 6901, Sect. 4)\r
11941                         if (reference_token.size() > 1 and reference_token[0] == '0')\r
11942                         {\r
11943                             JSON_THROW(std::domain_error("array index must not begin with '0'"));\r
11944                         }\r
11945 \r
11946                         // use unchecked array access\r
11947                         ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));\r
11948                         break;\r
11949                     }\r
11950 \r
11951                     default:\r
11952                     {\r
11953                         JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));\r
11954                     }\r
11955                 }\r
11956             }\r
11957 \r
11958             return *ptr;\r
11959         }\r
11960 \r
11961         const_reference get_checked(const_pointer ptr) const\r
11962         {\r
11963             for (const auto& reference_token : reference_tokens)\r
11964             {\r
11965                 switch (ptr->m_type)\r
11966                 {\r
11967                     case value_t::object:\r
11968                     {\r
11969                         // note: at performs range check\r
11970                         ptr = &ptr->at(reference_token);\r
11971                         break;\r
11972                     }\r
11973 \r
11974                     case value_t::array:\r
11975                     {\r
11976                         if (reference_token == "-")\r
11977                         {\r
11978                             // "-" always fails the range check\r
11979                             JSON_THROW(std::out_of_range("array index '-' (" +\r
11980                                                          std::to_string(ptr->m_value.array->size()) +\r
11981                                                          ") is out of range"));\r
11982                         }\r
11983 \r
11984                         // error condition (cf. RFC 6901, Sect. 4)\r
11985                         if (reference_token.size() > 1 and reference_token[0] == '0')\r
11986                         {\r
11987                             JSON_THROW(std::domain_error("array index must not begin with '0'"));\r
11988                         }\r
11989 \r
11990                         // note: at performs range check\r
11991                         ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));\r
11992                         break;\r
11993                     }\r
11994 \r
11995                     default:\r
11996                     {\r
11997                         JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));\r
11998                     }\r
11999                 }\r
12000             }\r
12001 \r
12002             return *ptr;\r
12003         }\r
12004 \r
12005         /// split the string input to reference tokens\r
12006         static std::vector<std::string> split(const std::string& reference_string)\r
12007         {\r
12008             std::vector<std::string> result;\r
12009 \r
12010             // special case: empty reference string -> no reference tokens\r
12011             if (reference_string.empty())\r
12012             {\r
12013                 return result;\r
12014             }\r
12015 \r
12016             // check if nonempty reference string begins with slash\r
12017             if (reference_string[0] != '/')\r
12018             {\r
12019                 JSON_THROW(std::domain_error("JSON pointer must be empty or begin with '/'"));\r
12020             }\r
12021 \r
12022             // extract the reference tokens:\r
12023             // - slash: position of the last read slash (or end of string)\r
12024             // - start: position after the previous slash\r
12025             for (\r
12026                 // search for the first slash after the first character\r
12027                 size_t slash = reference_string.find_first_of('/', 1),\r
12028                 // set the beginning of the first reference token\r
12029                 start = 1;\r
12030                 // we can stop if start == string::npos+1 = 0\r
12031                 start != 0;\r
12032                 // set the beginning of the next reference token\r
12033                 // (will eventually be 0 if slash == std::string::npos)\r
12034                 start = slash + 1,\r
12035                 // find next slash\r
12036                 slash = reference_string.find_first_of('/', start))\r
12037             {\r
12038                 // use the text between the beginning of the reference token\r
12039                 // (start) and the last slash (slash).\r
12040                 auto reference_token = reference_string.substr(start, slash - start);\r
12041 \r
12042                 // check reference tokens are properly escaped\r
12043                 for (size_t pos = reference_token.find_first_of('~');\r
12044                         pos != std::string::npos;\r
12045                         pos = reference_token.find_first_of('~', pos + 1))\r
12046                 {\r
12047                     assert(reference_token[pos] == '~');\r
12048 \r
12049                     // ~ must be followed by 0 or 1\r
12050                     if (pos == reference_token.size() - 1 or\r
12051                             (reference_token[pos + 1] != '0' and\r
12052                              reference_token[pos + 1] != '1'))\r
12053                     {\r
12054                         JSON_THROW(std::domain_error("escape error: '~' must be followed with '0' or '1'"));\r
12055                     }\r
12056                 }\r
12057 \r
12058                 // finally, store the reference token\r
12059                 unescape(reference_token);\r
12060                 result.push_back(reference_token);\r
12061             }\r
12062 \r
12063             return result;\r
12064         }\r
12065 \r
12066       private:\r
12067         /*!\r
12068         @brief replace all occurrences of a substring by another string\r
12069 \r
12070         @param[in,out] s  the string to manipulate; changed so that all\r
12071                           occurrences of @a f are replaced with @a t\r
12072         @param[in]     f  the substring to replace with @a t\r
12073         @param[in]     t  the string to replace @a f\r
12074 \r
12075         @pre The search string @a f must not be empty.\r
12076 \r
12077         @since version 2.0.0\r
12078         */\r
12079         static void replace_substring(std::string& s,\r
12080                                       const std::string& f,\r
12081                                       const std::string& t)\r
12082         {\r
12083             assert(not f.empty());\r
12084 \r
12085             for (\r
12086                 size_t pos = s.find(f);         // find first occurrence of f\r
12087                 pos != std::string::npos;       // make sure f was found\r
12088                 s.replace(pos, f.size(), t),    // replace with t\r
12089                 pos = s.find(f, pos + t.size()) // find next occurrence of f\r
12090             );\r
12091         }\r
12092 \r
12093         /// escape tilde and slash\r
12094         static std::string escape(std::string s)\r
12095         {\r
12096             // escape "~"" to "~0" and "/" to "~1"\r
12097             replace_substring(s, "~", "~0");\r
12098             replace_substring(s, "/", "~1");\r
12099             return s;\r
12100         }\r
12101 \r
12102         /// unescape tilde and slash\r
12103         static void unescape(std::string& s)\r
12104         {\r
12105             // first transform any occurrence of the sequence '~1' to '/'\r
12106             replace_substring(s, "~1", "/");\r
12107             // then transform any occurrence of the sequence '~0' to '~'\r
12108             replace_substring(s, "~0", "~");\r
12109         }\r
12110 \r
12111         /*!\r
12112         @param[in] reference_string  the reference string to the current value\r
12113         @param[in] value             the value to consider\r
12114         @param[in,out] result        the result object to insert values to\r
12115 \r
12116         @note Empty objects or arrays are flattened to `null`.\r
12117         */\r
12118         static void flatten(const std::string& reference_string,\r
12119                             const basic_json& value,\r
12120                             basic_json& result)\r
12121         {\r
12122             switch (value.m_type)\r
12123             {\r
12124                 case value_t::array:\r
12125                 {\r
12126                     if (value.m_value.array->empty())\r
12127                     {\r
12128                         // flatten empty array as null\r
12129                         result[reference_string] = nullptr;\r
12130                     }\r
12131                     else\r
12132                     {\r
12133                         // iterate array and use index as reference string\r
12134                         for (size_t i = 0; i < value.m_value.array->size(); ++i)\r
12135                         {\r
12136                             flatten(reference_string + "/" + std::to_string(i),\r
12137                                     value.m_value.array->operator[](i), result);\r
12138                         }\r
12139                     }\r
12140                     break;\r
12141                 }\r
12142 \r
12143                 case value_t::object:\r
12144                 {\r
12145                     if (value.m_value.object->empty())\r
12146                     {\r
12147                         // flatten empty object as null\r
12148                         result[reference_string] = nullptr;\r
12149                     }\r
12150                     else\r
12151                     {\r
12152                         // iterate object and use keys as reference string\r
12153                         for (const auto& element : *value.m_value.object)\r
12154                         {\r
12155                             flatten(reference_string + "/" + escape(element.first),\r
12156                                     element.second, result);\r
12157                         }\r
12158                     }\r
12159                     break;\r
12160                 }\r
12161 \r
12162                 default:\r
12163                 {\r
12164                     // add primitive value with its reference string\r
12165                     result[reference_string] = value;\r
12166                     break;\r
12167                 }\r
12168             }\r
12169         }\r
12170 \r
12171         /*!\r
12172         @param[in] value  flattened JSON\r
12173 \r
12174         @return unflattened JSON\r
12175         */\r
12176         static basic_json unflatten(const basic_json& value)\r
12177         {\r
12178             if (not value.is_object())\r
12179             {\r
12180                 JSON_THROW(std::domain_error("only objects can be unflattened"));\r
12181             }\r
12182 \r
12183             basic_json result;\r
12184 \r
12185             // iterate the JSON object values\r
12186             for (const auto& element : *value.m_value.object)\r
12187             {\r
12188                 if (not element.second.is_primitive())\r
12189                 {\r
12190                     JSON_THROW(std::domain_error("values in object must be primitive"));\r
12191                 }\r
12192 \r
12193                 // assign value to reference pointed to by JSON pointer; Note\r
12194                 // that if the JSON pointer is "" (i.e., points to the whole\r
12195                 // value), function get_and_create returns a reference to\r
12196                 // result itself. An assignment will then create a primitive\r
12197                 // value.\r
12198                 json_pointer(element.first).get_and_create(result) = element.second;\r
12199             }\r
12200 \r
12201             return result;\r
12202         }\r
12203 \r
12204       private:\r
12205         friend bool operator==(json_pointer const& lhs,\r
12206                                json_pointer const& rhs) noexcept\r
12207         {\r
12208             return lhs.reference_tokens == rhs.reference_tokens;\r
12209         }\r
12210 \r
12211         friend bool operator!=(json_pointer const& lhs,\r
12212                                json_pointer const& rhs) noexcept\r
12213         {\r
12214             return !(lhs == rhs);\r
12215         }\r
12216 \r
12217         /// the reference tokens\r
12218         std::vector<std::string> reference_tokens {};\r
12219     };\r
12220 \r
12221     //////////////////////////\r
12222     // JSON Pointer support //\r
12223     //////////////////////////\r
12224 \r
12225     /// @name JSON Pointer functions\r
12226     /// @{\r
12227 \r
12228     /*!\r
12229     @brief access specified element via JSON Pointer\r
12230 \r
12231     Uses a JSON pointer to retrieve a reference to the respective JSON value.\r
12232     No bound checking is performed. Similar to @ref operator[](const typename\r
12233     object_t::key_type&), `null` values are created in arrays and objects if\r
12234     necessary.\r
12235 \r
12236     In particular:\r
12237     - If the JSON pointer points to an object key that does not exist, it\r
12238       is created an filled with a `null` value before a reference to it\r
12239       is returned.\r
12240     - If the JSON pointer points to an array index that does not exist, it\r
12241       is created an filled with a `null` value before a reference to it\r
12242       is returned. All indices between the current maximum and the given\r
12243       index are also filled with `null`.\r
12244     - The special value `-` is treated as a synonym for the index past the\r
12245       end.\r
12246 \r
12247     @param[in] ptr  a JSON pointer\r
12248 \r
12249     @return reference to the element pointed to by @a ptr\r
12250 \r
12251     @complexity Constant.\r
12252 \r
12253     @throw std::out_of_range      if the JSON pointer can not be resolved\r
12254     @throw std::domain_error      if an array index begins with '0'\r
12255     @throw std::invalid_argument  if an array index was not a number\r
12256 \r
12257     @liveexample{The behavior is shown in the example.,operatorjson_pointer}\r
12258 \r
12259     @since version 2.0.0\r
12260     */\r
12261     reference operator[](const json_pointer& ptr)\r
12262     {\r
12263         return ptr.get_unchecked(this);\r
12264     }\r
12265 \r
12266     /*!\r
12267     @brief access specified element via JSON Pointer\r
12268 \r
12269     Uses a JSON pointer to retrieve a reference to the respective JSON value.\r
12270     No bound checking is performed. The function does not change the JSON\r
12271     value; no `null` values are created. In particular, the the special value\r
12272     `-` yields an exception.\r
12273 \r
12274     @param[in] ptr  JSON pointer to the desired element\r
12275 \r
12276     @return const reference to the element pointed to by @a ptr\r
12277 \r
12278     @complexity Constant.\r
12279 \r
12280     @throw std::out_of_range      if the JSON pointer can not be resolved\r
12281     @throw std::domain_error      if an array index begins with '0'\r
12282     @throw std::invalid_argument  if an array index was not a number\r
12283 \r
12284     @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}\r
12285 \r
12286     @since version 2.0.0\r
12287     */\r
12288     const_reference operator[](const json_pointer& ptr) const\r
12289     {\r
12290         return ptr.get_unchecked(this);\r
12291     }\r
12292 \r
12293     /*!\r
12294     @brief access specified element via JSON Pointer\r
12295 \r
12296     Returns a reference to the element at with specified JSON pointer @a ptr,\r
12297     with bounds checking.\r
12298 \r
12299     @param[in] ptr  JSON pointer to the desired element\r
12300 \r
12301     @return reference to the element pointed to by @a ptr\r
12302 \r
12303     @complexity Constant.\r
12304 \r
12305     @throw std::out_of_range      if the JSON pointer can not be resolved\r
12306     @throw std::domain_error      if an array index begins with '0'\r
12307     @throw std::invalid_argument  if an array index was not a number\r
12308 \r
12309     @liveexample{The behavior is shown in the example.,at_json_pointer}\r
12310 \r
12311     @since version 2.0.0\r
12312     */\r
12313     reference at(const json_pointer& ptr)\r
12314     {\r
12315         return ptr.get_checked(this);\r
12316     }\r
12317 \r
12318     /*!\r
12319     @brief access specified element via JSON Pointer\r
12320 \r
12321     Returns a const reference to the element at with specified JSON pointer @a\r
12322     ptr, with bounds checking.\r
12323 \r
12324     @param[in] ptr  JSON pointer to the desired element\r
12325 \r
12326     @return reference to the element pointed to by @a ptr\r
12327 \r
12328     @complexity Constant.\r
12329 \r
12330     @throw std::out_of_range      if the JSON pointer can not be resolved\r
12331     @throw std::domain_error      if an array index begins with '0'\r
12332     @throw std::invalid_argument  if an array index was not a number\r
12333 \r
12334     @liveexample{The behavior is shown in the example.,at_json_pointer_const}\r
12335 \r
12336     @since version 2.0.0\r
12337     */\r
12338     const_reference at(const json_pointer& ptr) const\r
12339     {\r
12340         return ptr.get_checked(this);\r
12341     }\r
12342 \r
12343     /*!\r
12344     @brief return flattened JSON value\r
12345 \r
12346     The function creates a JSON object whose keys are JSON pointers (see [RFC\r
12347     6901](https://tools.ietf.org/html/rfc6901)) and whose values are all\r
12348     primitive. The original JSON value can be restored using the @ref\r
12349     unflatten() function.\r
12350 \r
12351     @return an object that maps JSON pointers to primitive values\r
12352 \r
12353     @note Empty objects and arrays are flattened to `null` and will not be\r
12354           reconstructed correctly by the @ref unflatten() function.\r
12355 \r
12356     @complexity Linear in the size the JSON value.\r
12357 \r
12358     @liveexample{The following code shows how a JSON object is flattened to an\r
12359     object whose keys consist of JSON pointers.,flatten}\r
12360 \r
12361     @sa @ref unflatten() for the reverse function\r
12362 \r
12363     @since version 2.0.0\r
12364     */\r
12365     basic_json flatten() const\r
12366     {\r
12367         basic_json result(value_t::object);\r
12368         json_pointer::flatten("", *this, result);\r
12369         return result;\r
12370     }\r
12371 \r
12372     /*!\r
12373     @brief unflatten a previously flattened JSON value\r
12374 \r
12375     The function restores the arbitrary nesting of a JSON value that has been\r
12376     flattened before using the @ref flatten() function. The JSON value must\r
12377     meet certain constraints:\r
12378     1. The value must be an object.\r
12379     2. The keys must be JSON pointers (see\r
12380        [RFC 6901](https://tools.ietf.org/html/rfc6901))\r
12381     3. The mapped values must be primitive JSON types.\r
12382 \r
12383     @return the original JSON from a flattened version\r
12384 \r
12385     @note Empty objects and arrays are flattened by @ref flatten() to `null`\r
12386           values and can not unflattened to their original type. Apart from\r
12387           this example, for a JSON value `j`, the following is always true:\r
12388           `j == j.flatten().unflatten()`.\r
12389 \r
12390     @complexity Linear in the size the JSON value.\r
12391 \r
12392     @liveexample{The following code shows how a flattened JSON object is\r
12393     unflattened into the original nested JSON object.,unflatten}\r
12394 \r
12395     @sa @ref flatten() for the reverse function\r
12396 \r
12397     @since version 2.0.0\r
12398     */\r
12399     basic_json unflatten() const\r
12400     {\r
12401         return json_pointer::unflatten(*this);\r
12402     }\r
12403 \r
12404     /// @}\r
12405 \r
12406     //////////////////////////\r
12407     // JSON Patch functions //\r
12408     //////////////////////////\r
12409 \r
12410     /// @name JSON Patch functions\r
12411     /// @{\r
12412 \r
12413     /*!\r
12414     @brief applies a JSON patch\r
12415 \r
12416     [JSON Patch](http://jsonpatch.com) defines a JSON document structure for\r
12417     expressing a sequence of operations to apply to a JSON) document. With\r
12418     this function, a JSON Patch is applied to the current JSON value by\r
12419     executing all operations from the patch.\r
12420 \r
12421     @param[in] json_patch  JSON patch document\r
12422     @return patched document\r
12423 \r
12424     @note The application of a patch is atomic: Either all operations succeed\r
12425           and the patched document is returned or an exception is thrown. In\r
12426           any case, the original value is not changed: the patch is applied\r
12427           to a copy of the value.\r
12428 \r
12429     @throw std::out_of_range if a JSON pointer inside the patch could not\r
12430     be resolved successfully in the current JSON value; example: `"key baz\r
12431     not found"`\r
12432     @throw invalid_argument if the JSON patch is malformed (e.g., mandatory\r
12433     attributes are missing); example: `"operation add must have member path"`\r
12434 \r
12435     @complexity Linear in the size of the JSON value and the length of the\r
12436     JSON patch. As usually only a fraction of the JSON value is affected by\r
12437     the patch, the complexity can usually be neglected.\r
12438 \r
12439     @liveexample{The following code shows how a JSON patch is applied to a\r
12440     value.,patch}\r
12441 \r
12442     @sa @ref diff -- create a JSON patch by comparing two JSON values\r
12443 \r
12444     @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\r
12445     @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)\r
12446 \r
12447     @since version 2.0.0\r
12448     */\r
12449     basic_json patch(const basic_json& json_patch) const\r
12450     {\r
12451         // make a working copy to apply the patch to\r
12452         basic_json result = *this;\r
12453 \r
12454         // the valid JSON Patch operations\r
12455         enum class patch_operations {add, remove, replace, move, copy, test, invalid};\r
12456 \r
12457         const auto get_op = [](const std::string op)\r
12458         {\r
12459             if (op == "add")\r
12460             {\r
12461                 return patch_operations::add;\r
12462             }\r
12463             if (op == "remove")\r
12464             {\r
12465                 return patch_operations::remove;\r
12466             }\r
12467             if (op == "replace")\r
12468             {\r
12469                 return patch_operations::replace;\r
12470             }\r
12471             if (op == "move")\r
12472             {\r
12473                 return patch_operations::move;\r
12474             }\r
12475             if (op == "copy")\r
12476             {\r
12477                 return patch_operations::copy;\r
12478             }\r
12479             if (op == "test")\r
12480             {\r
12481                 return patch_operations::test;\r
12482             }\r
12483 \r
12484             return patch_operations::invalid;\r
12485         };\r
12486 \r
12487         // wrapper for "add" operation; add value at ptr\r
12488         const auto operation_add = [&result](json_pointer & ptr, basic_json val)\r
12489         {\r
12490             // adding to the root of the target document means replacing it\r
12491             if (ptr.is_root())\r
12492             {\r
12493                 result = val;\r
12494             }\r
12495             else\r
12496             {\r
12497                 // make sure the top element of the pointer exists\r
12498                 json_pointer top_pointer = ptr.top();\r
12499                 if (top_pointer != ptr)\r
12500                 {\r
12501                     result.at(top_pointer);\r
12502                 }\r
12503 \r
12504                 // get reference to parent of JSON pointer ptr\r
12505                 const auto last_path = ptr.pop_back();\r
12506                 basic_json& parent = result[ptr];\r
12507 \r
12508                 switch (parent.m_type)\r
12509                 {\r
12510                     case value_t::null:\r
12511                     case value_t::object:\r
12512                     {\r
12513                         // use operator[] to add value\r
12514                         parent[last_path] = val;\r
12515                         break;\r
12516                     }\r
12517 \r
12518                     case value_t::array:\r
12519                     {\r
12520                         if (last_path == "-")\r
12521                         {\r
12522                             // special case: append to back\r
12523                             parent.push_back(val);\r
12524                         }\r
12525                         else\r
12526                         {\r
12527                             const auto idx = std::stoi(last_path);\r
12528                             if (static_cast<size_type>(idx) > parent.size())\r
12529                             {\r
12530                                 // avoid undefined behavior\r
12531                                 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));\r
12532                             }\r
12533                             else\r
12534                             {\r
12535                                 // default case: insert add offset\r
12536                                 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);\r
12537                             }\r
12538                         }\r
12539                         break;\r
12540                     }\r
12541 \r
12542                     default:\r
12543                     {\r
12544                         // if there exists a parent it cannot be primitive\r
12545                         assert(false);  // LCOV_EXCL_LINE\r
12546                     }\r
12547                 }\r
12548             }\r
12549         };\r
12550 \r
12551         // wrapper for "remove" operation; remove value at ptr\r
12552         const auto operation_remove = [&result](json_pointer & ptr)\r
12553         {\r
12554             // get reference to parent of JSON pointer ptr\r
12555             const auto last_path = ptr.pop_back();\r
12556             basic_json& parent = result.at(ptr);\r
12557 \r
12558             // remove child\r
12559             if (parent.is_object())\r
12560             {\r
12561                 // perform range check\r
12562                 auto it = parent.find(last_path);\r
12563                 if (it != parent.end())\r
12564                 {\r
12565                     parent.erase(it);\r
12566                 }\r
12567                 else\r
12568                 {\r
12569                     JSON_THROW(std::out_of_range("key '" + last_path + "' not found"));\r
12570                 }\r
12571             }\r
12572             else if (parent.is_array())\r
12573             {\r
12574                 // note erase performs range check\r
12575                 parent.erase(static_cast<size_type>(std::stoi(last_path)));\r
12576             }\r
12577         };\r
12578 \r
12579         // type check\r
12580         if (not json_patch.is_array())\r
12581         {\r
12582             // a JSON patch must be an array of objects\r
12583             JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));\r
12584         }\r
12585 \r
12586         // iterate and apply the operations\r
12587         for (const auto& val : json_patch)\r
12588         {\r
12589             // wrapper to get a value for an operation\r
12590             const auto get_value = [&val](const std::string & op,\r
12591                                           const std::string & member,\r
12592                                           bool string_type) -> basic_json&\r
12593             {\r
12594                 // find value\r
12595                 auto it = val.m_value.object->find(member);\r
12596 \r
12597                 // context-sensitive error message\r
12598                 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";\r
12599 \r
12600                 // check if desired value is present\r
12601                 if (it == val.m_value.object->end())\r
12602                 {\r
12603                     JSON_THROW(std::invalid_argument(error_msg + " must have member '" + member + "'"));\r
12604                 }\r
12605 \r
12606                 // check if result is of type string\r
12607                 if (string_type and not it->second.is_string())\r
12608                 {\r
12609                     JSON_THROW(std::invalid_argument(error_msg + " must have string member '" + member + "'"));\r
12610                 }\r
12611 \r
12612                 // no error: return value\r
12613                 return it->second;\r
12614             };\r
12615 \r
12616             // type check\r
12617             if (not val.is_object())\r
12618             {\r
12619                 JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));\r
12620             }\r
12621 \r
12622             // collect mandatory members\r
12623             const std::string op = get_value("op", "op", true);\r
12624             const std::string path = get_value(op, "path", true);\r
12625             json_pointer ptr(path);\r
12626 \r
12627             switch (get_op(op))\r
12628             {\r
12629                 case patch_operations::add:\r
12630                 {\r
12631                     operation_add(ptr, get_value("add", "value", false));\r
12632                     break;\r
12633                 }\r
12634 \r
12635                 case patch_operations::remove:\r
12636                 {\r
12637                     operation_remove(ptr);\r
12638                     break;\r
12639                 }\r
12640 \r
12641                 case patch_operations::replace:\r
12642                 {\r
12643                     // the "path" location must exist - use at()\r
12644                     result.at(ptr) = get_value("replace", "value", false);\r
12645                     break;\r
12646                 }\r
12647 \r
12648                 case patch_operations::move:\r
12649                 {\r
12650                     const std::string from_path = get_value("move", "from", true);\r
12651                     json_pointer from_ptr(from_path);\r
12652 \r
12653                     // the "from" location must exist - use at()\r
12654                     basic_json v = result.at(from_ptr);\r
12655 \r
12656                     // The move operation is functionally identical to a\r
12657                     // "remove" operation on the "from" location, followed\r
12658                     // immediately by an "add" operation at the target\r
12659                     // location with the value that was just removed.\r
12660                     operation_remove(from_ptr);\r
12661                     operation_add(ptr, v);\r
12662                     break;\r
12663                 }\r
12664 \r
12665                 case patch_operations::copy:\r
12666                 {\r
12667                     const std::string from_path = get_value("copy", "from", true);;\r
12668                     const json_pointer from_ptr(from_path);\r
12669 \r
12670                     // the "from" location must exist - use at()\r
12671                     result[ptr] = result.at(from_ptr);\r
12672                     break;\r
12673                 }\r
12674 \r
12675                 case patch_operations::test:\r
12676                 {\r
12677                     bool success = false;\r
12678                     JSON_TRY\r
12679                     {\r
12680                         // check if "value" matches the one at "path"\r
12681                         // the "path" location must exist - use at()\r
12682                         success = (result.at(ptr) == get_value("test", "value", false));\r
12683                     }\r
12684                     JSON_CATCH (std::out_of_range&)\r
12685                     {\r
12686                         // ignore out of range errors: success remains false\r
12687                     }\r
12688 \r
12689                     // throw an exception if test fails\r
12690                     if (not success)\r
12691                     {\r
12692                         JSON_THROW(std::domain_error("unsuccessful: " + val.dump()));\r
12693                     }\r
12694 \r
12695                     break;\r
12696                 }\r
12697 \r
12698                 case patch_operations::invalid:\r
12699                 {\r
12700                     // op must be "add", "remove", "replace", "move", "copy", or\r
12701                     // "test"\r
12702                     JSON_THROW(std::invalid_argument("operation value '" + op + "' is invalid"));\r
12703                 }\r
12704             }\r
12705         }\r
12706 \r
12707         return result;\r
12708     }\r
12709 \r
12710     /*!\r
12711     @brief creates a diff as a JSON patch\r
12712 \r
12713     Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can\r
12714     be changed into the value @a target by calling @ref patch function.\r
12715 \r
12716     @invariant For two JSON values @a source and @a target, the following code\r
12717     yields always `true`:\r
12718     @code {.cpp}\r
12719     source.patch(diff(source, target)) == target;\r
12720     @endcode\r
12721 \r
12722     @note Currently, only `remove`, `add`, and `replace` operations are\r
12723           generated.\r
12724 \r
12725     @param[in] source  JSON value to compare from\r
12726     @param[in] target  JSON value to compare against\r
12727     @param[in] path    helper value to create JSON pointers\r
12728 \r
12729     @return a JSON patch to convert the @a source to @a target\r
12730 \r
12731     @complexity Linear in the lengths of @a source and @a target.\r
12732 \r
12733     @liveexample{The following code shows how a JSON patch is created as a\r
12734     diff for two JSON values.,diff}\r
12735 \r
12736     @sa @ref patch -- apply a JSON patch\r
12737 \r
12738     @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\r
12739 \r
12740     @since version 2.0.0\r
12741     */\r
12742     static basic_json diff(const basic_json& source,\r
12743                            const basic_json& target,\r
12744                            const std::string& path = "")\r
12745     {\r
12746         // the patch\r
12747         basic_json result(value_t::array);\r
12748 \r
12749         // if the values are the same, return empty patch\r
12750         if (source == target)\r
12751         {\r
12752             return result;\r
12753         }\r
12754 \r
12755         if (source.type() != target.type())\r
12756         {\r
12757             // different types: replace value\r
12758             result.push_back(\r
12759             {\r
12760                 {"op", "replace"},\r
12761                 {"path", path},\r
12762                 {"value", target}\r
12763             });\r
12764         }\r
12765         else\r
12766         {\r
12767             switch (source.type())\r
12768             {\r
12769                 case value_t::array:\r
12770                 {\r
12771                     // first pass: traverse common elements\r
12772                     size_t i = 0;\r
12773                     while (i < source.size() and i < target.size())\r
12774                     {\r
12775                         // recursive call to compare array values at index i\r
12776                         auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));\r
12777                         result.insert(result.end(), temp_diff.begin(), temp_diff.end());\r
12778                         ++i;\r
12779                     }\r
12780 \r
12781                     // i now reached the end of at least one array\r
12782                     // in a second pass, traverse the remaining elements\r
12783 \r
12784                     // remove my remaining elements\r
12785                     const auto end_index = static_cast<difference_type>(result.size());\r
12786                     while (i < source.size())\r
12787                     {\r
12788                         // add operations in reverse order to avoid invalid\r
12789                         // indices\r
12790                         result.insert(result.begin() + end_index, object(\r
12791                         {\r
12792                             {"op", "remove"},\r
12793                             {"path", path + "/" + std::to_string(i)}\r
12794                         }));\r
12795                         ++i;\r
12796                     }\r
12797 \r
12798                     // add other remaining elements\r
12799                     while (i < target.size())\r
12800                     {\r
12801                         result.push_back(\r
12802                         {\r
12803                             {"op", "add"},\r
12804                             {"path", path + "/" + std::to_string(i)},\r
12805                             {"value", target[i]}\r
12806                         });\r
12807                         ++i;\r
12808                     }\r
12809 \r
12810                     break;\r
12811                 }\r
12812 \r
12813                 case value_t::object:\r
12814                 {\r
12815                     // first pass: traverse this object's elements\r
12816                     for (auto it = source.begin(); it != source.end(); ++it)\r
12817                     {\r
12818                         // escape the key name to be used in a JSON patch\r
12819                         const auto key = json_pointer::escape(it.key());\r
12820 \r
12821                         if (target.find(it.key()) != target.end())\r
12822                         {\r
12823                             // recursive call to compare object values at key it\r
12824                             auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);\r
12825                             result.insert(result.end(), temp_diff.begin(), temp_diff.end());\r
12826                         }\r
12827                         else\r
12828                         {\r
12829                             // found a key that is not in o -> remove it\r
12830                             result.push_back(object(\r
12831                             {\r
12832                                 {"op", "remove"},\r
12833                                 {"path", path + "/" + key}\r
12834                             }));\r
12835                         }\r
12836                     }\r
12837 \r
12838                     // second pass: traverse other object's elements\r
12839                     for (auto it = target.begin(); it != target.end(); ++it)\r
12840                     {\r
12841                         if (source.find(it.key()) == source.end())\r
12842                         {\r
12843                             // found a key that is not in this -> add it\r
12844                             const auto key = json_pointer::escape(it.key());\r
12845                             result.push_back(\r
12846                             {\r
12847                                 {"op", "add"},\r
12848                                 {"path", path + "/" + key},\r
12849                                 {"value", it.value()}\r
12850                             });\r
12851                         }\r
12852                     }\r
12853 \r
12854                     break;\r
12855                 }\r
12856 \r
12857                 default:\r
12858                 {\r
12859                     // both primitive type: replace value\r
12860                     result.push_back(\r
12861                     {\r
12862                         {"op", "replace"},\r
12863                         {"path", path},\r
12864                         {"value", target}\r
12865                     });\r
12866                     break;\r
12867                 }\r
12868             }\r
12869         }\r
12870 \r
12871         return result;\r
12872     }\r
12873 \r
12874     /// @}\r
12875 };\r
12876 \r
12877 /////////////\r
12878 // presets //\r
12879 /////////////\r
12880 \r
12881 /*!\r
12882 @brief default JSON class\r
12883 \r
12884 This type is the default specialization of the @ref basic_json class which\r
12885 uses the standard template types.\r
12886 \r
12887 @since version 1.0.0\r
12888 */\r
12889 using json = basic_json<>;\r
12890 } // namespace nlohmann\r
12891 \r
12892 \r
12893 ///////////////////////\r
12894 // nonmember support //\r
12895 ///////////////////////\r
12896 \r
12897 // specialization of std::swap, and std::hash\r
12898 namespace std\r
12899 {\r
12900 /*!\r
12901 @brief exchanges the values of two JSON objects\r
12902 \r
12903 @since version 1.0.0\r
12904 */\r
12905 template<>\r
12906 inline void swap(nlohmann::json& j1,\r
12907                  nlohmann::json& j2) noexcept(\r
12908                      is_nothrow_move_constructible<nlohmann::json>::value and\r
12909                      is_nothrow_move_assignable<nlohmann::json>::value\r
12910                  )\r
12911 {\r
12912     j1.swap(j2);\r
12913 }\r
12914 \r
12915 /// hash value for JSON objects\r
12916 template<>\r
12917 struct hash<nlohmann::json>\r
12918 {\r
12919     /*!\r
12920     @brief return a hash value for a JSON object\r
12921 \r
12922     @since version 1.0.0\r
12923     */\r
12924     std::size_t operator()(const nlohmann::json& j) const\r
12925     {\r
12926         // a naive hashing via the string representation\r
12927         const auto& h = hash<nlohmann::json::string_t>();\r
12928         return h(j.dump());\r
12929     }\r
12930 };\r
12931 } // namespace std\r
12932 \r
12933 /*!\r
12934 @brief user-defined string literal for JSON values\r
12935 \r
12936 This operator implements a user-defined string literal for JSON objects. It\r
12937 can be used by adding `"_json"` to a string literal and returns a JSON object\r
12938 if no parse error occurred.\r
12939 \r
12940 @param[in] s  a string representation of a JSON object\r
12941 @param[in] n  the length of string @a s\r
12942 @return a JSON object\r
12943 \r
12944 @since version 1.0.0\r
12945 */\r
12946 inline nlohmann::json operator "" _json(const char* s, std::size_t n)\r
12947 {\r
12948     return nlohmann::json::parse(s, s + n);\r
12949 }\r
12950 \r
12951 /*!\r
12952 @brief user-defined string literal for JSON pointer\r
12953 \r
12954 This operator implements a user-defined string literal for JSON Pointers. It\r
12955 can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer\r
12956 object if no parse error occurred.\r
12957 \r
12958 @param[in] s  a string representation of a JSON Pointer\r
12959 @param[in] n  the length of string @a s\r
12960 @return a JSON pointer object\r
12961 \r
12962 @since version 2.0.0\r
12963 */\r
12964 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)\r
12965 {\r
12966     return nlohmann::json::json_pointer(std::string(s, n));\r
12967 }\r
12968 \r
12969 // clean up\r
12970 #undef JSON_CATCH\r
12971 #undef JSON_DEPRECATED\r
12972 #undef JSON_THROW\r
12973 #undef JSON_TRY\r
12974 \r
12975 #endif\r