JSON for Modern C++ 2.1.1
Loading...
Searching...
No Matches
json.hpp
1/*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 2.1.1
5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files (the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions:
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27*/
28
29#ifndef NLOHMANN_JSON_HPP
30#define NLOHMANN_JSON_HPP
31
32#include <algorithm> // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform
33#include <array> // array
34#include <cassert> // assert
35#include <cctype> // isdigit
36#include <ciso646> // and, not, or
37#include <cmath> // isfinite, labs, ldexp, signbit
38#include <cstddef> // nullptr_t, ptrdiff_t, size_t
39#include <cstdint> // int64_t, uint64_t
40#include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
41#include <cstring> // strlen
42#include <forward_list> // forward_list
43#include <functional> // function, hash, less
44#include <initializer_list> // initializer_list
45#include <iomanip> // setw
46#include <iostream> // istream, ostream
47#include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
48#include <limits> // numeric_limits
49#include <locale> // locale
50#include <map> // map
51#include <memory> // addressof, allocator, allocator_traits, unique_ptr
52#include <numeric> // accumulate
53#include <sstream> // stringstream
54#include <stdexcept> // domain_error, invalid_argument, out_of_range
55#include <string> // getline, stoi, string, to_string
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
57#include <utility> // declval, forward, make_pair, move, pair, swap
58#include <vector> // vector
59
60// exclude unsupported compilers
61#if defined(__clang__)
62 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
63 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
64 #endif
65#elif defined(__GNUC__)
66 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
67 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
68 #endif
69#endif
70
71// disable float-equal warnings on GCC/clang
72#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
73 #pragma GCC diagnostic push
74 #pragma GCC diagnostic ignored "-Wfloat-equal"
75#endif
76
77// disable documentation warnings on clang
78#if defined(__clang__)
79 #pragma GCC diagnostic push
80 #pragma GCC diagnostic ignored "-Wdocumentation"
81#endif
82
83// allow for portable deprecation warnings
84#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
85 #define JSON_DEPRECATED __attribute__((deprecated))
86#elif defined(_MSC_VER)
87 #define JSON_DEPRECATED __declspec(deprecated)
88#else
89 #define JSON_DEPRECATED
90#endif
91
92// allow to disable exceptions
93#if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS)
94 #define JSON_THROW(exception) throw exception
95 #define JSON_TRY try
96 #define JSON_CATCH(exception) catch(exception)
97#else
98 #define JSON_THROW(exception) std::abort()
99 #define JSON_TRY if(true)
100 #define JSON_CATCH(exception) if(false)
101#endif
102
108namespace nlohmann
109{
110
119namespace detail
120{
122// JSON type enumeration //
124
149enum class value_t : uint8_t
150{
151 null,
152 object,
153 array,
154 string,
155 boolean,
156 number_integer,
157 number_unsigned,
158 number_float,
159 discarded
160};
161
171inline bool operator<(const value_t lhs, const value_t rhs) noexcept
172{
173 static constexpr std::array<uint8_t, 8> order = {{
174 0, // null
175 3, // object
176 4, // array
177 5, // string
178 1, // boolean
179 2, // integer
180 2, // unsigned
181 2, // float
182 }
183 };
184
185 // discarded values are not comparable
186 if (lhs == value_t::discarded or rhs == value_t::discarded)
187 {
188 return false;
189 }
190
191 return order[static_cast<std::size_t>(lhs)] <
192 order[static_cast<std::size_t>(rhs)];
193}
194
195
197// helpers //
199
200// alias templates to reduce boilerplate
201template<bool B, typename T = void>
202using enable_if_t = typename std::enable_if<B, T>::type;
203
204template<typename T>
205using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
206
207// taken from http://stackoverflow.com/a/26936864/266378
208template<typename T>
209using is_unscoped_enum =
210 std::integral_constant<bool, std::is_convertible<T, int>::value and
211 std::is_enum<T>::value>;
212
213/*
214Implementation of two C++17 constructs: conjunction, negation. This is needed
215to avoid evaluating all the traits in a condition
216
217For example: not std::is_same<void, T>::value and has_value_type<T>::value
218will not compile when T = void (on MSVC at least). Whereas
219conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
220stop evaluating if negation<...>::value == false
221
222Please note that those constructs must be used with caution, since symbols can
223become very long quickly (which can slow down compilation and cause MSVC
224internal compiler errors). Only use it when you have to (see example ahead).
225*/
226template<class...> struct conjunction : std::true_type {};
227template<class B1> struct conjunction<B1> : B1 {};
228template<class B1, class... Bn>
229struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
230
231template<class B> struct negation : std::integral_constant < bool, !B::value > {};
232
233// dispatch utility (taken from ranges-v3)
234template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
235template<> struct priority_tag<0> {};
236
237
239// constructors //
241
242template<value_t> struct external_constructor;
243
244template<>
245struct external_constructor<value_t::boolean>
246{
247 template<typename BasicJsonType>
248 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
249 {
250 j.m_type = value_t::boolean;
251 j.m_value = b;
252 j.assert_invariant();
253 }
254};
255
256template<>
257struct external_constructor<value_t::string>
258{
259 template<typename BasicJsonType>
260 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
261 {
262 j.m_type = value_t::string;
263 j.m_value = s;
264 j.assert_invariant();
265 }
266};
267
268template<>
269struct external_constructor<value_t::number_float>
270{
271 template<typename BasicJsonType>
272 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
273 {
274 // replace infinity and NAN by null
275 if (not std::isfinite(val))
276 {
277 j = BasicJsonType{};
278 }
279 else
280 {
281 j.m_type = value_t::number_float;
282 j.m_value = val;
283 }
284 j.assert_invariant();
285 }
286};
287
288template<>
289struct external_constructor<value_t::number_unsigned>
290{
291 template<typename BasicJsonType>
292 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
293 {
294 j.m_type = value_t::number_unsigned;
295 j.m_value = val;
296 j.assert_invariant();
297 }
298};
299
300template<>
301struct external_constructor<value_t::number_integer>
302{
303 template<typename BasicJsonType>
304 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
305 {
306 j.m_type = value_t::number_integer;
307 j.m_value = val;
308 j.assert_invariant();
309 }
310};
311
312template<>
313struct external_constructor<value_t::array>
314{
315 template<typename BasicJsonType>
316 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
317 {
318 j.m_type = value_t::array;
319 j.m_value = arr;
320 j.assert_invariant();
321 }
322
323 template<typename BasicJsonType, typename CompatibleArrayType,
324 enable_if_t<not std::is_same<CompatibleArrayType,
325 typename BasicJsonType::array_t>::value,
326 int> = 0>
327 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
328 {
329 using std::begin;
330 using std::end;
331 j.m_type = value_t::array;
332 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
333 j.assert_invariant();
334 }
335};
336
337template<>
338struct external_constructor<value_t::object>
339{
340 template<typename BasicJsonType>
341 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
342 {
343 j.m_type = value_t::object;
344 j.m_value = obj;
345 j.assert_invariant();
346 }
347
348 template<typename BasicJsonType, typename CompatibleObjectType,
349 enable_if_t<not std::is_same<CompatibleObjectType,
350 typename BasicJsonType::object_t>::value,
351 int> = 0>
352 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
353 {
354 using std::begin;
355 using std::end;
356
357 j.m_type = value_t::object;
358 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
359 j.assert_invariant();
360 }
361};
362
363
365// has_/is_ functions //
367
378#define NLOHMANN_JSON_HAS_HELPER(type) \
379 template<typename T> struct has_##type { \
380 private: \
381 template<typename U, typename = typename U::type> \
382 static int detect(U &&); \
383 static void detect(...); \
384 public: \
385 static constexpr bool value = \
386 std::is_integral<decltype(detect(std::declval<T>()))>::value; \
387 }
388
389NLOHMANN_JSON_HAS_HELPER(mapped_type);
390NLOHMANN_JSON_HAS_HELPER(key_type);
391NLOHMANN_JSON_HAS_HELPER(value_type);
392NLOHMANN_JSON_HAS_HELPER(iterator);
393
394#undef NLOHMANN_JSON_HAS_HELPER
395
396
397template<bool B, class RealType, class CompatibleObjectType>
398struct is_compatible_object_type_impl : std::false_type {};
399
400template<class RealType, class CompatibleObjectType>
401struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
402{
403 static constexpr auto value =
404 std::is_constructible<typename RealType::key_type,
405 typename CompatibleObjectType::key_type>::value and
406 std::is_constructible<typename RealType::mapped_type,
407 typename CompatibleObjectType::mapped_type>::value;
408};
409
410template<class BasicJsonType, class CompatibleObjectType>
411struct is_compatible_object_type
412{
413 static auto constexpr value = is_compatible_object_type_impl <
414 conjunction<negation<std::is_same<void, CompatibleObjectType>>,
415 has_mapped_type<CompatibleObjectType>,
416 has_key_type<CompatibleObjectType>>::value,
417 typename BasicJsonType::object_t, CompatibleObjectType >::value;
418};
419
420template<typename BasicJsonType, typename T>
421struct is_basic_json_nested_type
422{
423 static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
424 std::is_same<T, typename BasicJsonType::const_iterator>::value or
425 std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
426 std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value or
427 std::is_same<T, typename BasicJsonType::json_pointer>::value;
428};
429
430template<class BasicJsonType, class CompatibleArrayType>
431struct is_compatible_array_type
432{
433 static auto constexpr value =
434 conjunction<negation<std::is_same<void, CompatibleArrayType>>,
435 negation<is_compatible_object_type<
436 BasicJsonType, CompatibleArrayType>>,
437 negation<std::is_constructible<typename BasicJsonType::string_t,
438 CompatibleArrayType>>,
439 negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,
440 has_value_type<CompatibleArrayType>,
441 has_iterator<CompatibleArrayType>>::value;
442};
443
444template<bool, typename, typename>
445struct is_compatible_integer_type_impl : std::false_type {};
446
447template<typename RealIntegerType, typename CompatibleNumberIntegerType>
448struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
449{
450 // is there an assert somewhere on overflows?
451 using RealLimits = std::numeric_limits<RealIntegerType>;
452 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
453
454 static constexpr auto value =
455 std::is_constructible<RealIntegerType,
456 CompatibleNumberIntegerType>::value and
457 CompatibleLimits::is_integer and
458 RealLimits::is_signed == CompatibleLimits::is_signed;
459};
460
461template<typename RealIntegerType, typename CompatibleNumberIntegerType>
462struct is_compatible_integer_type
463{
464 static constexpr auto value =
465 is_compatible_integer_type_impl <
466 std::is_integral<CompatibleNumberIntegerType>::value and
467 not std::is_same<bool, CompatibleNumberIntegerType>::value,
468 RealIntegerType, CompatibleNumberIntegerType > ::value;
469};
470
471
472// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
473template<typename BasicJsonType, typename T>
474struct has_from_json
475{
476 private:
477 // also check the return type of from_json
478 template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
479 std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
480 static int detect(U&&);
481 static void detect(...);
482
483 public:
484 static constexpr bool value = std::is_integral<decltype(
485 detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
486};
487
488// This trait checks if JSONSerializer<T>::from_json(json const&) exists
489// this overload is used for non-default-constructible user-defined-types
490template<typename BasicJsonType, typename T>
491struct has_non_default_from_json
492{
493 private:
494 template <
495 typename U,
496 typename = enable_if_t<std::is_same<
497 T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
498 static int detect(U&&);
499 static void detect(...);
500
501 public:
502 static constexpr bool value = std::is_integral<decltype(detect(
503 std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
504};
505
506// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
507template<typename BasicJsonType, typename T>
508struct has_to_json
509{
510 private:
511 template<typename U, typename = decltype(uncvref_t<U>::to_json(
512 std::declval<BasicJsonType&>(), std::declval<T>()))>
513 static int detect(U&&);
514 static void detect(...);
515
516 public:
517 static constexpr bool value = std::is_integral<decltype(detect(
518 std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
519};
520
521
523// to_json //
525
526template<typename BasicJsonType, typename T, enable_if_t<
527 std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
528void to_json(BasicJsonType& j, T b) noexcept
529{
530 external_constructor<value_t::boolean>::construct(j, b);
531}
532
533template<typename BasicJsonType, typename CompatibleString,
534 enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
535 CompatibleString>::value, int> = 0>
536void to_json(BasicJsonType& j, const CompatibleString& s)
537{
538 external_constructor<value_t::string>::construct(j, s);
539}
540
541template<typename BasicJsonType, typename FloatType,
542 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
543void to_json(BasicJsonType& j, FloatType val) noexcept
544{
545 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
546}
547
548template <
549 typename BasicJsonType, typename CompatibleNumberUnsignedType,
550 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,
551 CompatibleNumberUnsignedType>::value, int> = 0 >
552void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
553{
554 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
555}
556
557template <
558 typename BasicJsonType, typename CompatibleNumberIntegerType,
559 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t,
560 CompatibleNumberIntegerType>::value, int> = 0 >
561void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
562{
563 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
564}
565
566template<typename BasicJsonType, typename UnscopedEnumType,
567 enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
568void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept
569{
570 external_constructor<value_t::number_integer>::construct(j, e);
571}
572
573template <
574 typename BasicJsonType, typename CompatibleArrayType,
575 enable_if_t <
576 is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
577 std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
578 int > = 0 >
579void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
580{
581 external_constructor<value_t::array>::construct(j, arr);
582}
583
584template <
585 typename BasicJsonType, typename CompatibleObjectType,
586 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
587 int> = 0 >
588void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
589{
590 external_constructor<value_t::object>::construct(j, arr);
591}
592
593
595// from_json //
597
598// overloads for basic_json template parameters
599template<typename BasicJsonType, typename ArithmeticType,
600 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
601 not std::is_same<ArithmeticType,
602 typename BasicJsonType::boolean_t>::value,
603 int> = 0>
604void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
605{
606 switch (static_cast<value_t>(j))
607 {
608 case value_t::number_unsigned:
609 {
610 val = static_cast<ArithmeticType>(
611 *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
612 break;
613 }
614 case value_t::number_integer:
615 {
616 val = static_cast<ArithmeticType>(
617 *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
618 break;
619 }
620 case value_t::number_float:
621 {
622 val = static_cast<ArithmeticType>(
623 *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
624 break;
625 }
626 default:
627 {
628 JSON_THROW(
629 std::domain_error("type must be number, but is " + j.type_name()));
630 }
631 }
632}
633
634template<typename BasicJsonType>
635void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
636{
637 if (not j.is_boolean())
638 {
639 JSON_THROW(std::domain_error("type must be boolean, but is " + j.type_name()));
640 }
641 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
642}
643
644template<typename BasicJsonType>
645void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
646{
647 if (not j.is_string())
648 {
649 JSON_THROW(std::domain_error("type must be string, but is " + j.type_name()));
650 }
651 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
652}
653
654template<typename BasicJsonType>
655void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
656{
657 get_arithmetic_value(j, val);
658}
659
660template<typename BasicJsonType>
661void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
662{
663 get_arithmetic_value(j, val);
664}
665
666template<typename BasicJsonType>
667void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
668{
669 get_arithmetic_value(j, val);
670}
671
672template<typename BasicJsonType, typename UnscopedEnumType,
673 enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
674void from_json(const BasicJsonType& j, UnscopedEnumType& e)
675{
676 typename std::underlying_type<UnscopedEnumType>::type val;
677 get_arithmetic_value(j, val);
678 e = static_cast<UnscopedEnumType>(val);
679}
680
681template<typename BasicJsonType>
682void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
683{
684 if (not j.is_array())
685 {
686 JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
687 }
688 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
689}
690
691// forward_list doesn't have an insert method
692template<typename BasicJsonType, typename T, typename Allocator>
693void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
694{
695 // do not perform the check when user wants to retrieve jsons
696 // (except when it's null.. ?)
697 if (j.is_null())
698 {
699 JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
700 }
701 if (not std::is_same<T, BasicJsonType>::value)
702 {
703 if (not j.is_array())
704 {
705 JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
706 }
707 }
708 for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)
709 {
710 l.push_front(it->template get<T>());
711 }
712}
713
714template<typename BasicJsonType, typename CompatibleArrayType>
715void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)
716{
717 using std::begin;
718 using std::end;
719
720 std::transform(j.begin(), j.end(),
721 std::inserter(arr, end(arr)), [](const BasicJsonType & i)
722 {
723 // get<BasicJsonType>() returns *this, this won't call a from_json
724 // method when value_type is BasicJsonType
725 return i.template get<typename CompatibleArrayType::value_type>();
726 });
727}
728
729template<typename BasicJsonType, typename CompatibleArrayType>
730auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)
731-> decltype(
732 arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
733 void())
734{
735 using std::begin;
736 using std::end;
737
738 arr.reserve(j.size());
739 std::transform(
740 j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i)
741 {
742 // get<BasicJsonType>() returns *this, this won't call a from_json
743 // method when value_type is BasicJsonType
744 return i.template get<typename CompatibleArrayType::value_type>();
745 });
746}
747
748template<typename BasicJsonType, typename CompatibleArrayType,
749 enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
750 not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
751void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
752{
753 if (j.is_null())
754 {
755 JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
756 }
757
758 // when T == BasicJsonType, do not check if value_t is correct
759 if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
760 {
761 if (not j.is_array())
762 {
763 JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
764 }
765 }
766 from_json_array_impl(j, arr, priority_tag<1> {});
767}
768
769template<typename BasicJsonType, typename CompatibleObjectType,
770 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
771void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
772{
773 if (not j.is_object())
774 {
775 JSON_THROW(std::domain_error("type must be object, but is " + j.type_name()));
776 }
777
778 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
779 using std::begin;
780 using std::end;
781 // we could avoid the assignment, but this might require a for loop, which
782 // might be less efficient than the container constructor for some
783 // containers (would it?)
784 obj = CompatibleObjectType(begin(*inner_object), end(*inner_object));
785}
786
787// overload for arithmetic types, not chosen for basic_json template arguments
788// (BooleanType, etc..); note: Is it really necessary to provide explicit
789// overloads for boolean_t etc. in case of a custom BooleanType which is not
790// an arithmetic type?
791template<typename BasicJsonType, typename ArithmeticType,
792 enable_if_t <
793 std::is_arithmetic<ArithmeticType>::value and
794 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
795 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
796 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
797 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
798 int> = 0>
799void from_json(const BasicJsonType& j, ArithmeticType& val)
800{
801 switch (static_cast<value_t>(j))
802 {
803 case value_t::number_unsigned:
804 {
805 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
806 break;
807 }
808 case value_t::number_integer:
809 {
810 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
811 break;
812 }
813 case value_t::number_float:
814 {
815 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
816 break;
817 }
818 case value_t::boolean:
819 {
820 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
821 break;
822 }
823 default:
824 {
825 JSON_THROW(std::domain_error("type must be number, but is " + j.type_name()));
826 }
827 }
828}
829
830struct to_json_fn
831{
832 private:
833 template<typename BasicJsonType, typename T>
834 auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
835 -> decltype(to_json(j, std::forward<T>(val)), void())
836 {
837 return to_json(j, std::forward<T>(val));
838 }
839
840 template<typename BasicJsonType, typename T>
841 void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept
842 {
843 static_assert(sizeof(BasicJsonType) == 0,
844 "could not find to_json() method in T's namespace");
845 }
846
847 public:
848 template<typename BasicJsonType, typename T>
849 void operator()(BasicJsonType& j, T&& val) const
850 noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
851 {
852 return call(j, std::forward<T>(val), priority_tag<1> {});
853 }
854};
855
856struct from_json_fn
857{
858 private:
859 template<typename BasicJsonType, typename T>
860 auto call(const BasicJsonType& j, T& val, priority_tag<1>) const
861 noexcept(noexcept(from_json(j, val)))
862 -> decltype(from_json(j, val), void())
863 {
864 return from_json(j, val);
865 }
866
867 template<typename BasicJsonType, typename T>
868 void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept
869 {
870 static_assert(sizeof(BasicJsonType) == 0,
871 "could not find from_json() method in T's namespace");
872 }
873
874 public:
875 template<typename BasicJsonType, typename T>
876 void operator()(const BasicJsonType& j, T& val) const
877 noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
878 {
879 return call(j, val, priority_tag<1> {});
880 }
881};
882
883// taken from ranges-v3
884template<typename T>
885struct static_const
886{
887 static constexpr T value{};
888};
889
890template<typename T>
891constexpr T static_const<T>::value;
892} // namespace detail
893
894
896namespace
897{
898constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
899constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
900}
901
902
910template<typename = void, typename = void>
912{
922 template<typename BasicJsonType, typename ValueType>
923 static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
924 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
925 {
926 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
927 }
928
938 template<typename BasicJsonType, typename ValueType>
939 static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
940 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
941 {
942 ::nlohmann::to_json(j, std::forward<ValueType>(val));
943 }
944};
945
946
1028template <
1029 template<typename U, typename V, typename... Args> class ObjectType = std::map,
1030 template<typename U, typename... Args> class ArrayType = std::vector,
1031 class StringType = std::string,
1032 class BooleanType = bool,
1033 class NumberIntegerType = std::int64_t,
1034 class NumberUnsignedType = std::uint64_t,
1035 class NumberFloatType = double,
1036 template<typename U> class AllocatorType = std::allocator,
1037 template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer
1038 >
1040{
1041 private:
1042 template<detail::value_t> friend struct detail::external_constructor;
1047
1048 public:
1049 using value_t = detail::value_t;
1050 // forward declarations
1051 template<typename U> class iter_impl;
1052 template<typename Base> class json_reverse_iterator;
1053 class json_pointer;
1054 template<typename T, typename SFINAE>
1056
1058 // container types //
1060
1065
1068
1073
1075 using difference_type = std::ptrdiff_t;
1077 using size_type = std::size_t;
1078
1081
1083 using pointer = typename std::allocator_traits<allocator_type>::pointer;
1085 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
1086
1095
1097
1098
1103 {
1104 return allocator_type();
1105 }
1106
1131 {
1133
1134 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
1135 result["name"] = "JSON for Modern C++";
1136 result["url"] = "https://github.com/nlohmann/json";
1137 result["version"] =
1138 {
1139 {"string", "2.1.1"},
1140 {"major", 2},
1141 {"minor", 1},
1142 {"patch", 1}
1143 };
1144
1145#ifdef _WIN32
1146 result["platform"] = "win32";
1147#elif defined __linux__
1148 result["platform"] = "linux";
1149#elif defined __APPLE__
1150 result["platform"] = "apple";
1151#elif defined __unix__
1152 result["platform"] = "unix";
1153#else
1154 result["platform"] = "unknown";
1155#endif
1156
1157#if defined(__clang__)
1158 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
1159#elif defined(__ICC) || defined(__INTEL_COMPILER)
1160 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
1161#elif defined(__GNUC__) || defined(__GNUG__)
1162 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
1163#elif defined(__HP_cc) || defined(__HP_aCC)
1164 result["compiler"] = "hp"
1165#elif defined(__IBMCPP__)
1166 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
1167#elif defined(_MSC_VER)
1168 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
1169#elif defined(__PGI)
1170 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
1171#elif defined(__SUNPRO_CC)
1172 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
1173#else
1174 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
1175#endif
1176
1177#ifdef __cplusplus
1178 result["compiler"]["c++"] = std::to_string(__cplusplus);
1179#else
1180 result["compiler"]["c++"] = "unknown";
1181#endif
1182 return result;
1183 }
1184
1185
1187 // JSON value data types //
1189
1194
1279 basic_json,
1280 std::less<StringType>,
1281 AllocatorType<std::pair<const StringType,
1282 basic_json>>>;
1283
1329
1382
1408
1480
1551
1619
1621
1622 private:
1623
1625 template<typename T, typename... Args>
1626 static T* create(Args&& ... args)
1627 {
1629 auto deleter = [&](T * object)
1630 {
1631 alloc.deallocate(object, 1);
1632 };
1633 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
1634 alloc.construct(object.get(), std::forward<Args>(args)...);
1635 assert(object != nullptr);
1636 return object.release();
1637 }
1638
1640 // JSON value storage //
1642
1667 union json_value
1668 {
1670 object_t* object;
1672 array_t* array;
1674 string_t* string;
1676 boolean_t boolean;
1678 number_integer_t number_integer;
1680 number_unsigned_t number_unsigned;
1682 number_float_t number_float;
1683
1685 json_value() = default;
1687 json_value(boolean_t v) noexcept : boolean(v) {}
1689 json_value(number_integer_t v) noexcept : number_integer(v) {}
1691 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
1693 json_value(number_float_t v) noexcept : number_float(v) {}
1695 json_value(value_t t)
1696 {
1697 switch (t)
1698 {
1699 case value_t::object:
1700 {
1701 object = create<object_t>();
1702 break;
1703 }
1704
1705 case value_t::array:
1706 {
1707 array = create<array_t>();
1708 break;
1709 }
1710
1711 case value_t::string:
1712 {
1713 string = create<string_t>("");
1714 break;
1715 }
1716
1717 case value_t::boolean:
1718 {
1719 boolean = boolean_t(false);
1720 break;
1721 }
1722
1723 case value_t::number_integer:
1724 {
1725 number_integer = number_integer_t(0);
1726 break;
1727 }
1728
1729 case value_t::number_unsigned:
1730 {
1731 number_unsigned = number_unsigned_t(0);
1732 break;
1733 }
1734
1735 case value_t::number_float:
1736 {
1737 number_float = number_float_t(0.0);
1738 break;
1739 }
1740
1741 case value_t::null:
1742 {
1743 break;
1744 }
1745
1746 default:
1747 {
1748 if (t == value_t::null)
1749 {
1750 JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE
1751 }
1752 break;
1753 }
1754 }
1755 }
1756
1758 json_value(const string_t& value)
1759 {
1760 string = create<string_t>(value);
1761 }
1762
1764 json_value(const object_t& value)
1765 {
1766 object = create<object_t>(value);
1767 }
1768
1770 json_value(const array_t& value)
1771 {
1772 array = create<array_t>(value);
1773 }
1774 };
1775
1785 void assert_invariant() const
1786 {
1787 assert(m_type != value_t::object or m_value.object != nullptr);
1788 assert(m_type != value_t::array or m_value.array != nullptr);
1789 assert(m_type != value_t::string or m_value.string != nullptr);
1790 }
1791
1792 public:
1794 // JSON parser callback //
1796
1808 {
1812 object_end,
1816 array_end,
1818 key,
1820 value
1821 };
1822
1875 using parser_callback_t = std::function<bool(int depth,
1877 basic_json& parsed)>;
1878
1879
1881 // constructors //
1883
1888
1916 basic_json(const value_t value_type)
1917 : m_type(value_type), m_value(value_type)
1918 {
1919 assert_invariant();
1920 }
1921
1940 basic_json(std::nullptr_t = nullptr) noexcept
1941 : basic_json(value_t::null)
1942 {
1943 assert_invariant();
1944 }
1945
1999 template<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
2000 detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
2001 not std::is_same<U, basic_json_t>::value and
2002 not detail::is_basic_json_nested_type<
2003 basic_json_t, U>::value and
2004 detail::has_to_json<basic_json, U>::value,
2005 int> = 0>
2006 basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(
2007 std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
2008 {
2009 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
2010 assert_invariant();
2011 }
2012
2082 basic_json(std::initializer_list<basic_json> init,
2083 bool type_deduction = true,
2084 value_t manual_type = value_t::array)
2085 {
2086 // check if each element is an array with two elements whose first
2087 // element is a string
2088 bool is_an_object = std::all_of(init.begin(), init.end(),
2089 [](const basic_json & element)
2090 {
2091 return element.is_array() and element.size() == 2 and element[0].is_string();
2092 });
2093
2094 // adjust type if type deduction is not wanted
2095 if (not type_deduction)
2096 {
2097 // if array is wanted, do not create an object though possible
2098 if (manual_type == value_t::array)
2099 {
2100 is_an_object = false;
2101 }
2102
2103 // if object is wanted but impossible, throw an exception
2104 if (manual_type == value_t::object and not is_an_object)
2105 {
2106 JSON_THROW(std::domain_error("cannot create object from initializer list"));
2107 }
2108 }
2109
2110 if (is_an_object)
2111 {
2112 // the initializer list is a list of pairs -> create object
2113 m_type = value_t::object;
2114 m_value = value_t::object;
2115
2116 std::for_each(init.begin(), init.end(), [this](const basic_json & element)
2117 {
2118 m_value.object->emplace(*(element[0].m_value.string), element[1]);
2119 });
2120 }
2121 else
2122 {
2123 // the initializer list describes an array -> create array
2124 m_type = value_t::array;
2125 m_value.array = create<array_t>(init);
2126 }
2127
2128 assert_invariant();
2129 }
2130
2165 static basic_json array(std::initializer_list<basic_json> init =
2166 std::initializer_list<basic_json>())
2167 {
2168 return basic_json(init, false, value_t::array);
2169 }
2170
2205 static basic_json object(std::initializer_list<basic_json> init =
2206 std::initializer_list<basic_json>())
2207 {
2208 return basic_json(init, false, value_t::object);
2209 }
2210
2230 : m_type(value_t::array)
2231 {
2232 m_value.array = create<array_t>(cnt, val);
2233 assert_invariant();
2234 }
2235
2273 template<class InputIT, typename std::enable_if<
2274 std::is_same<InputIT, typename basic_json_t::iterator>::value or
2275 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
2277 {
2278 assert(first.m_object != nullptr);
2279 assert(last.m_object != nullptr);
2280
2281 // make sure iterator fits the current value
2282 if (first.m_object != last.m_object)
2283 {
2284 JSON_THROW(std::domain_error("iterators are not compatible"));
2285 }
2286
2287 // copy type from first iterator
2288 m_type = first.m_object->m_type;
2289
2290 // check if iterator range is complete for primitive values
2291 switch (m_type)
2292 {
2293 case value_t::boolean:
2294 case value_t::number_float:
2295 case value_t::number_integer:
2296 case value_t::number_unsigned:
2297 case value_t::string:
2298 {
2299 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
2300 {
2301 JSON_THROW(std::out_of_range("iterators out of range"));
2302 }
2303 break;
2304 }
2305
2306 default:
2307 {
2308 break;
2309 }
2310 }
2311
2312 switch (m_type)
2313 {
2314 case value_t::number_integer:
2315 {
2316 m_value.number_integer = first.m_object->m_value.number_integer;
2317 break;
2318 }
2319
2320 case value_t::number_unsigned:
2321 {
2322 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2323 break;
2324 }
2325
2326 case value_t::number_float:
2327 {
2328 m_value.number_float = first.m_object->m_value.number_float;
2329 break;
2330 }
2331
2332 case value_t::boolean:
2333 {
2334 m_value.boolean = first.m_object->m_value.boolean;
2335 break;
2336 }
2337
2338 case value_t::string:
2339 {
2340 m_value = *first.m_object->m_value.string;
2341 break;
2342 }
2343
2344 case value_t::object:
2345 {
2346 m_value.object = create<object_t>(first.m_it.object_iterator,
2347 last.m_it.object_iterator);
2348 break;
2349 }
2350
2351 case value_t::array:
2352 {
2353 m_value.array = create<array_t>(first.m_it.array_iterator,
2354 last.m_it.array_iterator);
2355 break;
2356 }
2357
2358 default:
2359 {
2360 JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()));
2361 }
2362 }
2363
2364 assert_invariant();
2365 }
2366
2395 JSON_DEPRECATED
2396 explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
2397 {
2398 *this = parser(i, cb).parse();
2399 assert_invariant();
2400 }
2401
2403 // other constructors and destructor //
2405
2429 : m_type(other.m_type)
2430 {
2431 // check of passed value is valid
2432 other.assert_invariant();
2433
2434 switch (m_type)
2435 {
2436 case value_t::object:
2437 {
2438 m_value = *other.m_value.object;
2439 break;
2440 }
2441
2442 case value_t::array:
2443 {
2444 m_value = *other.m_value.array;
2445 break;
2446 }
2447
2448 case value_t::string:
2449 {
2450 m_value = *other.m_value.string;
2451 break;
2452 }
2453
2454 case value_t::boolean:
2455 {
2456 m_value = other.m_value.boolean;
2457 break;
2458 }
2459
2460 case value_t::number_integer:
2461 {
2462 m_value = other.m_value.number_integer;
2463 break;
2464 }
2465
2466 case value_t::number_unsigned:
2467 {
2468 m_value = other.m_value.number_unsigned;
2469 break;
2470 }
2471
2472 case value_t::number_float:
2473 {
2474 m_value = other.m_value.number_float;
2475 break;
2476 }
2477
2478 default:
2479 {
2480 break;
2481 }
2482 }
2483
2484 assert_invariant();
2485 }
2486
2506 : m_type(std::move(other.m_type)),
2507 m_value(std::move(other.m_value))
2508 {
2509 // check that passed value is valid
2510 other.assert_invariant();
2511
2512 // invalidate payload
2513 other.m_type = value_t::null;
2514 other.m_value = {};
2515
2516 assert_invariant();
2517 }
2518
2543 std::is_nothrow_move_constructible<value_t>::value and
2544 std::is_nothrow_move_assignable<value_t>::value and
2545 std::is_nothrow_move_constructible<json_value>::value and
2546 std::is_nothrow_move_assignable<json_value>::value
2547 )
2548 {
2549 // check that passed value is valid
2550 other.assert_invariant();
2551
2552 using std::swap;
2553 swap(m_type, other.m_type);
2554 swap(m_value, other.m_value);
2555
2556 assert_invariant();
2557 return *this;
2558 }
2559
2576 {
2577 assert_invariant();
2578
2579 switch (m_type)
2580 {
2581 case value_t::object:
2582 {
2584 alloc.destroy(m_value.object);
2585 alloc.deallocate(m_value.object, 1);
2586 break;
2587 }
2588
2589 case value_t::array:
2590 {
2592 alloc.destroy(m_value.array);
2593 alloc.deallocate(m_value.array, 1);
2594 break;
2595 }
2596
2597 case value_t::string:
2598 {
2600 alloc.destroy(m_value.string);
2601 alloc.deallocate(m_value.string, 1);
2602 break;
2603 }
2604
2605 default:
2606 {
2607 // all other types need no specific destructor
2608 break;
2609 }
2610 }
2611 }
2612
2614
2615 public:
2617 // object inspection //
2619
2623
2647 string_t dump(const int indent = -1) const
2648 {
2649 std::stringstream ss;
2650
2651 if (indent >= 0)
2652 {
2653 dump(ss, true, static_cast<unsigned int>(indent));
2654 }
2655 else
2656 {
2657 dump(ss, false, 0);
2658 }
2659
2660 return ss.str();
2661 }
2662
2681 constexpr value_t type() const noexcept
2682 {
2683 return m_type;
2684 }
2685
2711 constexpr bool is_primitive() const noexcept
2712 {
2713 return is_null() or is_string() or is_boolean() or is_number();
2714 }
2715
2739 {
2740 return is_array() or is_object();
2741 }
2742
2760 constexpr bool is_null() const noexcept
2761 {
2762 return m_type == value_t::null;
2763 }
2764
2782 constexpr bool is_boolean() const noexcept
2783 {
2784 return m_type == value_t::boolean;
2785 }
2786
2812 constexpr bool is_number() const noexcept
2813 {
2815 }
2816
2842 {
2843 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2844 }
2845
2870 {
2871 return m_type == value_t::number_unsigned;
2872 }
2873
2898 {
2899 return m_type == value_t::number_float;
2900 }
2901
2919 constexpr bool is_object() const noexcept
2920 {
2921 return m_type == value_t::object;
2922 }
2923
2941 constexpr bool is_array() const noexcept
2942 {
2943 return m_type == value_t::array;
2944 }
2945
2963 constexpr bool is_string() const noexcept
2964 {
2965 return m_type == value_t::string;
2966 }
2967
2990 constexpr bool is_discarded() const noexcept
2991 {
2992 return m_type == value_t::discarded;
2993 }
2994
3013 constexpr operator value_t() const noexcept
3014 {
3015 return m_type;
3016 }
3017
3019
3020 private:
3022 // value access //
3024
3026 boolean_t get_impl(boolean_t* /*unused*/) const
3027 {
3028 if (is_boolean())
3029 {
3030 return m_value.boolean;
3031 }
3032
3033 JSON_THROW(std::domain_error("type must be boolean, but is " + type_name()));
3034 }
3035
3037 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
3038 {
3039 return is_object() ? m_value.object : nullptr;
3040 }
3041
3043 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
3044 {
3045 return is_object() ? m_value.object : nullptr;
3046 }
3047
3049 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
3050 {
3051 return is_array() ? m_value.array : nullptr;
3052 }
3053
3055 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
3056 {
3057 return is_array() ? m_value.array : nullptr;
3058 }
3059
3061 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
3062 {
3063 return is_string() ? m_value.string : nullptr;
3064 }
3065
3067 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
3068 {
3069 return is_string() ? m_value.string : nullptr;
3070 }
3071
3073 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
3074 {
3075 return is_boolean() ? &m_value.boolean : nullptr;
3076 }
3077
3079 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
3080 {
3081 return is_boolean() ? &m_value.boolean : nullptr;
3082 }
3083
3085 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
3086 {
3087 return is_number_integer() ? &m_value.number_integer : nullptr;
3088 }
3089
3091 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
3092 {
3093 return is_number_integer() ? &m_value.number_integer : nullptr;
3094 }
3095
3097 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
3098 {
3099 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3100 }
3101
3103 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
3104 {
3105 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3106 }
3107
3109 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
3110 {
3111 return is_number_float() ? &m_value.number_float : nullptr;
3112 }
3113
3115 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
3116 {
3117 return is_number_float() ? &m_value.number_float : nullptr;
3118 }
3119
3131 template<typename ReferenceType, typename ThisType>
3132 static ReferenceType get_ref_impl(ThisType& obj)
3133 {
3134 // helper type
3135 using PointerType = typename std::add_pointer<ReferenceType>::type;
3136
3137 // delegate the call to get_ptr<>()
3138 auto ptr = obj.template get_ptr<PointerType>();
3139
3140 if (ptr != nullptr)
3141 {
3142 return *ptr;
3143 }
3144
3145 JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
3146 obj.type_name()));
3147 }
3148
3149 public:
3153
3168 template <
3169 typename BasicJsonType,
3170 detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,
3171 basic_json_t>::value,
3172 int> = 0 >
3174 {
3175 return *this;
3176 }
3177
3217 template <
3218 typename ValueTypeCV,
3219 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3220 detail::enable_if_t <
3221 not std::is_same<basic_json_t, ValueType>::value and
3222 detail::has_from_json<basic_json_t, ValueType>::value and
3223 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
3224 int > = 0 >
3227 {
3228 // we cannot static_assert on ValueTypeCV being non-const, because
3229 // there is support for get<const basic_json_t>(), which is why we
3230 // still need the uncvref
3231 static_assert(not std::is_reference<ValueTypeCV>::value,
3232 "get() cannot be used with reference types, you might want to use get_ref()");
3233 static_assert(std::is_default_constructible<ValueType>::value,
3234 "types must be DefaultConstructible when used with get()");
3235
3236 ValueType ret;
3237 JSONSerializer<ValueType>::from_json(*this, ret);
3238 return ret;
3239 }
3240
3272 template <
3273 typename ValueTypeCV,
3274 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3275 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
3276 detail::has_non_default_from_json<basic_json_t,
3277 ValueType>::value, int> = 0 >
3280 {
3281 static_assert(not std::is_reference<ValueTypeCV>::value,
3282 "get() cannot be used with reference types, you might want to use get_ref()");
3283 return JSONSerializer<ValueTypeCV>::from_json(*this);
3284 }
3285
3313 template<typename PointerType, typename std::enable_if<
3314 std::is_pointer<PointerType>::value, int>::type = 0>
3316 {
3317 // delegate the call to get_ptr
3318 return get_ptr<PointerType>();
3319 }
3320
3325 template<typename PointerType, typename std::enable_if<
3326 std::is_pointer<PointerType>::value, int>::type = 0>
3327 constexpr const PointerType get() const noexcept
3328 {
3329 // delegate the call to get_ptr
3330 return get_ptr<PointerType>();
3331 }
3332
3359 template<typename PointerType, typename std::enable_if<
3360 std::is_pointer<PointerType>::value, int>::type = 0>
3362 {
3363 // get the type of the PointerType (remove pointer and const)
3364 using pointee_t = typename std::remove_const<typename
3365 std::remove_pointer<typename
3366 std::remove_const<PointerType>::type>::type>::type;
3367 // make sure the type matches the allowed types
3368 static_assert(
3369 std::is_same<object_t, pointee_t>::value
3370 or std::is_same<array_t, pointee_t>::value
3371 or std::is_same<string_t, pointee_t>::value
3372 or std::is_same<boolean_t, pointee_t>::value
3373 or std::is_same<number_integer_t, pointee_t>::value
3374 or std::is_same<number_unsigned_t, pointee_t>::value
3375 or std::is_same<number_float_t, pointee_t>::value
3376 , "incompatible pointer type");
3377
3378 // delegate the call to get_impl_ptr<>()
3379 return get_impl_ptr(static_cast<PointerType>(nullptr));
3380 }
3381
3386 template<typename PointerType, typename std::enable_if<
3387 std::is_pointer<PointerType>::value and
3388 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3390 {
3391 // get the type of the PointerType (remove pointer and const)
3392 using pointee_t = typename std::remove_const<typename
3393 std::remove_pointer<typename
3394 std::remove_const<PointerType>::type>::type>::type;
3395 // make sure the type matches the allowed types
3396 static_assert(
3397 std::is_same<object_t, pointee_t>::value
3398 or std::is_same<array_t, pointee_t>::value
3399 or std::is_same<string_t, pointee_t>::value
3400 or std::is_same<boolean_t, pointee_t>::value
3401 or std::is_same<number_integer_t, pointee_t>::value
3402 or std::is_same<number_unsigned_t, pointee_t>::value
3403 or std::is_same<number_float_t, pointee_t>::value
3404 , "incompatible pointer type");
3405
3406 // delegate the call to get_impl_ptr<>() const
3407 return get_impl_ptr(static_cast<const PointerType>(nullptr));
3408 }
3409
3436 template<typename ReferenceType, typename std::enable_if<
3437 std::is_reference<ReferenceType>::value, int>::type = 0>
3439 {
3440 // delegate call to get_ref_impl
3441 return get_ref_impl<ReferenceType>(*this);
3442 }
3443
3448 template<typename ReferenceType, typename std::enable_if<
3449 std::is_reference<ReferenceType>::value and
3450 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3452 {
3453 // delegate call to get_ref_impl
3454 return get_ref_impl<ReferenceType>(*this);
3455 }
3456
3485 template < typename ValueType, typename std::enable_if <
3486 not std::is_pointer<ValueType>::value and
3487 not std::is_same<ValueType, typename string_t::value_type>::value
3488#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
3489 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3490#endif
3491 , int >::type = 0 >
3492 operator ValueType() const
3493 {
3494 // delegate the call to get<>() const
3495 return get<ValueType>();
3496 }
3497
3499
3500
3502 // element access //
3504
3508
3532 {
3533 // at only works for arrays
3534 if (is_array())
3535 {
3536 JSON_TRY
3537 {
3538 return m_value.array->at(idx);
3539 }
3540 JSON_CATCH (std::out_of_range&)
3541 {
3542 // create better exception explanation
3543 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
3544 }
3545 }
3546 else
3547 {
3548 JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3549 }
3550 }
3551
3575 {
3576 // at only works for arrays
3577 if (is_array())
3578 {
3579 JSON_TRY
3580 {
3581 return m_value.array->at(idx);
3582 }
3583 JSON_CATCH (std::out_of_range&)
3584 {
3585 // create better exception explanation
3586 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
3587 }
3588 }
3589 else
3590 {
3591 JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3592 }
3593 }
3594
3621 reference at(const typename object_t::key_type& key)
3622 {
3623 // at only works for objects
3624 if (is_object())
3625 {
3626 JSON_TRY
3627 {
3628 return m_value.object->at(key);
3629 }
3630 JSON_CATCH (std::out_of_range&)
3631 {
3632 // create better exception explanation
3633 JSON_THROW(std::out_of_range("key '" + key + "' not found"));
3634 }
3635 }
3636 else
3637 {
3638 JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3639 }
3640 }
3641
3668 const_reference at(const typename object_t::key_type& key) const
3669 {
3670 // at only works for objects
3671 if (is_object())
3672 {
3673 JSON_TRY
3674 {
3675 return m_value.object->at(key);
3676 }
3677 JSON_CATCH (std::out_of_range&)
3678 {
3679 // create better exception explanation
3680 JSON_THROW(std::out_of_range("key '" + key + "' not found"));
3681 }
3682 }
3683 else
3684 {
3685 JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3686 }
3687 }
3688
3715 {
3716 // implicitly convert null value to an empty array
3717 if (is_null())
3718 {
3719 m_type = value_t::array;
3720 m_value.array = create<array_t>();
3721 assert_invariant();
3722 }
3723
3724 // operator[] only works for arrays
3725 if (is_array())
3726 {
3727 // fill up array with null values if given idx is outside range
3728 if (idx >= m_value.array->size())
3729 {
3730 m_value.array->insert(m_value.array->end(),
3731 idx - m_value.array->size() + 1,
3732 basic_json());
3733 }
3734
3735 return m_value.array->operator[](idx);
3736 }
3737
3738 JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3739 }
3740
3761 {
3762 // const operator[] only works for arrays
3763 if (is_array())
3764 {
3765 return m_value.array->operator[](idx);
3766 }
3767
3768 JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3769 }
3770
3798 reference operator[](const typename object_t::key_type& key)
3799 {
3800 // implicitly convert null value to an empty object
3801 if (is_null())
3802 {
3803 m_type = value_t::object;
3804 m_value.object = create<object_t>();
3805 assert_invariant();
3806 }
3807
3808 // operator[] only works for objects
3809 if (is_object())
3810 {
3811 return m_value.object->operator[](key);
3812 }
3813
3814 JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3815 }
3816
3847 const_reference operator[](const typename object_t::key_type& key) const
3848 {
3849 // const operator[] only works for objects
3850 if (is_object())
3851 {
3852 assert(m_value.object->find(key) != m_value.object->end());
3853 return m_value.object->find(key)->second;
3854 }
3855
3856 JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3857 }
3858
3886 template<typename T, std::size_t n>
3888 {
3889 return operator[](static_cast<const T>(key));
3890 }
3891
3921 template<typename T, std::size_t n>
3923 {
3924 return operator[](static_cast<const T>(key));
3925 }
3926
3954 template<typename T>
3956 {
3957 // implicitly convert null to object
3958 if (is_null())
3959 {
3960 m_type = value_t::object;
3961 m_value = value_t::object;
3962 assert_invariant();
3963 }
3964
3965 // at only works for objects
3966 if (is_object())
3967 {
3968 return m_value.object->operator[](key);
3969 }
3970
3971 JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3972 }
3973
4004 template<typename T>
4006 {
4007 // at only works for objects
4008 if (is_object())
4009 {
4010 assert(m_value.object->find(key) != m_value.object->end());
4011 return m_value.object->find(key)->second;
4012 }
4013
4014 JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
4015 }
4016
4065 template<class ValueType, typename std::enable_if<
4066 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4067 ValueType value(const typename object_t::key_type& key, ValueType default_value) const
4068 {
4069 // at only works for objects
4070 if (is_object())
4071 {
4072 // if key is found, return value and given default value otherwise
4073 const auto it = find(key);
4074 if (it != end())
4075 {
4076 return *it;
4077 }
4078
4079 return default_value;
4080 }
4081 else
4082 {
4083 JSON_THROW(std::domain_error("cannot use value() with " + type_name()));
4084 }
4085 }
4086
4091 string_t value(const typename object_t::key_type& key, const char* default_value) const
4092 {
4093 return value(key, string_t(default_value));
4094 }
4095
4137 template<class ValueType, typename std::enable_if<
4138 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4140 {
4141 // at only works for objects
4142 if (is_object())
4143 {
4144 // if pointer resolves a value, return it or use default value
4145 JSON_TRY
4146 {
4147 return ptr.get_checked(this);
4148 }
4149 JSON_CATCH (std::out_of_range&)
4150 {
4151 return default_value;
4152 }
4153 }
4154
4155 JSON_THROW(std::domain_error("cannot use value() with " + type_name()));
4156 }
4157
4162 string_t value(const json_pointer& ptr, const char* default_value) const
4163 {
4164 return value(ptr, string_t(default_value));
4165 }
4166
4193 {
4194 return *begin();
4195 }
4196
4201 {
4202 return *cbegin();
4203 }
4204
4236 {
4237 auto tmp = end();
4238 --tmp;
4239 return *tmp;
4240 }
4241
4246 {
4247 auto tmp = cend();
4248 --tmp;
4249 return *tmp;
4250 }
4251
4297 template<class IteratorType, typename std::enable_if<
4298 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4299 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4300 = 0>
4302 {
4303 // make sure iterator fits the current value
4304 if (this != pos.m_object)
4305 {
4306 JSON_THROW(std::domain_error("iterator does not fit current value"));
4307 }
4308
4310
4311 switch (m_type)
4312 {
4313 case value_t::boolean:
4314 case value_t::number_float:
4315 case value_t::number_integer:
4316 case value_t::number_unsigned:
4317 case value_t::string:
4318 {
4319 if (not pos.m_it.primitive_iterator.is_begin())
4320 {
4321 JSON_THROW(std::out_of_range("iterator out of range"));
4322 }
4323
4324 if (is_string())
4325 {
4327 alloc.destroy(m_value.string);
4328 alloc.deallocate(m_value.string, 1);
4329 m_value.string = nullptr;
4330 }
4331
4332 m_type = value_t::null;
4333 assert_invariant();
4334 break;
4335 }
4336
4337 case value_t::object:
4338 {
4339 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4340 break;
4341 }
4342
4343 case value_t::array:
4344 {
4345 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4346 break;
4347 }
4348
4349 default:
4350 {
4351 JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4352 }
4353 }
4354
4355 return result;
4356 }
4357
4404 template<class IteratorType, typename std::enable_if<
4405 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4406 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4407 = 0>
4409 {
4410 // make sure iterator fits the current value
4411 if (this != first.m_object or this != last.m_object)
4412 {
4413 JSON_THROW(std::domain_error("iterators do not fit current value"));
4414 }
4415
4417
4418 switch (m_type)
4419 {
4420 case value_t::boolean:
4421 case value_t::number_float:
4422 case value_t::number_integer:
4423 case value_t::number_unsigned:
4424 case value_t::string:
4425 {
4426 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4427 {
4428 JSON_THROW(std::out_of_range("iterators out of range"));
4429 }
4430
4431 if (is_string())
4432 {
4434 alloc.destroy(m_value.string);
4435 alloc.deallocate(m_value.string, 1);
4436 m_value.string = nullptr;
4437 }
4438
4439 m_type = value_t::null;
4440 assert_invariant();
4441 break;
4442 }
4443
4444 case value_t::object:
4445 {
4446 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4447 last.m_it.object_iterator);
4448 break;
4449 }
4450
4451 case value_t::array:
4452 {
4453 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4454 last.m_it.array_iterator);
4455 break;
4456 }
4457
4458 default:
4459 {
4460 JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4461 }
4462 }
4463
4464 return result;
4465 }
4466
4496 size_type erase(const typename object_t::key_type& key)
4497 {
4498 // this erase only works for objects
4499 if (is_object())
4500 {
4501 return m_value.object->erase(key);
4502 }
4503
4504 JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4505 }
4506
4531 void erase(const size_type idx)
4532 {
4533 // this erase only works for arrays
4534 if (is_array())
4535 {
4536 if (idx >= size())
4537 {
4538 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
4539 }
4540
4541 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4542 }
4543 else
4544 {
4545 JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4546 }
4547 }
4548
4550
4551
4553 // lookup //
4555
4558
4581 iterator find(typename object_t::key_type key)
4582 {
4583 auto result = end();
4584
4585 if (is_object())
4586 {
4587 result.m_it.object_iterator = m_value.object->find(key);
4588 }
4589
4590 return result;
4591 }
4592
4597 const_iterator find(typename object_t::key_type key) const
4598 {
4599 auto result = cend();
4600
4601 if (is_object())
4602 {
4603 result.m_it.object_iterator = m_value.object->find(key);
4604 }
4605
4606 return result;
4607 }
4608
4630 size_type count(typename object_t::key_type key) const
4631 {
4632 // return 0 for all nonobject types
4633 return is_object() ? m_value.object->count(key) : 0;
4634 }
4635
4637
4638
4640 // iterators //
4642
4645
4671 {
4672 iterator result(this);
4673 result.set_begin();
4674 return result;
4675 }
4676
4681 {
4682 return cbegin();
4683 }
4684
4711 {
4712 const_iterator result(this);
4713 result.set_begin();
4714 return result;
4715 }
4716
4742 {
4743 iterator result(this);
4744 result.set_end();
4745 return result;
4746 }
4747
4752 {
4753 return cend();
4754 }
4755
4782 {
4783 const_iterator result(this);
4784 result.set_end();
4785 return result;
4786 }
4787
4812 {
4813 return reverse_iterator(end());
4814 }
4815
4820 {
4821 return crbegin();
4822 }
4823
4849 {
4850 return reverse_iterator(begin());
4851 }
4852
4857 {
4858 return crend();
4859 }
4860
4889
4918
4919 private:
4920 // forward declaration
4921 template<typename IteratorType> class iteration_proxy;
4922
4923 public:
4939
4947
4949
4950
4952 // capacity //
4954
4957
4996 {
4997 switch (m_type)
4998 {
4999 case value_t::null:
5000 {
5001 // null values are empty
5002 return true;
5003 }
5004
5005 case value_t::array:
5006 {
5007 // delegate call to array_t::empty()
5008 return m_value.array->empty();
5009 }
5010
5011 case value_t::object:
5012 {
5013 // delegate call to object_t::empty()
5014 return m_value.object->empty();
5015 }
5016
5017 default:
5018 {
5019 // all other types are nonempty
5020 return false;
5021 }
5022 }
5023 }
5024
5064 {
5065 switch (m_type)
5066 {
5067 case value_t::null:
5068 {
5069 // null values are empty
5070 return 0;
5071 }
5072
5073 case value_t::array:
5074 {
5075 // delegate call to array_t::size()
5076 return m_value.array->size();
5077 }
5078
5079 case value_t::object:
5080 {
5081 // delegate call to object_t::size()
5082 return m_value.object->size();
5083 }
5084
5085 default:
5086 {
5087 // all other types have size 1
5088 return 1;
5089 }
5090 }
5091 }
5092
5130 {
5131 switch (m_type)
5132 {
5133 case value_t::array:
5134 {
5135 // delegate call to array_t::max_size()
5136 return m_value.array->max_size();
5137 }
5138
5139 case value_t::object:
5140 {
5141 // delegate call to object_t::max_size()
5142 return m_value.object->max_size();
5143 }
5144
5145 default:
5146 {
5147 // all other types have max_size() == size()
5148 return size();
5149 }
5150 }
5151 }
5152
5154
5155
5157 // modifiers //
5159
5162
5186 {
5187 switch (m_type)
5188 {
5189 case value_t::number_integer:
5190 {
5191 m_value.number_integer = 0;
5192 break;
5193 }
5194
5195 case value_t::number_unsigned:
5196 {
5197 m_value.number_unsigned = 0;
5198 break;
5199 }
5200
5201 case value_t::number_float:
5202 {
5203 m_value.number_float = 0.0;
5204 break;
5205 }
5206
5207 case value_t::boolean:
5208 {
5209 m_value.boolean = false;
5210 break;
5211 }
5212
5213 case value_t::string:
5214 {
5215 m_value.string->clear();
5216 break;
5217 }
5218
5219 case value_t::array:
5220 {
5221 m_value.array->clear();
5222 break;
5223 }
5224
5225 case value_t::object:
5226 {
5227 m_value.object->clear();
5228 break;
5229 }
5230
5231 default:
5232 {
5233 break;
5234 }
5235 }
5236 }
5237
5259 {
5260 // push_back only works for null objects or arrays
5261 if (not(is_null() or is_array()))
5262 {
5263 JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5264 }
5265
5266 // transform null object into an array
5267 if (is_null())
5268 {
5269 m_type = value_t::array;
5270 m_value = value_t::array;
5271 assert_invariant();
5272 }
5273
5274 // add element to array (move semantics)
5275 m_value.array->push_back(std::move(val));
5276 // invalidate object
5277 val.m_type = value_t::null;
5278 }
5279
5285 {
5286 push_back(std::move(val));
5287 return *this;
5288 }
5289
5295 {
5296 // push_back only works for null objects or arrays
5297 if (not(is_null() or is_array()))
5298 {
5299 JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5300 }
5301
5302 // transform null object into an array
5303 if (is_null())
5304 {
5305 m_type = value_t::array;
5306 m_value = value_t::array;
5307 assert_invariant();
5308 }
5309
5310 // add element to array
5311 m_value.array->push_back(val);
5312 }
5313
5319 {
5320 push_back(val);
5321 return *this;
5322 }
5323
5344 void push_back(const typename object_t::value_type& val)
5345 {
5346 // push_back only works for null objects or objects
5347 if (not(is_null() or is_object()))
5348 {
5349 JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5350 }
5351
5352 // transform null object into an object
5353 if (is_null())
5354 {
5355 m_type = value_t::object;
5356 m_value = value_t::object;
5357 assert_invariant();
5358 }
5359
5360 // add element to array
5361 m_value.object->insert(val);
5362 }
5363
5368 reference operator+=(const typename object_t::value_type& val)
5369 {
5370 push_back(val);
5371 return *this;
5372 }
5373
5399 void push_back(std::initializer_list<basic_json> init)
5400 {
5401 if (is_object() and init.size() == 2 and init.begin()->is_string())
5402 {
5403 const string_t key = *init.begin();
5404 push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5405 }
5406 else
5407 {
5409 }
5410 }
5411
5416 reference operator+=(std::initializer_list<basic_json> init)
5417 {
5418 push_back(init);
5419 return *this;
5420 }
5421
5443 template<class... Args>
5445 {
5446 // emplace_back only works for null objects or arrays
5447 if (not(is_null() or is_array()))
5448 {
5449 JSON_THROW(std::domain_error("cannot use emplace_back() with " + type_name()));
5450 }
5451
5452 // transform null object into an array
5453 if (is_null())
5454 {
5455 m_type = value_t::array;
5456 m_value = value_t::array;
5457 assert_invariant();
5458 }
5459
5460 // add element to array (perfect forwarding)
5461 m_value.array->emplace_back(std::forward<Args>(args)...);
5462 }
5463
5491 template<class... Args>
5492 std::pair<iterator, bool> emplace(Args&& ... args)
5493 {
5494 // emplace only works for null objects or arrays
5495 if (not(is_null() or is_object()))
5496 {
5497 JSON_THROW(std::domain_error("cannot use emplace() with " + type_name()));
5498 }
5499
5500 // transform null object into an object
5501 if (is_null())
5502 {
5503 m_type = value_t::object;
5504 m_value = value_t::object;
5505 assert_invariant();
5506 }
5507
5508 // add element to array (perfect forwarding)
5509 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5510 // create result iterator and set iterator to the result of emplace
5511 auto it = begin();
5512 it.m_it.object_iterator = res.first;
5513
5514 // return pair of iterator and boolean
5515 return {it, res.second};
5516 }
5517
5541 {
5542 // insert only works for arrays
5543 if (is_array())
5544 {
5545 // check if iterator pos fits to this JSON value
5546 if (pos.m_object != this)
5547 {
5548 JSON_THROW(std::domain_error("iterator does not fit current value"));
5549 }
5550
5551 // insert to array and return iterator
5552 iterator result(this);
5553 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5554 return result;
5555 }
5556
5557 JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5558 }
5559
5565 {
5566 return insert(pos, val);
5567 }
5568
5594 {
5595 // insert only works for arrays
5596 if (is_array())
5597 {
5598 // check if iterator pos fits to this JSON value
5599 if (pos.m_object != this)
5600 {
5601 JSON_THROW(std::domain_error("iterator does not fit current value"));
5602 }
5603
5604 // insert to array and return iterator
5605 iterator result(this);
5606 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5607 return result;
5608 }
5609
5610 JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5611 }
5612
5644 {
5645 // insert only works for arrays
5646 if (not is_array())
5647 {
5648 JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5649 }
5650
5651 // check if iterator pos fits to this JSON value
5652 if (pos.m_object != this)
5653 {
5654 JSON_THROW(std::domain_error("iterator does not fit current value"));
5655 }
5656
5657 // check if range iterators belong to the same JSON object
5658 if (first.m_object != last.m_object)
5659 {
5660 JSON_THROW(std::domain_error("iterators do not fit"));
5661 }
5662
5663 if (first.m_object == this or last.m_object == this)
5664 {
5665 JSON_THROW(std::domain_error("passed iterators may not belong to container"));
5666 }
5667
5668 // insert to array and return iterator
5669 iterator result(this);
5670 result.m_it.array_iterator = m_value.array->insert(
5671 pos.m_it.array_iterator,
5672 first.m_it.array_iterator,
5673 last.m_it.array_iterator);
5674 return result;
5675 }
5676
5701 iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5702 {
5703 // insert only works for arrays
5704 if (not is_array())
5705 {
5706 JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5707 }
5708
5709 // check if iterator pos fits to this JSON value
5710 if (pos.m_object != this)
5711 {
5712 JSON_THROW(std::domain_error("iterator does not fit current value"));
5713 }
5714
5715 // insert to array and return iterator
5716 iterator result(this);
5717 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5718 return result;
5719 }
5720
5738 void swap(reference other) noexcept (
5739 std::is_nothrow_move_constructible<value_t>::value and
5740 std::is_nothrow_move_assignable<value_t>::value and
5741 std::is_nothrow_move_constructible<json_value>::value and
5742 std::is_nothrow_move_assignable<json_value>::value
5743 )
5744 {
5745 std::swap(m_type, other.m_type);
5746 std::swap(m_value, other.m_value);
5747 assert_invariant();
5748 }
5749
5771 {
5772 // swap only works for arrays
5773 if (is_array())
5774 {
5775 std::swap(*(m_value.array), other);
5776 }
5777 else
5778 {
5779 JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5780 }
5781 }
5782
5804 {
5805 // swap only works for objects
5806 if (is_object())
5807 {
5808 std::swap(*(m_value.object), other);
5809 }
5810 else
5811 {
5812 JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5813 }
5814 }
5815
5837 {
5838 // swap only works for strings
5839 if (is_string())
5840 {
5841 std::swap(*(m_value.string), other);
5842 }
5843 else
5844 {
5845 JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5846 }
5847 }
5848
5850
5851 public:
5853 // lexicographical comparison operators //
5855
5858
5883 {
5884 const auto lhs_type = lhs.type();
5885 const auto rhs_type = rhs.type();
5886
5887 if (lhs_type == rhs_type)
5888 {
5889 switch (lhs_type)
5890 {
5891 case value_t::array:
5892 {
5893 return *lhs.m_value.array == *rhs.m_value.array;
5894 }
5895 case value_t::object:
5896 {
5897 return *lhs.m_value.object == *rhs.m_value.object;
5898 }
5899 case value_t::null:
5900 {
5901 return true;
5902 }
5903 case value_t::string:
5904 {
5905 return *lhs.m_value.string == *rhs.m_value.string;
5906 }
5907 case value_t::boolean:
5908 {
5909 return lhs.m_value.boolean == rhs.m_value.boolean;
5910 }
5911 case value_t::number_integer:
5912 {
5913 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5914 }
5915 case value_t::number_unsigned:
5916 {
5917 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5918 }
5919 case value_t::number_float:
5920 {
5921 return lhs.m_value.number_float == rhs.m_value.number_float;
5922 }
5923 default:
5924 {
5925 return false;
5926 }
5927 }
5928 }
5929 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5930 {
5931 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5932 }
5933 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5934 {
5935 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5936 }
5937 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5938 {
5939 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5940 }
5941 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5942 {
5943 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5944 }
5945 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5946 {
5947 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5948 }
5949 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5950 {
5951 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5952 }
5953
5954 return false;
5955 }
5956
5961 template<typename ScalarType, typename std::enable_if<
5962 std::is_scalar<ScalarType>::value, int>::type = 0>
5963 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
5964 {
5965 return (lhs == basic_json(rhs));
5966 }
5967
5972 template<typename ScalarType, typename std::enable_if<
5973 std::is_scalar<ScalarType>::value, int>::type = 0>
5974 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
5975 {
5976 return (basic_json(lhs) == rhs);
5977 }
5978
5996 {
5997 return not (lhs == rhs);
5998 }
5999
6004 template<typename ScalarType, typename std::enable_if<
6005 std::is_scalar<ScalarType>::value, int>::type = 0>
6006 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
6007 {
6008 return (lhs != basic_json(rhs));
6009 }
6010
6015 template<typename ScalarType, typename std::enable_if<
6016 std::is_scalar<ScalarType>::value, int>::type = 0>
6017 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
6018 {
6019 return (basic_json(lhs) != rhs);
6020 }
6021
6047 {
6048 const auto lhs_type = lhs.type();
6049 const auto rhs_type = rhs.type();
6050
6051 if (lhs_type == rhs_type)
6052 {
6053 switch (lhs_type)
6054 {
6055 case value_t::array:
6056 {
6057 return *lhs.m_value.array < *rhs.m_value.array;
6058 }
6059 case value_t::object:
6060 {
6061 return *lhs.m_value.object < *rhs.m_value.object;
6062 }
6063 case value_t::null:
6064 {
6065 return false;
6066 }
6067 case value_t::string:
6068 {
6069 return *lhs.m_value.string < *rhs.m_value.string;
6070 }
6071 case value_t::boolean:
6072 {
6073 return lhs.m_value.boolean < rhs.m_value.boolean;
6074 }
6075 case value_t::number_integer:
6076 {
6077 return lhs.m_value.number_integer < rhs.m_value.number_integer;
6078 }
6079 case value_t::number_unsigned:
6080 {
6081 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
6082 }
6083 case value_t::number_float:
6084 {
6085 return lhs.m_value.number_float < rhs.m_value.number_float;
6086 }
6087 default:
6088 {
6089 return false;
6090 }
6091 }
6092 }
6093 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
6094 {
6095 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
6096 }
6097 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
6098 {
6099 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
6100 }
6101 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
6102 {
6103 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
6104 }
6105 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
6106 {
6107 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
6108 }
6109 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
6110 {
6111 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6112 }
6113 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
6114 {
6115 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
6116 }
6117
6118 // We only reach this line if we cannot compare values. In that case,
6119 // we compare types. Note we have to call the operator explicitly,
6120 // because MSVC has problems otherwise.
6121 return operator<(lhs_type, rhs_type);
6122 }
6123
6142 {
6143 return not (rhs < lhs);
6144 }
6145
6164 {
6165 return not (lhs <= rhs);
6166 }
6167
6186 {
6187 return not (lhs < rhs);
6188 }
6189
6191
6192
6194 // serialization //
6196
6199
6222 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
6223 {
6224 // read width member and use it as indentation parameter if nonzero
6225 const bool pretty_print = (o.width() > 0);
6226 const auto indentation = (pretty_print ? o.width() : 0);
6227
6228 // reset width to 0 for subsequent calls to this stream
6229 o.width(0);
6230
6231 // do the actual serialization
6232 j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
6233
6234 return o;
6235 }
6236
6241 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
6242 {
6243 return o << j;
6244 }
6245
6247
6248
6250 // deserialization //
6252
6255
6283 template<class T, std::size_t N>
6284 static basic_json parse(T (&array)[N],
6285 const parser_callback_t cb = nullptr)
6286 {
6287 // delegate the call to the iterator-range parse overload
6288 return parse(std::begin(array), std::end(array), cb);
6289 }
6290
6318 template<typename CharT, typename std::enable_if<
6319 std::is_pointer<CharT>::value and
6320 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6321 sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
6322 static basic_json parse(const CharT s,
6323 const parser_callback_t cb = nullptr)
6324 {
6325 return parser(reinterpret_cast<const char*>(s), cb).parse();
6326 }
6327
6352 static basic_json parse(std::istream& i,
6353 const parser_callback_t cb = nullptr)
6354 {
6355 return parser(i, cb).parse();
6356 }
6357
6361 static basic_json parse(std::istream&& i,
6362 const parser_callback_t cb = nullptr)
6363 {
6364 return parser(i, cb).parse();
6365 }
6366
6408 template<class IteratorType, typename std::enable_if<
6409 std::is_base_of<
6410 std::random_access_iterator_tag,
6411 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6413 const parser_callback_t cb = nullptr)
6414 {
6415 // assertion to check that the iterator range is indeed contiguous,
6416 // see http://stackoverflow.com/a/35008842/266378 for more discussion
6417 assert(std::accumulate(first, last, std::pair<bool, int>(true, 0),
6418 [&first](std::pair<bool, int> res, decltype(*first) val)
6419 {
6420 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6421 return res;
6422 }).first);
6423
6424 // assertion to check that each element is 1 byte long
6425 static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6426 "each element in the iterator range must have the size of 1 byte");
6427
6428 // if iterator range is empty, create a parser with an empty string
6429 // to generate "unexpected EOF" error message
6430 if (std::distance(first, last) <= 0)
6431 {
6432 return parser("").parse();
6433 }
6434
6435 return parser(first, last, cb).parse();
6436 }
6437
6478 template<class ContiguousContainer, typename std::enable_if<
6479 not std::is_pointer<ContiguousContainer>::value and
6480 std::is_base_of<
6481 std::random_access_iterator_tag,
6482 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6483 , int>::type = 0>
6485 const parser_callback_t cb = nullptr)
6486 {
6487 // delegate the call to the iterator-range parse overload
6488 return parse(std::begin(c), std::end(c), cb);
6489 }
6490
6514 friend std::istream& operator<<(basic_json& j, std::istream& i)
6515 {
6516 j = parser(i).parse();
6517 return i;
6518 }
6519
6524 friend std::istream& operator>>(std::istream& i, basic_json& j)
6525 {
6526 j = parser(i).parse();
6527 return i;
6528 }
6529
6531
6533 // binary serialization/deserialization //
6535
6538
6539 private:
6545 template<typename T>
6546 static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
6547 {
6548 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6549
6550 switch (bytes)
6551 {
6552 case 8:
6553 {
6554 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 070) & 0xff));
6555 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 060) & 0xff));
6556 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 050) & 0xff));
6557 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 040) & 0xff));
6558 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6559 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6560 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6561 vec.push_back(static_cast<uint8_t>(number & 0xff));
6562 break;
6563 }
6564
6565 case 4:
6566 {
6567 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6568 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6569 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6570 vec.push_back(static_cast<uint8_t>(number & 0xff));
6571 break;
6572 }
6573
6574 case 2:
6575 {
6576 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6577 vec.push_back(static_cast<uint8_t>(number & 0xff));
6578 break;
6579 }
6580
6581 case 1:
6582 {
6583 vec.push_back(static_cast<uint8_t>(number & 0xff));
6584 break;
6585 }
6586 }
6587 }
6588
6625 template<typename T>
6626 static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
6627 {
6628 if (current_index + sizeof(T) + 1 > vec.size())
6629 {
6630 JSON_THROW(std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector"));
6631 }
6632
6633 T result;
6634 auto* ptr = reinterpret_cast<uint8_t*>(&result);
6635 for (size_t i = 0; i < sizeof(T); ++i)
6636 {
6637 *ptr++ = vec[current_index + sizeof(T) - i];
6638 }
6639 return result;
6640 }
6641
6652 static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
6653 {
6654 switch (j.type())
6655 {
6656 case value_t::null:
6657 {
6658 // nil
6659 v.push_back(0xc0);
6660 break;
6661 }
6662
6663 case value_t::boolean:
6664 {
6665 // true and false
6666 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6667 break;
6668 }
6669
6670 case value_t::number_integer:
6671 {
6672 if (j.m_value.number_integer >= 0)
6673 {
6674 // MessagePack does not differentiate between positive
6675 // signed integers and unsigned integers. Therefore, we
6676 // used the code from the value_t::number_unsigned case
6677 // here.
6678 if (j.m_value.number_unsigned < 128)
6679 {
6680 // positive fixnum
6681 add_to_vector(v, 1, j.m_value.number_unsigned);
6682 }
6683 else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6684 {
6685 // uint 8
6686 v.push_back(0xcc);
6687 add_to_vector(v, 1, j.m_value.number_unsigned);
6688 }
6689 else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6690 {
6691 // uint 16
6692 v.push_back(0xcd);
6693 add_to_vector(v, 2, j.m_value.number_unsigned);
6694 }
6695 else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6696 {
6697 // uint 32
6698 v.push_back(0xce);
6699 add_to_vector(v, 4, j.m_value.number_unsigned);
6700 }
6701 else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6702 {
6703 // uint 64
6704 v.push_back(0xcf);
6705 add_to_vector(v, 8, j.m_value.number_unsigned);
6706 }
6707 }
6708 else
6709 {
6710 if (j.m_value.number_integer >= -32)
6711 {
6712 // negative fixnum
6713 add_to_vector(v, 1, j.m_value.number_integer);
6714 }
6715 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())
6716 {
6717 // int 8
6718 v.push_back(0xd0);
6719 add_to_vector(v, 1, j.m_value.number_integer);
6720 }
6721 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())
6722 {
6723 // int 16
6724 v.push_back(0xd1);
6725 add_to_vector(v, 2, j.m_value.number_integer);
6726 }
6727 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())
6728 {
6729 // int 32
6730 v.push_back(0xd2);
6731 add_to_vector(v, 4, j.m_value.number_integer);
6732 }
6733 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())
6734 {
6735 // int 64
6736 v.push_back(0xd3);
6737 add_to_vector(v, 8, j.m_value.number_integer);
6738 }
6739 }
6740 break;
6741 }
6742
6743 case value_t::number_unsigned:
6744 {
6745 if (j.m_value.number_unsigned < 128)
6746 {
6747 // positive fixnum
6748 add_to_vector(v, 1, j.m_value.number_unsigned);
6749 }
6750 else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6751 {
6752 // uint 8
6753 v.push_back(0xcc);
6754 add_to_vector(v, 1, j.m_value.number_unsigned);
6755 }
6756 else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6757 {
6758 // uint 16
6759 v.push_back(0xcd);
6760 add_to_vector(v, 2, j.m_value.number_unsigned);
6761 }
6762 else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6763 {
6764 // uint 32
6765 v.push_back(0xce);
6766 add_to_vector(v, 4, j.m_value.number_unsigned);
6767 }
6768 else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6769 {
6770 // uint 64
6771 v.push_back(0xcf);
6772 add_to_vector(v, 8, j.m_value.number_unsigned);
6773 }
6774 break;
6775 }
6776
6777 case value_t::number_float:
6778 {
6779 // float 64
6780 v.push_back(0xcb);
6781 const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6782 for (size_t i = 0; i < 8; ++i)
6783 {
6784 v.push_back(helper[7 - i]);
6785 }
6786 break;
6787 }
6788
6789 case value_t::string:
6790 {
6791 const auto N = j.m_value.string->size();
6792 if (N <= 31)
6793 {
6794 // fixstr
6795 v.push_back(static_cast<uint8_t>(0xa0 | N));
6796 }
6797 else if (N <= 255)
6798 {
6799 // str 8
6800 v.push_back(0xd9);
6801 add_to_vector(v, 1, N);
6802 }
6803 else if (N <= 65535)
6804 {
6805 // str 16
6806 v.push_back(0xda);
6807 add_to_vector(v, 2, N);
6808 }
6809 else if (N <= 4294967295)
6810 {
6811 // str 32
6812 v.push_back(0xdb);
6813 add_to_vector(v, 4, N);
6814 }
6815
6816 // append string
6817 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6818 std::back_inserter(v));
6819 break;
6820 }
6821
6822 case value_t::array:
6823 {
6824 const auto N = j.m_value.array->size();
6825 if (N <= 15)
6826 {
6827 // fixarray
6828 v.push_back(static_cast<uint8_t>(0x90 | N));
6829 }
6830 else if (N <= 0xffff)
6831 {
6832 // array 16
6833 v.push_back(0xdc);
6834 add_to_vector(v, 2, N);
6835 }
6836 else if (N <= 0xffffffff)
6837 {
6838 // array 32
6839 v.push_back(0xdd);
6840 add_to_vector(v, 4, N);
6841 }
6842
6843 // append each element
6844 for (const auto& el : *j.m_value.array)
6845 {
6846 to_msgpack_internal(el, v);
6847 }
6848 break;
6849 }
6850
6851 case value_t::object:
6852 {
6853 const auto N = j.m_value.object->size();
6854 if (N <= 15)
6855 {
6856 // fixmap
6857 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6858 }
6859 else if (N <= 65535)
6860 {
6861 // map 16
6862 v.push_back(0xde);
6863 add_to_vector(v, 2, N);
6864 }
6865 else if (N <= 4294967295)
6866 {
6867 // map 32
6868 v.push_back(0xdf);
6869 add_to_vector(v, 4, N);
6870 }
6871
6872 // append each element
6873 for (const auto& el : *j.m_value.object)
6874 {
6875 to_msgpack_internal(el.first, v);
6876 to_msgpack_internal(el.second, v);
6877 }
6878 break;
6879 }
6880
6881 default:
6882 {
6883 break;
6884 }
6885 }
6886 }
6887
6898 static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
6899 {
6900 switch (j.type())
6901 {
6902 case value_t::null:
6903 {
6904 v.push_back(0xf6);
6905 break;
6906 }
6907
6908 case value_t::boolean:
6909 {
6910 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6911 break;
6912 }
6913
6914 case value_t::number_integer:
6915 {
6916 if (j.m_value.number_integer >= 0)
6917 {
6918 // CBOR does not differentiate between positive signed
6919 // integers and unsigned integers. Therefore, we used the
6920 // code from the value_t::number_unsigned case here.
6921 if (j.m_value.number_integer <= 0x17)
6922 {
6923 add_to_vector(v, 1, j.m_value.number_integer);
6924 }
6925 else if (j.m_value.number_integer <= std::numeric_limits<uint8_t>::max())
6926 {
6927 v.push_back(0x18);
6928 // one-byte uint8_t
6929 add_to_vector(v, 1, j.m_value.number_integer);
6930 }
6931 else if (j.m_value.number_integer <= std::numeric_limits<uint16_t>::max())
6932 {
6933 v.push_back(0x19);
6934 // two-byte uint16_t
6935 add_to_vector(v, 2, j.m_value.number_integer);
6936 }
6937 else if (j.m_value.number_integer <= std::numeric_limits<uint32_t>::max())
6938 {
6939 v.push_back(0x1a);
6940 // four-byte uint32_t
6941 add_to_vector(v, 4, j.m_value.number_integer);
6942 }
6943 else
6944 {
6945 v.push_back(0x1b);
6946 // eight-byte uint64_t
6947 add_to_vector(v, 8, j.m_value.number_integer);
6948 }
6949 }
6950 else
6951 {
6952 // The conversions below encode the sign in the first
6953 // byte, and the value is converted to a positive number.
6954 const auto positive_number = -1 - j.m_value.number_integer;
6955 if (j.m_value.number_integer >= -24)
6956 {
6957 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6958 }
6959 else if (positive_number <= std::numeric_limits<uint8_t>::max())
6960 {
6961 // int 8
6962 v.push_back(0x38);
6963 add_to_vector(v, 1, positive_number);
6964 }
6965 else if (positive_number <= std::numeric_limits<uint16_t>::max())
6966 {
6967 // int 16
6968 v.push_back(0x39);
6969 add_to_vector(v, 2, positive_number);
6970 }
6971 else if (positive_number <= std::numeric_limits<uint32_t>::max())
6972 {
6973 // int 32
6974 v.push_back(0x3a);
6975 add_to_vector(v, 4, positive_number);
6976 }
6977 else
6978 {
6979 // int 64
6980 v.push_back(0x3b);
6981 add_to_vector(v, 8, positive_number);
6982 }
6983 }
6984 break;
6985 }
6986
6987 case value_t::number_unsigned:
6988 {
6989 if (j.m_value.number_unsigned <= 0x17)
6990 {
6991 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6992 }
6993 else if (j.m_value.number_unsigned <= 0xff)
6994 {
6995 v.push_back(0x18);
6996 // one-byte uint8_t
6997 add_to_vector(v, 1, j.m_value.number_unsigned);
6998 }
6999 else if (j.m_value.number_unsigned <= 0xffff)
7000 {
7001 v.push_back(0x19);
7002 // two-byte uint16_t
7003 add_to_vector(v, 2, j.m_value.number_unsigned);
7004 }
7005 else if (j.m_value.number_unsigned <= 0xffffffff)
7006 {
7007 v.push_back(0x1a);
7008 // four-byte uint32_t
7009 add_to_vector(v, 4, j.m_value.number_unsigned);
7010 }
7011 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
7012 {
7013 v.push_back(0x1b);
7014 // eight-byte uint64_t
7015 add_to_vector(v, 8, j.m_value.number_unsigned);
7016 }
7017 break;
7018 }
7019
7020 case value_t::number_float:
7021 {
7022 // Double-Precision Float
7023 v.push_back(0xfb);
7024 const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
7025 for (size_t i = 0; i < 8; ++i)
7026 {
7027 v.push_back(helper[7 - i]);
7028 }
7029 break;
7030 }
7031
7032 case value_t::string:
7033 {
7034 const auto N = j.m_value.string->size();
7035 if (N <= 0x17)
7036 {
7037 v.push_back(0x60 + static_cast<uint8_t>(N)); // 1 byte for string + size
7038 }
7039 else if (N <= 0xff)
7040 {
7041 v.push_back(0x78); // one-byte uint8_t for N
7042 add_to_vector(v, 1, N);
7043 }
7044 else if (N <= 0xffff)
7045 {
7046 v.push_back(0x79); // two-byte uint16_t for N
7047 add_to_vector(v, 2, N);
7048 }
7049 else if (N <= 0xffffffff)
7050 {
7051 v.push_back(0x7a); // four-byte uint32_t for N
7052 add_to_vector(v, 4, N);
7053 }
7054 // LCOV_EXCL_START
7055 else if (N <= 0xffffffffffffffff)
7056 {
7057 v.push_back(0x7b); // eight-byte uint64_t for N
7058 add_to_vector(v, 8, N);
7059 }
7060 // LCOV_EXCL_STOP
7061
7062 // append string
7063 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
7064 std::back_inserter(v));
7065 break;
7066 }
7067
7068 case value_t::array:
7069 {
7070 const auto N = j.m_value.array->size();
7071 if (N <= 0x17)
7072 {
7073 v.push_back(0x80 + static_cast<uint8_t>(N)); // 1 byte for array + size
7074 }
7075 else if (N <= 0xff)
7076 {
7077 v.push_back(0x98); // one-byte uint8_t for N
7078 add_to_vector(v, 1, N);
7079 }
7080 else if (N <= 0xffff)
7081 {
7082 v.push_back(0x99); // two-byte uint16_t for N
7083 add_to_vector(v, 2, N);
7084 }
7085 else if (N <= 0xffffffff)
7086 {
7087 v.push_back(0x9a); // four-byte uint32_t for N
7088 add_to_vector(v, 4, N);
7089 }
7090 // LCOV_EXCL_START
7091 else if (N <= 0xffffffffffffffff)
7092 {
7093 v.push_back(0x9b); // eight-byte uint64_t for N
7094 add_to_vector(v, 8, N);
7095 }
7096 // LCOV_EXCL_STOP
7097
7098 // append each element
7099 for (const auto& el : *j.m_value.array)
7100 {
7101 to_cbor_internal(el, v);
7102 }
7103 break;
7104 }
7105
7106 case value_t::object:
7107 {
7108 const auto N = j.m_value.object->size();
7109 if (N <= 0x17)
7110 {
7111 v.push_back(0xa0 + static_cast<uint8_t>(N)); // 1 byte for object + size
7112 }
7113 else if (N <= 0xff)
7114 {
7115 v.push_back(0xb8);
7116 add_to_vector(v, 1, N); // one-byte uint8_t for N
7117 }
7118 else if (N <= 0xffff)
7119 {
7120 v.push_back(0xb9);
7121 add_to_vector(v, 2, N); // two-byte uint16_t for N
7122 }
7123 else if (N <= 0xffffffff)
7124 {
7125 v.push_back(0xba);
7126 add_to_vector(v, 4, N); // four-byte uint32_t for N
7127 }
7128 // LCOV_EXCL_START
7129 else if (N <= 0xffffffffffffffff)
7130 {
7131 v.push_back(0xbb);
7132 add_to_vector(v, 8, N); // eight-byte uint64_t for N
7133 }
7134 // LCOV_EXCL_STOP
7135
7136 // append each element
7137 for (const auto& el : *j.m_value.object)
7138 {
7139 to_cbor_internal(el.first, v);
7140 to_cbor_internal(el.second, v);
7141 }
7142 break;
7143 }
7144
7145 default:
7146 {
7147 break;
7148 }
7149 }
7150 }
7151
7152
7153 /*
7154 @brief checks if given lengths do not exceed the size of a given vector
7155
7156 To secure the access to the byte vector during CBOR/MessagePack
7157 deserialization, bytes are copied from the vector into buffers. This
7158 function checks if the number of bytes to copy (@a len) does not exceed
7159 the size @s size of the vector. Additionally, an @a offset is given from
7160 where to start reading the bytes.
7161
7162 This function checks whether reading the bytes is safe; that is, offset is
7163 a valid index in the vector, offset+len
7164
7165 @param[in] size size of the byte vector
7166 @param[in] len number of bytes to read
7167 @param[in] offset offset where to start reading
7168
7169 vec: x x x x x X X X X X
7170 ^ ^ ^
7171 0 offset len
7172
7173 @throws out_of_range if `len > v.size()`
7174 */
7175 static void check_length(const size_t size, const size_t len, const size_t offset)
7176 {
7177 // simple case: requested length is greater than the vector's length
7178 if (len > size or offset > size)
7179 {
7180 JSON_THROW(std::out_of_range("len out of range"));
7181 }
7182
7183 // second case: adding offset would result in overflow
7184 if ((size > (std::numeric_limits<size_t>::max() - offset)))
7185 {
7186 JSON_THROW(std::out_of_range("len+offset out of range"));
7187 }
7188
7189 // last case: reading past the end of the vector
7190 if (len + offset > size)
7191 {
7192 JSON_THROW(std::out_of_range("len+offset out of range"));
7193 }
7194 }
7195
7210 static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
7211 {
7212 // make sure reading 1 byte is safe
7213 check_length(v.size(), 1, idx);
7214
7215 // store and increment index
7216 const size_t current_idx = idx++;
7217
7218 if (v[current_idx] <= 0xbf)
7219 {
7220 if (v[current_idx] <= 0x7f) // positive fixint
7221 {
7222 return v[current_idx];
7223 }
7224 if (v[current_idx] <= 0x8f) // fixmap
7225 {
7226 basic_json result = value_t::object;
7227 const size_t len = v[current_idx] & 0x0f;
7228 for (size_t i = 0; i < len; ++i)
7229 {
7230 std::string key = from_msgpack_internal(v, idx);
7231 result[key] = from_msgpack_internal(v, idx);
7232 }
7233 return result;
7234 }
7235 else if (v[current_idx] <= 0x9f) // fixarray
7236 {
7237 basic_json result = value_t::array;
7238 const size_t len = v[current_idx] & 0x0f;
7239 for (size_t i = 0; i < len; ++i)
7240 {
7241 result.push_back(from_msgpack_internal(v, idx));
7242 }
7243 return result;
7244 }
7245 else // fixstr
7246 {
7247 const size_t len = v[current_idx] & 0x1f;
7248 const size_t offset = current_idx + 1;
7249 idx += len; // skip content bytes
7250 check_length(v.size(), len, offset);
7251 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7252 }
7253 }
7254 else if (v[current_idx] >= 0xe0) // negative fixint
7255 {
7256 return static_cast<int8_t>(v[current_idx]);
7257 }
7258 else
7259 {
7260 switch (v[current_idx])
7261 {
7262 case 0xc0: // nil
7263 {
7264 return value_t::null;
7265 }
7266
7267 case 0xc2: // false
7268 {
7269 return false;
7270 }
7271
7272 case 0xc3: // true
7273 {
7274 return true;
7275 }
7276
7277 case 0xca: // float 32
7278 {
7279 // copy bytes in reverse order into the double variable
7280 float res;
7281 for (size_t byte = 0; byte < sizeof(float); ++byte)
7282 {
7283 reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
7284 }
7285 idx += sizeof(float); // skip content bytes
7286 return res;
7287 }
7288
7289 case 0xcb: // float 64
7290 {
7291 // copy bytes in reverse order into the double variable
7292 double res;
7293 for (size_t byte = 0; byte < sizeof(double); ++byte)
7294 {
7295 reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
7296 }
7297 idx += sizeof(double); // skip content bytes
7298 return res;
7299 }
7300
7301 case 0xcc: // uint 8
7302 {
7303 idx += 1; // skip content byte
7305 }
7306
7307 case 0xcd: // uint 16
7308 {
7309 idx += 2; // skip 2 content bytes
7311 }
7312
7313 case 0xce: // uint 32
7314 {
7315 idx += 4; // skip 4 content bytes
7317 }
7318
7319 case 0xcf: // uint 64
7320 {
7321 idx += 8; // skip 8 content bytes
7323 }
7324
7325 case 0xd0: // int 8
7326 {
7327 idx += 1; // skip content byte
7329 }
7330
7331 case 0xd1: // int 16
7332 {
7333 idx += 2; // skip 2 content bytes
7335 }
7336
7337 case 0xd2: // int 32
7338 {
7339 idx += 4; // skip 4 content bytes
7341 }
7342
7343 case 0xd3: // int 64
7344 {
7345 idx += 8; // skip 8 content bytes
7347 }
7348
7349 case 0xd9: // str 8
7350 {
7351 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7352 const size_t offset = current_idx + 2;
7353 idx += len + 1; // skip size byte + content bytes
7354 check_length(v.size(), len, offset);
7355 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7356 }
7357
7358 case 0xda: // str 16
7359 {
7360 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7361 const size_t offset = current_idx + 3;
7362 idx += len + 2; // skip 2 size bytes + content bytes
7363 check_length(v.size(), len, offset);
7364 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7365 }
7366
7367 case 0xdb: // str 32
7368 {
7369 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7370 const size_t offset = current_idx + 5;
7371 idx += len + 4; // skip 4 size bytes + content bytes
7372 check_length(v.size(), len, offset);
7373 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7374 }
7375
7376 case 0xdc: // array 16
7377 {
7378 basic_json result = value_t::array;
7379 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7380 idx += 2; // skip 2 size bytes
7381 for (size_t i = 0; i < len; ++i)
7382 {
7383 result.push_back(from_msgpack_internal(v, idx));
7384 }
7385 return result;
7386 }
7387
7388 case 0xdd: // array 32
7389 {
7390 basic_json result = value_t::array;
7391 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7392 idx += 4; // skip 4 size bytes
7393 for (size_t i = 0; i < len; ++i)
7394 {
7395 result.push_back(from_msgpack_internal(v, idx));
7396 }
7397 return result;
7398 }
7399
7400 case 0xde: // map 16
7401 {
7402 basic_json result = value_t::object;
7403 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7404 idx += 2; // skip 2 size bytes
7405 for (size_t i = 0; i < len; ++i)
7406 {
7407 std::string key = from_msgpack_internal(v, idx);
7408 result[key] = from_msgpack_internal(v, idx);
7409 }
7410 return result;
7411 }
7412
7413 case 0xdf: // map 32
7414 {
7415 basic_json result = value_t::object;
7416 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7417 idx += 4; // skip 4 size bytes
7418 for (size_t i = 0; i < len; ++i)
7419 {
7420 std::string key = from_msgpack_internal(v, idx);
7421 result[key] = from_msgpack_internal(v, idx);
7422 }
7423 return result;
7424 }
7425
7426 default:
7427 {
7428 JSON_THROW(std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));
7429 }
7430 }
7431 }
7432 }
7433
7448 static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
7449 {
7450 // store and increment index
7451 const size_t current_idx = idx++;
7452
7453 switch (v.at(current_idx))
7454 {
7455 // Integer 0x00..0x17 (0..23)
7456 case 0x00:
7457 case 0x01:
7458 case 0x02:
7459 case 0x03:
7460 case 0x04:
7461 case 0x05:
7462 case 0x06:
7463 case 0x07:
7464 case 0x08:
7465 case 0x09:
7466 case 0x0a:
7467 case 0x0b:
7468 case 0x0c:
7469 case 0x0d:
7470 case 0x0e:
7471 case 0x0f:
7472 case 0x10:
7473 case 0x11:
7474 case 0x12:
7475 case 0x13:
7476 case 0x14:
7477 case 0x15:
7478 case 0x16:
7479 case 0x17:
7480 {
7481 return v[current_idx];
7482 }
7483
7484 case 0x18: // Unsigned integer (one-byte uint8_t follows)
7485 {
7486 idx += 1; // skip content byte
7488 }
7489
7490 case 0x19: // Unsigned integer (two-byte uint16_t follows)
7491 {
7492 idx += 2; // skip 2 content bytes
7494 }
7495
7496 case 0x1a: // Unsigned integer (four-byte uint32_t follows)
7497 {
7498 idx += 4; // skip 4 content bytes
7500 }
7501
7502 case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
7503 {
7504 idx += 8; // skip 8 content bytes
7506 }
7507
7508 // Negative integer -1-0x00..-1-0x17 (-1..-24)
7509 case 0x20:
7510 case 0x21:
7511 case 0x22:
7512 case 0x23:
7513 case 0x24:
7514 case 0x25:
7515 case 0x26:
7516 case 0x27:
7517 case 0x28:
7518 case 0x29:
7519 case 0x2a:
7520 case 0x2b:
7521 case 0x2c:
7522 case 0x2d:
7523 case 0x2e:
7524 case 0x2f:
7525 case 0x30:
7526 case 0x31:
7527 case 0x32:
7528 case 0x33:
7529 case 0x34:
7530 case 0x35:
7531 case 0x36:
7532 case 0x37:
7533 {
7534 return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
7535 }
7536
7537 case 0x38: // Negative integer (one-byte uint8_t follows)
7538 {
7539 idx += 1; // skip content byte
7540 // must be uint8_t !
7541 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7542 }
7543
7544 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
7545 {
7546 idx += 2; // skip 2 content bytes
7547 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7548 }
7549
7550 case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
7551 {
7552 idx += 4; // skip 4 content bytes
7553 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7554 }
7555
7556 case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
7557 {
7558 idx += 8; // skip 8 content bytes
7559 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7560 }
7561
7562 // UTF-8 string (0x00..0x17 bytes follow)
7563 case 0x60:
7564 case 0x61:
7565 case 0x62:
7566 case 0x63:
7567 case 0x64:
7568 case 0x65:
7569 case 0x66:
7570 case 0x67:
7571 case 0x68:
7572 case 0x69:
7573 case 0x6a:
7574 case 0x6b:
7575 case 0x6c:
7576 case 0x6d:
7577 case 0x6e:
7578 case 0x6f:
7579 case 0x70:
7580 case 0x71:
7581 case 0x72:
7582 case 0x73:
7583 case 0x74:
7584 case 0x75:
7585 case 0x76:
7586 case 0x77:
7587 {
7588 const auto len = static_cast<size_t>(v[current_idx] - 0x60);
7589 const size_t offset = current_idx + 1;
7590 idx += len; // skip content bytes
7591 check_length(v.size(), len, offset);
7592 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7593 }
7594
7595 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7596 {
7597 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7598 const size_t offset = current_idx + 2;
7599 idx += len + 1; // skip size byte + content bytes
7600 check_length(v.size(), len, offset);
7601 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7602 }
7603
7604 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7605 {
7606 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7607 const size_t offset = current_idx + 3;
7608 idx += len + 2; // skip 2 size bytes + content bytes
7609 check_length(v.size(), len, offset);
7610 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7611 }
7612
7613 case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
7614 {
7615 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7616 const size_t offset = current_idx + 5;
7617 idx += len + 4; // skip 4 size bytes + content bytes
7618 check_length(v.size(), len, offset);
7619 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7620 }
7621
7622 case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
7623 {
7624 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7625 const size_t offset = current_idx + 9;
7626 idx += len + 8; // skip 8 size bytes + content bytes
7627 check_length(v.size(), len, offset);
7628 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7629 }
7630
7631 case 0x7f: // UTF-8 string (indefinite length)
7632 {
7633 std::string result;
7634 while (v.at(idx) != 0xff)
7635 {
7636 string_t s = from_cbor_internal(v, idx);
7637 result += s;
7638 }
7639 // skip break byte (0xFF)
7640 idx += 1;
7641 return result;
7642 }
7643
7644 // array (0x00..0x17 data items follow)
7645 case 0x80:
7646 case 0x81:
7647 case 0x82:
7648 case 0x83:
7649 case 0x84:
7650 case 0x85:
7651 case 0x86:
7652 case 0x87:
7653 case 0x88:
7654 case 0x89:
7655 case 0x8a:
7656 case 0x8b:
7657 case 0x8c:
7658 case 0x8d:
7659 case 0x8e:
7660 case 0x8f:
7661 case 0x90:
7662 case 0x91:
7663 case 0x92:
7664 case 0x93:
7665 case 0x94:
7666 case 0x95:
7667 case 0x96:
7668 case 0x97:
7669 {
7670 basic_json result = value_t::array;
7671 const auto len = static_cast<size_t>(v[current_idx] - 0x80);
7672 for (size_t i = 0; i < len; ++i)
7673 {
7674 result.push_back(from_cbor_internal(v, idx));
7675 }
7676 return result;
7677 }
7678
7679 case 0x98: // array (one-byte uint8_t for n follows)
7680 {
7681 basic_json result = value_t::array;
7682 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7683 idx += 1; // skip 1 size byte
7684 for (size_t i = 0; i < len; ++i)
7685 {
7686 result.push_back(from_cbor_internal(v, idx));
7687 }
7688 return result;
7689 }
7690
7691 case 0x99: // array (two-byte uint16_t for n follow)
7692 {
7693 basic_json result = value_t::array;
7694 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7695 idx += 2; // skip 4 size bytes
7696 for (size_t i = 0; i < len; ++i)
7697 {
7698 result.push_back(from_cbor_internal(v, idx));
7699 }
7700 return result;
7701 }
7702
7703 case 0x9a: // array (four-byte uint32_t for n follow)
7704 {
7705 basic_json result = value_t::array;
7706 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7707 idx += 4; // skip 4 size bytes
7708 for (size_t i = 0; i < len; ++i)
7709 {
7710 result.push_back(from_cbor_internal(v, idx));
7711 }
7712 return result;
7713 }
7714
7715 case 0x9b: // array (eight-byte uint64_t for n follow)
7716 {
7717 basic_json result = value_t::array;
7718 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7719 idx += 8; // skip 8 size bytes
7720 for (size_t i = 0; i < len; ++i)
7721 {
7722 result.push_back(from_cbor_internal(v, idx));
7723 }
7724 return result;
7725 }
7726
7727 case 0x9f: // array (indefinite length)
7728 {
7729 basic_json result = value_t::array;
7730 while (v.at(idx) != 0xff)
7731 {
7732 result.push_back(from_cbor_internal(v, idx));
7733 }
7734 // skip break byte (0xFF)
7735 idx += 1;
7736 return result;
7737 }
7738
7739 // map (0x00..0x17 pairs of data items follow)
7740 case 0xa0:
7741 case 0xa1:
7742 case 0xa2:
7743 case 0xa3:
7744 case 0xa4:
7745 case 0xa5:
7746 case 0xa6:
7747 case 0xa7:
7748 case 0xa8:
7749 case 0xa9:
7750 case 0xaa:
7751 case 0xab:
7752 case 0xac:
7753 case 0xad:
7754 case 0xae:
7755 case 0xaf:
7756 case 0xb0:
7757 case 0xb1:
7758 case 0xb2:
7759 case 0xb3:
7760 case 0xb4:
7761 case 0xb5:
7762 case 0xb6:
7763 case 0xb7:
7764 {
7765 basic_json result = value_t::object;
7766 const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
7767 for (size_t i = 0; i < len; ++i)
7768 {
7769 std::string key = from_cbor_internal(v, idx);
7770 result[key] = from_cbor_internal(v, idx);
7771 }
7772 return result;
7773 }
7774
7775 case 0xb8: // map (one-byte uint8_t for n follows)
7776 {
7777 basic_json result = value_t::object;
7778 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7779 idx += 1; // skip 1 size byte
7780 for (size_t i = 0; i < len; ++i)
7781 {
7782 std::string key = from_cbor_internal(v, idx);
7783 result[key] = from_cbor_internal(v, idx);
7784 }
7785 return result;
7786 }
7787
7788 case 0xb9: // map (two-byte uint16_t for n follow)
7789 {
7790 basic_json result = value_t::object;
7791 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7792 idx += 2; // skip 2 size bytes
7793 for (size_t i = 0; i < len; ++i)
7794 {
7795 std::string key = from_cbor_internal(v, idx);
7796 result[key] = from_cbor_internal(v, idx);
7797 }
7798 return result;
7799 }
7800
7801 case 0xba: // map (four-byte uint32_t for n follow)
7802 {
7803 basic_json result = value_t::object;
7804 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7805 idx += 4; // skip 4 size bytes
7806 for (size_t i = 0; i < len; ++i)
7807 {
7808 std::string key = from_cbor_internal(v, idx);
7809 result[key] = from_cbor_internal(v, idx);
7810 }
7811 return result;
7812 }
7813
7814 case 0xbb: // map (eight-byte uint64_t for n follow)
7815 {
7816 basic_json result = value_t::object;
7817 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7818 idx += 8; // skip 8 size bytes
7819 for (size_t i = 0; i < len; ++i)
7820 {
7821 std::string key = from_cbor_internal(v, idx);
7822 result[key] = from_cbor_internal(v, idx);
7823 }
7824 return result;
7825 }
7826
7827 case 0xbf: // map (indefinite length)
7828 {
7829 basic_json result = value_t::object;
7830 while (v.at(idx) != 0xff)
7831 {
7832 std::string key = from_cbor_internal(v, idx);
7833 result[key] = from_cbor_internal(v, idx);
7834 }
7835 // skip break byte (0xFF)
7836 idx += 1;
7837 return result;
7838 }
7839
7840 case 0xf4: // false
7841 {
7842 return false;
7843 }
7844
7845 case 0xf5: // true
7846 {
7847 return true;
7848 }
7849
7850 case 0xf6: // null
7851 {
7852 return value_t::null;
7853 }
7854
7855 case 0xf9: // Half-Precision Float (two-byte IEEE 754)
7856 {
7857 idx += 2; // skip two content bytes
7858
7859 // code from RFC 7049, Appendix D, Figure 3:
7860 // As half-precision floating-point numbers were only added to
7861 // IEEE 754 in 2008, today's programming platforms often still
7862 // only have limited support for them. It is very easy to
7863 // include at least decoding support for them even without such
7864 // support. An example of a small decoder for half-precision
7865 // floating-point numbers in the C language is shown in Fig. 3.
7866 const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);
7867 const int exp = (half >> 10) & 0x1f;
7868 const int mant = half & 0x3ff;
7869 double val;
7870 if (exp == 0)
7871 {
7872 val = std::ldexp(mant, -24);
7873 }
7874 else if (exp != 31)
7875 {
7876 val = std::ldexp(mant + 1024, exp - 25);
7877 }
7878 else
7879 {
7880 val = mant == 0
7881 ? std::numeric_limits<double>::infinity()
7883 }
7884 return (half & 0x8000) != 0 ? -val : val;
7885 }
7886
7887 case 0xfa: // Single-Precision Float (four-byte IEEE 754)
7888 {
7889 // copy bytes in reverse order into the float variable
7890 float res;
7891 for (size_t byte = 0; byte < sizeof(float); ++byte)
7892 {
7893 reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
7894 }
7895 idx += sizeof(float); // skip content bytes
7896 return res;
7897 }
7898
7899 case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
7900 {
7901 // copy bytes in reverse order into the double variable
7902 double res;
7903 for (size_t byte = 0; byte < sizeof(double); ++byte)
7904 {
7905 reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
7906 }
7907 idx += sizeof(double); // skip content bytes
7908 return res;
7909 }
7910
7911 default: // anything else (0xFF is handled inside the other types)
7912 {
7913 JSON_THROW(std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));
7914 }
7915 }
7916 }
7917
7918 public:
7941 static std::vector<uint8_t> to_msgpack(const basic_json& j)
7942 {
7943 std::vector<uint8_t> result;
7944 to_msgpack_internal(j, result);
7945 return result;
7946 }
7947
7974 static basic_json from_msgpack(const std::vector<uint8_t>& v,
7975 const size_t start_index = 0)
7976 {
7977 size_t i = start_index;
7978 return from_msgpack_internal(v, i);
7979 }
7980
8004 static std::vector<uint8_t> to_cbor(const basic_json& j)
8005 {
8006 std::vector<uint8_t> result;
8007 to_cbor_internal(j, result);
8008 return result;
8009 }
8010
8037 static basic_json from_cbor(const std::vector<uint8_t>& v,
8038 const size_t start_index = 0)
8039 {
8040 size_t i = start_index;
8041 return from_cbor_internal(v, i);
8042 }
8043
8045
8047 // convenience functions //
8049
8065 std::string type_name() const
8066 {
8067 {
8068 switch (m_type)
8069 {
8070 case value_t::null:
8071 return "null";
8072 case value_t::object:
8073 return "object";
8074 case value_t::array:
8075 return "array";
8076 case value_t::string:
8077 return "string";
8078 case value_t::boolean:
8079 return "boolean";
8080 case value_t::discarded:
8081 return "discarded";
8082 default:
8083 return "number";
8084 }
8085 }
8086 }
8087
8088 private:
8097 static std::size_t extra_space(const string_t& s) noexcept
8098 {
8099 return std::accumulate(s.begin(), s.end(), size_t{},
8100 [](size_t res, typename string_t::value_type c)
8101 {
8102 switch (c)
8103 {
8104 case '"':
8105 case '\\':
8106 case '\b':
8107 case '\f':
8108 case '\n':
8109 case '\r':
8110 case '\t':
8111 {
8112 // from c (1 byte) to \x (2 bytes)
8113 return res + 1;
8114 }
8115
8116 default:
8117 {
8118 if (c >= 0x00 and c <= 0x1f)
8119 {
8120 // from c (1 byte) to \uxxxx (6 bytes)
8121 return res + 5;
8122 }
8123
8124 return res;
8125 }
8126 }
8127 });
8128 }
8129
8143 static string_t escape_string(const string_t& s)
8144 {
8145 const auto space = extra_space(s);
8146 if (space == 0)
8147 {
8148 return s;
8149 }
8150
8151 // create a result string of necessary size
8152 string_t result(s.size() + space, '\\');
8153 std::size_t pos = 0;
8154
8155 for (const auto& c : s)
8156 {
8157 switch (c)
8158 {
8159 // quotation mark (0x22)
8160 case '"':
8161 {
8162 result[pos + 1] = '"';
8163 pos += 2;
8164 break;
8165 }
8166
8167 // reverse solidus (0x5c)
8168 case '\\':
8169 {
8170 // nothing to change
8171 pos += 2;
8172 break;
8173 }
8174
8175 // backspace (0x08)
8176 case '\b':
8177 {
8178 result[pos + 1] = 'b';
8179 pos += 2;
8180 break;
8181 }
8182
8183 // formfeed (0x0c)
8184 case '\f':
8185 {
8186 result[pos + 1] = 'f';
8187 pos += 2;
8188 break;
8189 }
8190
8191 // newline (0x0a)
8192 case '\n':
8193 {
8194 result[pos + 1] = 'n';
8195 pos += 2;
8196 break;
8197 }
8198
8199 // carriage return (0x0d)
8200 case '\r':
8201 {
8202 result[pos + 1] = 'r';
8203 pos += 2;
8204 break;
8205 }
8206
8207 // horizontal tab (0x09)
8208 case '\t':
8209 {
8210 result[pos + 1] = 't';
8211 pos += 2;
8212 break;
8213 }
8214
8215 default:
8216 {
8217 if (c >= 0x00 and c <= 0x1f)
8218 {
8219 // convert a number 0..15 to its hex representation
8220 // (0..f)
8221 static const char hexify[16] =
8222 {
8223 '0', '1', '2', '3', '4', '5', '6', '7',
8224 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
8225 };
8226
8227 // print character c as \uxxxx
8228 for (const char m :
8229 { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
8230 })
8231 {
8232 result[++pos] = m;
8233 }
8234
8235 ++pos;
8236 }
8237 else
8238 {
8239 // all other characters are added as-is
8240 result[pos++] = c;
8241 }
8242 break;
8243 }
8244 }
8245 }
8246
8247 return result;
8248 }
8249
8250
8254 struct numtostr
8255 {
8256 public:
8257 template<typename NumberType>
8258 numtostr(NumberType value)
8259 {
8260 x_write(value, std::is_integral<NumberType>());
8261 }
8262
8263 const char* c_str() const
8264 {
8265 return m_buf.data();
8266 }
8267
8268 private:
8270 std::array < char, 64 > m_buf{{}};
8271
8272 template<typename NumberType>
8273 void x_write(NumberType x, /*is_integral=*/std::true_type)
8274 {
8275 // special case for "0"
8276 if (x == 0)
8277 {
8278 m_buf[0] = '0';
8279 return;
8280 }
8281
8282 const bool is_negative = x < 0;
8283 size_t i = 0;
8284
8285 // spare 1 byte for '\0'
8286 while (x != 0 and i < m_buf.size() - 1)
8287 {
8288 const auto digit = std::labs(static_cast<long>(x % 10));
8289 m_buf[i++] = static_cast<char>('0' + digit);
8290 x /= 10;
8291 }
8292
8293 // make sure the number has been processed completely
8294 assert(x == 0);
8295
8296 if (is_negative)
8297 {
8298 // make sure there is capacity for the '-'
8299 assert(i < m_buf.size() - 2);
8300 m_buf[i++] = '-';
8301 }
8302
8303 std::reverse(m_buf.begin(), m_buf.begin() + i);
8304 }
8305
8306 template<typename NumberType>
8307 void x_write(NumberType x, /*is_integral=*/std::false_type)
8308 {
8309 // special case for 0.0 and -0.0
8310 if (x == 0)
8311 {
8312 size_t i = 0;
8313 if (std::signbit(x))
8314 {
8315 m_buf[i++] = '-';
8316 }
8317 m_buf[i++] = '0';
8318 m_buf[i++] = '.';
8319 m_buf[i] = '0';
8320 return;
8321 }
8322
8323 // get number of digits for a text -> float -> text round-trip
8324 static constexpr auto d = std::numeric_limits<NumberType>::digits10;
8325
8326 // the actual conversion
8327 const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x);
8328
8329 // negative value indicates an error
8330 assert(written_bytes > 0);
8331 // check if buffer was large enough
8332 assert(static_cast<size_t>(written_bytes) < m_buf.size());
8333
8334 // read information from locale
8335 const auto loc = localeconv();
8336 assert(loc != nullptr);
8337 const char thousands_sep = !loc->thousands_sep ? '\0'
8338 : loc->thousands_sep[0];
8339
8340 const char decimal_point = !loc->decimal_point ? '\0'
8341 : loc->decimal_point[0];
8342
8343 // erase thousands separator
8344 if (thousands_sep != '\0')
8345 {
8346 const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep);
8347 std::fill(end, m_buf.end(), '\0');
8348 }
8349
8350 // convert decimal point to '.'
8351 if (decimal_point != '\0' and decimal_point != '.')
8352 {
8353 for (auto& c : m_buf)
8354 {
8355 if (c == decimal_point)
8356 {
8357 c = '.';
8358 break;
8359 }
8360 }
8361 }
8362
8363 // determine if need to append ".0"
8364 size_t i = 0;
8365 bool value_is_int_like = true;
8366 for (i = 0; i < m_buf.size(); ++i)
8367 {
8368 // break when end of number is reached
8369 if (m_buf[i] == '\0')
8370 {
8371 break;
8372 }
8373
8374 // check if we find non-int character
8375 value_is_int_like = value_is_int_like and m_buf[i] != '.' and
8376 m_buf[i] != 'e' and m_buf[i] != 'E';
8377 }
8378
8379 if (value_is_int_like)
8380 {
8381 // there must be 2 bytes left for ".0"
8382 assert((i + 2) < m_buf.size());
8383 // we write to the end of the number
8384 assert(m_buf[i] == '\0');
8385 assert(m_buf[i - 1] != '\0');
8386
8387 // add ".0"
8388 m_buf[i] = '.';
8389 m_buf[i + 1] = '0';
8390
8391 // the resulting string is properly terminated
8392 assert(m_buf[i + 2] == '\0');
8393 }
8394 }
8395 };
8396
8397
8415 void dump(std::ostream& o,
8416 const bool pretty_print,
8417 const unsigned int indent_step,
8418 const unsigned int current_indent = 0) const
8419 {
8420 // variable to hold indentation for recursive calls
8421 unsigned int new_indent = current_indent;
8422
8423 switch (m_type)
8424 {
8425 case value_t::object:
8426 {
8427 if (m_value.object->empty())
8428 {
8429 o << "{}";
8430 return;
8431 }
8432
8433 o << "{";
8434
8435 // increase indentation
8436 if (pretty_print)
8437 {
8438 new_indent += indent_step;
8439 o << "\n";
8440 }
8441
8442 for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
8443 {
8444 if (i != m_value.object->cbegin())
8445 {
8446 o << (pretty_print ? ",\n" : ",");
8447 }
8448 o << string_t(new_indent, ' ') << "\""
8449 << escape_string(i->first) << "\":"
8450 << (pretty_print ? " " : "");
8451 i->second.dump(o, pretty_print, indent_step, new_indent);
8452 }
8453
8454 // decrease indentation
8455 if (pretty_print)
8456 {
8457 new_indent -= indent_step;
8458 o << "\n";
8459 }
8460
8461 o << string_t(new_indent, ' ') + "}";
8462 return;
8463 }
8464
8465 case value_t::array:
8466 {
8467 if (m_value.array->empty())
8468 {
8469 o << "[]";
8470 return;
8471 }
8472
8473 o << "[";
8474
8475 // increase indentation
8476 if (pretty_print)
8477 {
8478 new_indent += indent_step;
8479 o << "\n";
8480 }
8481
8482 for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8483 {
8484 if (i != m_value.array->cbegin())
8485 {
8486 o << (pretty_print ? ",\n" : ",");
8487 }
8488 o << string_t(new_indent, ' ');
8489 i->dump(o, pretty_print, indent_step, new_indent);
8490 }
8491
8492 // decrease indentation
8493 if (pretty_print)
8494 {
8495 new_indent -= indent_step;
8496 o << "\n";
8497 }
8498
8499 o << string_t(new_indent, ' ') << "]";
8500 return;
8501 }
8502
8503 case value_t::string:
8504 {
8505 o << string_t("\"") << escape_string(*m_value.string) << "\"";
8506 return;
8507 }
8508
8509 case value_t::boolean:
8510 {
8511 o << (m_value.boolean ? "true" : "false");
8512 return;
8513 }
8514
8515 case value_t::number_integer:
8516 {
8517 o << numtostr(m_value.number_integer).c_str();
8518 return;
8519 }
8520
8521 case value_t::number_unsigned:
8522 {
8523 o << numtostr(m_value.number_unsigned).c_str();
8524 return;
8525 }
8526
8527 case value_t::number_float:
8528 {
8529 o << numtostr(m_value.number_float).c_str();
8530 return;
8531 }
8532
8533 case value_t::discarded:
8534 {
8535 o << "<discarded>";
8536 return;
8537 }
8538
8539 case value_t::null:
8540 {
8541 o << "null";
8542 return;
8543 }
8544 }
8545 }
8546
8547 private:
8549 // member variables //
8551
8553 value_t m_type = value_t::null;
8554
8556 json_value m_value = {};
8557
8558
8559 private:
8561 // iterators //
8563
8573 class primitive_iterator_t
8574 {
8575 public:
8576
8577 difference_type get_value() const noexcept
8578 {
8579 return m_it;
8580 }
8582 void set_begin() noexcept
8583 {
8584 m_it = begin_value;
8585 }
8586
8588 void set_end() noexcept
8589 {
8590 m_it = end_value;
8591 }
8592
8594 constexpr bool is_begin() const noexcept
8595 {
8596 return (m_it == begin_value);
8597 }
8598
8600 constexpr bool is_end() const noexcept
8601 {
8602 return (m_it == end_value);
8603 }
8604
8605 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8606 {
8607 return lhs.m_it == rhs.m_it;
8608 }
8609
8610 friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8611 {
8612 return !(lhs == rhs);
8613 }
8614
8615 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8616 {
8617 return lhs.m_it < rhs.m_it;
8618 }
8619
8620 friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8621 {
8622 return lhs.m_it <= rhs.m_it;
8623 }
8624
8625 friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8626 {
8627 return lhs.m_it > rhs.m_it;
8628 }
8629
8630 friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8631 {
8632 return lhs.m_it >= rhs.m_it;
8633 }
8634
8635 primitive_iterator_t operator+(difference_type i)
8636 {
8637 auto result = *this;
8638 result += i;
8639 return result;
8640 }
8641
8642 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8643 {
8644 return lhs.m_it - rhs.m_it;
8645 }
8646
8647 friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
8648 {
8649 return os << it.m_it;
8650 }
8651
8652 primitive_iterator_t& operator++()
8653 {
8654 ++m_it;
8655 return *this;
8656 }
8657
8658 primitive_iterator_t operator++(int)
8659 {
8660 auto result = *this;
8661 m_it++;
8662 return result;
8663 }
8664
8665 primitive_iterator_t& operator--()
8666 {
8667 --m_it;
8668 return *this;
8669 }
8670
8671 primitive_iterator_t operator--(int)
8672 {
8673 auto result = *this;
8674 m_it--;
8675 return result;
8676 }
8677
8678 primitive_iterator_t& operator+=(difference_type n)
8679 {
8680 m_it += n;
8681 return *this;
8682 }
8683
8684 primitive_iterator_t& operator-=(difference_type n)
8685 {
8686 m_it -= n;
8687 return *this;
8688 }
8689
8690 private:
8691 static constexpr difference_type begin_value = 0;
8692 static constexpr difference_type end_value = begin_value + 1;
8693
8695 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8696 };
8697
8705 struct internal_iterator
8706 {
8708 typename object_t::iterator object_iterator;
8710 typename array_t::iterator array_iterator;
8712 primitive_iterator_t primitive_iterator;
8713
8715 internal_iterator() noexcept
8716 : object_iterator(), array_iterator(), primitive_iterator()
8717 {}
8718 };
8719
8721 template<typename IteratorType>
8722 class iteration_proxy
8723 {
8724 private:
8726 class iteration_proxy_internal
8727 {
8728 private:
8730 IteratorType anchor;
8732 size_t array_index = 0;
8733
8734 public:
8735 explicit iteration_proxy_internal(IteratorType it) noexcept
8736 : anchor(it)
8737 {}
8738
8740 iteration_proxy_internal& operator*()
8741 {
8742 return *this;
8743 }
8744
8746 iteration_proxy_internal& operator++()
8747 {
8748 ++anchor;
8749 ++array_index;
8750
8751 return *this;
8752 }
8753
8755 bool operator!= (const iteration_proxy_internal& o) const
8756 {
8757 return anchor != o.anchor;
8758 }
8759
8761 typename basic_json::string_t key() const
8762 {
8763 assert(anchor.m_object != nullptr);
8764
8765 switch (anchor.m_object->type())
8766 {
8767 // use integer array index as key
8768 case value_t::array:
8769 {
8770 return std::to_string(array_index);
8771 }
8772
8773 // use key from the object
8774 case value_t::object:
8775 {
8776 return anchor.key();
8777 }
8778
8779 // use an empty key for all primitive types
8780 default:
8781 {
8782 return "";
8783 }
8784 }
8785 }
8786
8788 typename IteratorType::reference value() const
8789 {
8790 return anchor.value();
8791 }
8792 };
8793
8795 typename IteratorType::reference container;
8796
8797 public:
8799 explicit iteration_proxy(typename IteratorType::reference cont)
8800 : container(cont)
8801 {}
8802
8804 iteration_proxy_internal begin() noexcept
8805 {
8806 return iteration_proxy_internal(container.begin());
8807 }
8808
8810 iteration_proxy_internal end() noexcept
8811 {
8812 return iteration_proxy_internal(container.end());
8813 }
8814 };
8815
8816 public:
8836 template<typename U>
8837 class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
8838 {
8840 friend class basic_json;
8841
8842 // make sure U is basic_json or const basic_json
8843 static_assert(std::is_same<U, basic_json>::value
8844 or std::is_same<U, const basic_json>::value,
8845 "iter_impl only accepts (const) basic_json");
8846
8847 public:
8853 using pointer = typename std::conditional<std::is_const<U>::value,
8855 typename basic_json::pointer>::type;
8857 using reference = typename std::conditional<std::is_const<U>::value,
8859 typename basic_json::reference>::type;
8861 using iterator_category = std::bidirectional_iterator_tag;
8862
8864 iter_impl() = default;
8865
8872 explicit iter_impl(pointer object) noexcept
8873 : m_object(object)
8874 {
8875 assert(m_object != nullptr);
8876
8877 switch (m_object->m_type)
8878 {
8879 case basic_json::value_t::object:
8880 {
8881 m_it.object_iterator = typename object_t::iterator();
8882 break;
8883 }
8884
8885 case basic_json::value_t::array:
8886 {
8887 m_it.array_iterator = typename array_t::iterator();
8888 break;
8889 }
8890
8891 default:
8892 {
8893 m_it.primitive_iterator = primitive_iterator_t();
8894 break;
8895 }
8896 }
8897 }
8898
8899 /*
8900 Use operator `const_iterator` instead of `const_iterator(const iterator&
8901 other) noexcept` to avoid two class definitions for @ref iterator and
8902 @ref const_iterator.
8903
8904 This function is only called if this class is an @ref iterator. If this
8905 class is a @ref const_iterator this function is not called.
8906 */
8907 operator const_iterator() const
8908 {
8909 const_iterator ret;
8910
8911 if (m_object)
8912 {
8913 ret.m_object = m_object;
8914 ret.m_it = m_it;
8915 }
8916
8917 return ret;
8918 }
8919
8925 iter_impl(const iter_impl& other) noexcept
8926 : m_object(other.m_object), m_it(other.m_it)
8927 {}
8928
8935 std::is_nothrow_move_constructible<pointer>::value and
8936 std::is_nothrow_move_assignable<pointer>::value and
8937 std::is_nothrow_move_constructible<internal_iterator>::value and
8938 std::is_nothrow_move_assignable<internal_iterator>::value
8939 )
8940 {
8941 std::swap(m_object, other.m_object);
8942 std::swap(m_it, other.m_it);
8943 return *this;
8944 }
8945
8946 private:
8951 void set_begin() noexcept
8952 {
8953 assert(m_object != nullptr);
8954
8955 switch (m_object->m_type)
8956 {
8957 case basic_json::value_t::object:
8958 {
8959 m_it.object_iterator = m_object->m_value.object->begin();
8960 break;
8961 }
8962
8963 case basic_json::value_t::array:
8964 {
8965 m_it.array_iterator = m_object->m_value.array->begin();
8966 break;
8967 }
8968
8969 case basic_json::value_t::null:
8970 {
8971 // set to end so begin()==end() is true: null is empty
8972 m_it.primitive_iterator.set_end();
8973 break;
8974 }
8975
8976 default:
8977 {
8978 m_it.primitive_iterator.set_begin();
8979 break;
8980 }
8981 }
8982 }
8983
8988 void set_end() noexcept
8989 {
8990 assert(m_object != nullptr);
8991
8992 switch (m_object->m_type)
8993 {
8994 case basic_json::value_t::object:
8995 {
8996 m_it.object_iterator = m_object->m_value.object->end();
8997 break;
8998 }
8999
9000 case basic_json::value_t::array:
9001 {
9002 m_it.array_iterator = m_object->m_value.array->end();
9003 break;
9004 }
9005
9006 default:
9007 {
9008 m_it.primitive_iterator.set_end();
9009 break;
9010 }
9011 }
9012 }
9013
9014 public:
9020 {
9021 assert(m_object != nullptr);
9022
9023 switch (m_object->m_type)
9024 {
9025 case basic_json::value_t::object:
9026 {
9027 assert(m_it.object_iterator != m_object->m_value.object->end());
9028 return m_it.object_iterator->second;
9029 }
9030
9031 case basic_json::value_t::array:
9032 {
9033 assert(m_it.array_iterator != m_object->m_value.array->end());
9034 return *m_it.array_iterator;
9035 }
9036
9037 case basic_json::value_t::null:
9038 {
9039 JSON_THROW(std::out_of_range("cannot get value"));
9040 }
9041
9042 default:
9043 {
9044 if (m_it.primitive_iterator.is_begin())
9045 {
9046 return *m_object;
9047 }
9048
9049 JSON_THROW(std::out_of_range("cannot get value"));
9050 }
9051 }
9052 }
9053
9059 {
9060 assert(m_object != nullptr);
9061
9062 switch (m_object->m_type)
9063 {
9064 case basic_json::value_t::object:
9065 {
9066 assert(m_it.object_iterator != m_object->m_value.object->end());
9067 return &(m_it.object_iterator->second);
9068 }
9069
9070 case basic_json::value_t::array:
9071 {
9072 assert(m_it.array_iterator != m_object->m_value.array->end());
9073 return &*m_it.array_iterator;
9074 }
9075
9076 default:
9077 {
9078 if (m_it.primitive_iterator.is_begin())
9079 {
9080 return m_object;
9081 }
9082
9083 JSON_THROW(std::out_of_range("cannot get value"));
9084 }
9085 }
9086 }
9087
9093 {
9094 auto result = *this;
9095 ++(*this);
9096 return result;
9097 }
9098
9104 {
9105 assert(m_object != nullptr);
9106
9107 switch (m_object->m_type)
9108 {
9109 case basic_json::value_t::object:
9110 {
9111 std::advance(m_it.object_iterator, 1);
9112 break;
9113 }
9114
9115 case basic_json::value_t::array:
9116 {
9117 std::advance(m_it.array_iterator, 1);
9118 break;
9119 }
9120
9121 default:
9122 {
9123 ++m_it.primitive_iterator;
9124 break;
9125 }
9126 }
9127
9128 return *this;
9129 }
9130
9136 {
9137 auto result = *this;
9138 --(*this);
9139 return result;
9140 }
9141
9147 {
9148 assert(m_object != nullptr);
9149
9150 switch (m_object->m_type)
9151 {
9152 case basic_json::value_t::object:
9153 {
9154 std::advance(m_it.object_iterator, -1);
9155 break;
9156 }
9157
9158 case basic_json::value_t::array:
9159 {
9160 std::advance(m_it.array_iterator, -1);
9161 break;
9162 }
9163
9164 default:
9165 {
9166 --m_it.primitive_iterator;
9167 break;
9168 }
9169 }
9170
9171 return *this;
9172 }
9173
9178 bool operator==(const iter_impl& other) const
9179 {
9180 // if objects are not the same, the comparison is undefined
9181 if (m_object != other.m_object)
9182 {
9183 JSON_THROW(std::domain_error("cannot compare iterators of different containers"));
9184 }
9185
9186 assert(m_object != nullptr);
9187
9188 switch (m_object->m_type)
9189 {
9190 case basic_json::value_t::object:
9191 {
9192 return (m_it.object_iterator == other.m_it.object_iterator);
9193 }
9194
9195 case basic_json::value_t::array:
9196 {
9197 return (m_it.array_iterator == other.m_it.array_iterator);
9198 }
9199
9200 default:
9201 {
9202 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
9203 }
9204 }
9205 }
9206
9211 bool operator!=(const iter_impl& other) const
9212 {
9213 return not operator==(other);
9214 }
9215
9220 bool operator<(const iter_impl& other) const
9221 {
9222 // if objects are not the same, the comparison is undefined
9223 if (m_object != other.m_object)
9224 {
9225 JSON_THROW(std::domain_error("cannot compare iterators of different containers"));
9226 }
9227
9228 assert(m_object != nullptr);
9229
9230 switch (m_object->m_type)
9231 {
9232 case basic_json::value_t::object:
9233 {
9234 JSON_THROW(std::domain_error("cannot compare order of object iterators"));
9235 }
9236
9237 case basic_json::value_t::array:
9238 {
9239 return (m_it.array_iterator < other.m_it.array_iterator);
9240 }
9241
9242 default:
9243 {
9244 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
9245 }
9246 }
9247 }
9248
9253 bool operator<=(const iter_impl& other) const
9254 {
9255 return not other.operator < (*this);
9256 }
9257
9262 bool operator>(const iter_impl& other) const
9263 {
9264 return not operator<=(other);
9265 }
9266
9271 bool operator>=(const iter_impl& other) const
9272 {
9273 return not operator<(other);
9274 }
9275
9281 {
9282 assert(m_object != nullptr);
9283
9284 switch (m_object->m_type)
9285 {
9286 case basic_json::value_t::object:
9287 {
9288 JSON_THROW(std::domain_error("cannot use offsets with object iterators"));
9289 }
9290
9291 case basic_json::value_t::array:
9292 {
9293 std::advance(m_it.array_iterator, i);
9294 break;
9295 }
9296
9297 default:
9298 {
9299 m_it.primitive_iterator += i;
9300 break;
9301 }
9302 }
9303
9304 return *this;
9305 }
9306
9312 {
9313 return operator+=(-i);
9314 }
9315
9321 {
9322 auto result = *this;
9323 result += i;
9324 return result;
9325 }
9326
9332 {
9333 auto result = *this;
9334 result -= i;
9335 return result;
9336 }
9337
9343 {
9344 assert(m_object != nullptr);
9345
9346 switch (m_object->m_type)
9347 {
9348 case basic_json::value_t::object:
9349 {
9350 JSON_THROW(std::domain_error("cannot use offsets with object iterators"));
9351 }
9352
9353 case basic_json::value_t::array:
9354 {
9355 return m_it.array_iterator - other.m_it.array_iterator;
9356 }
9357
9358 default:
9359 {
9360 return m_it.primitive_iterator - other.m_it.primitive_iterator;
9361 }
9362 }
9363 }
9364
9370 {
9371 assert(m_object != nullptr);
9372
9373 switch (m_object->m_type)
9374 {
9375 case basic_json::value_t::object:
9376 {
9377 JSON_THROW(std::domain_error("cannot use operator[] for object iterators"));
9378 }
9379
9380 case basic_json::value_t::array:
9381 {
9382 return *std::next(m_it.array_iterator, n);
9383 }
9384
9385 case basic_json::value_t::null:
9386 {
9387 JSON_THROW(std::out_of_range("cannot get value"));
9388 }
9389
9390 default:
9391 {
9392 if (m_it.primitive_iterator.get_value() == -n)
9393 {
9394 return *m_object;
9395 }
9396
9397 JSON_THROW(std::out_of_range("cannot get value"));
9398 }
9399 }
9400 }
9401
9406 typename object_t::key_type key() const
9407 {
9408 assert(m_object != nullptr);
9409
9410 if (m_object->is_object())
9411 {
9412 return m_it.object_iterator->first;
9413 }
9414
9415 JSON_THROW(std::domain_error("cannot use key() for non-object iterators"));
9416 }
9417
9423 {
9424 return operator*();
9425 }
9426
9427 private:
9429 pointer m_object = nullptr;
9431 internal_iterator m_it = internal_iterator();
9432 };
9433
9451 template<typename Base>
9452 class json_reverse_iterator : public std::reverse_iterator<Base>
9453 {
9454 public:
9456 using base_iterator = std::reverse_iterator<Base>;
9458 using reference = typename Base::reference;
9459
9461 json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
9462 : base_iterator(it)
9463 {}
9464
9467 : base_iterator(it)
9468 {}
9469
9472 {
9473 return base_iterator::operator++(1);
9474 }
9475
9478 {
9479 base_iterator::operator++();
9480 return *this;
9481 }
9482
9485 {
9486 return base_iterator::operator--(1);
9487 }
9488
9491 {
9492 base_iterator::operator--();
9493 return *this;
9494 }
9495
9498 {
9499 base_iterator::operator+=(i);
9500 return *this;
9501 }
9502
9505 {
9506 auto result = *this;
9507 result += i;
9508 return result;
9509 }
9510
9513 {
9514 auto result = *this;
9515 result -= i;
9516 return result;
9517 }
9518
9521 {
9522 return this->base() - other.base();
9523 }
9524
9527 {
9528 return *(this->operator+(n));
9529 }
9530
9532 typename object_t::key_type key() const
9533 {
9534 auto it = --this->base();
9535 return it.key();
9536 }
9537
9540 {
9541 auto it = --this->base();
9542 return it.operator * ();
9543 }
9544 };
9545
9546
9547 private:
9549 // lexer and parser //
9551
9559 class lexer
9560 {
9561 public:
9563 enum class token_type
9564 {
9565 uninitialized,
9566 literal_true,
9567 literal_false,
9568 literal_null,
9569 value_string,
9570 value_unsigned,
9571 value_integer,
9572 value_float,
9573 begin_array,
9574 begin_object,
9575 end_array,
9576 end_object,
9577 name_separator,
9578 value_separator,
9579 parse_error,
9580 end_of_input
9581 };
9582
9584 using lexer_char_t = unsigned char;
9585
9587 lexer(const lexer_char_t* buff, const size_t len) noexcept
9588 : m_content(buff)
9589 {
9590 assert(m_content != nullptr);
9591 m_start = m_cursor = m_content;
9592 m_limit = m_content + len;
9593 }
9594
9596 explicit lexer(std::istream& s)
9597 : m_stream(&s), m_line_buffer()
9598 {
9599 // immediately abort if stream is erroneous
9600 if (s.fail())
9601 {
9602 JSON_THROW(std::invalid_argument("stream error"));
9603 }
9604
9605 // fill buffer
9606 fill_line_buffer();
9607
9608 // skip UTF-8 byte-order mark
9609 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
9610 {
9611 m_line_buffer[0] = ' ';
9612 m_line_buffer[1] = ' ';
9613 m_line_buffer[2] = ' ';
9614 }
9615 }
9616
9617 // switch off unwanted functions (due to pointer members)
9618 lexer() = delete;
9619 lexer(const lexer&) = delete;
9620 lexer operator=(const lexer&) = delete;
9621
9645 static string_t to_unicode(const std::size_t codepoint1,
9646 const std::size_t codepoint2 = 0)
9647 {
9648 // calculate the code point from the given code points
9649 std::size_t codepoint = codepoint1;
9650
9651 // check if codepoint1 is a high surrogate
9652 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9653 {
9654 // check if codepoint2 is a low surrogate
9655 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9656 {
9657 codepoint =
9658 // high surrogate occupies the most significant 22 bits
9659 (codepoint1 << 10)
9660 // low surrogate occupies the least significant 15 bits
9661 + codepoint2
9662 // there is still the 0xD800, 0xDC00 and 0x10000 noise
9663 // in the result so we have to subtract with:
9664 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
9665 - 0x35FDC00;
9666 }
9667 else
9668 {
9669 JSON_THROW(std::invalid_argument("missing or wrong low surrogate"));
9670 }
9671 }
9672
9673 string_t result;
9674
9675 if (codepoint < 0x80)
9676 {
9677 // 1-byte characters: 0xxxxxxx (ASCII)
9678 result.append(1, static_cast<typename string_t::value_type>(codepoint));
9679 }
9680 else if (codepoint <= 0x7ff)
9681 {
9682 // 2-byte characters: 110xxxxx 10xxxxxx
9683 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9684 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9685 }
9686 else if (codepoint <= 0xffff)
9687 {
9688 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
9689 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9690 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9691 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9692 }
9693 else if (codepoint <= 0x10ffff)
9694 {
9695 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
9696 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9697 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9698 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9699 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9700 }
9701 else
9702 {
9703 JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid"));
9704 }
9705
9706 return result;
9707 }
9708
9710 static std::string token_type_name(const token_type t)
9711 {
9712 switch (t)
9713 {
9714 case token_type::uninitialized:
9715 return "<uninitialized>";
9716 case token_type::literal_true:
9717 return "true literal";
9718 case token_type::literal_false:
9719 return "false literal";
9720 case token_type::literal_null:
9721 return "null literal";
9722 case token_type::value_string:
9723 return "string literal";
9724 case lexer::token_type::value_unsigned:
9725 case lexer::token_type::value_integer:
9726 case lexer::token_type::value_float:
9727 return "number literal";
9728 case token_type::begin_array:
9729 return "'['";
9730 case token_type::begin_object:
9731 return "'{'";
9732 case token_type::end_array:
9733 return "']'";
9734 case token_type::end_object:
9735 return "'}'";
9736 case token_type::name_separator:
9737 return "':'";
9738 case token_type::value_separator:
9739 return "','";
9740 case token_type::parse_error:
9741 return "<parse error>";
9742 case token_type::end_of_input:
9743 return "end of input";
9744 default:
9745 {
9746 // catch non-enum values
9747 return "unknown token"; // LCOV_EXCL_LINE
9748 }
9749 }
9750 }
9751
9773 token_type scan()
9774 {
9775 while (true)
9776 {
9777 // pointer for backtracking information
9778 m_marker = nullptr;
9779
9780 // remember the begin of the token
9781 m_start = m_cursor;
9782 assert(m_start != nullptr);
9783
9784
9785 {
9786 lexer_char_t yych;
9787 unsigned int yyaccept = 0;
9788 static const unsigned char yybm[] = {
9789 0, 0, 0, 0, 0, 0, 0, 0,
9790 0, 32, 32, 0, 0, 32, 0, 0,
9791 0, 0, 0, 0, 0, 0, 0, 0,
9792 0, 0, 0, 0, 0, 0, 0, 0,
9793 160, 128, 0, 128, 128, 128, 128, 128,
9794 128, 128, 128, 128, 128, 128, 128, 128,
9795 192, 192, 192, 192, 192, 192, 192, 192,
9796 192, 192, 128, 128, 128, 128, 128, 128,
9797 128, 128, 128, 128, 128, 128, 128, 128,
9798 128, 128, 128, 128, 128, 128, 128, 128,
9799 128, 128, 128, 128, 128, 128, 128, 128,
9800 128, 128, 128, 128, 0, 128, 128, 128,
9801 128, 128, 128, 128, 128, 128, 128, 128,
9802 128, 128, 128, 128, 128, 128, 128, 128,
9803 128, 128, 128, 128, 128, 128, 128, 128,
9804 128, 128, 128, 128, 128, 128, 128, 128,
9805 0, 0, 0, 0, 0, 0, 0, 0,
9806 0, 0, 0, 0, 0, 0, 0, 0,
9807 0, 0, 0, 0, 0, 0, 0, 0,
9808 0, 0, 0, 0, 0, 0, 0, 0,
9809 0, 0, 0, 0, 0, 0, 0, 0,
9810 0, 0, 0, 0, 0, 0, 0, 0,
9811 0, 0, 0, 0, 0, 0, 0, 0,
9812 0, 0, 0, 0, 0, 0, 0, 0,
9813 0, 0, 0, 0, 0, 0, 0, 0,
9814 0, 0, 0, 0, 0, 0, 0, 0,
9815 0, 0, 0, 0, 0, 0, 0, 0,
9816 0, 0, 0, 0, 0, 0, 0, 0,
9817 0, 0, 0, 0, 0, 0, 0, 0,
9818 0, 0, 0, 0, 0, 0, 0, 0,
9819 0, 0, 0, 0, 0, 0, 0, 0,
9820 0, 0, 0, 0, 0, 0, 0, 0,
9821 };
9822 if ((m_limit - m_cursor) < 5) fill_line_buffer(5); // LCOV_EXCL_LINE
9823 yych = *m_cursor;
9824 if (yybm[0+yych] & 32) {
9825 goto basic_json_parser_4;
9826 }
9827 if (yych <= '[') {
9828 if (yych <= '-') {
9829 if (yych <= '"') {
9830 if (yych <= 0x00) goto basic_json_parser_1;
9831 if (yych <= '!') goto basic_json_parser_2;
9832 goto basic_json_parser_5;
9833 } else {
9834 if (yych <= '+') goto basic_json_parser_2;
9835 if (yych <= ',') goto basic_json_parser_6;
9836 goto basic_json_parser_7;
9837 }
9838 } else {
9839 if (yych <= '9') {
9840 if (yych <= '/') goto basic_json_parser_2;
9841 if (yych <= '0') goto basic_json_parser_8;
9842 goto basic_json_parser_10;
9843 } else {
9844 if (yych <= ':') goto basic_json_parser_11;
9845 if (yych <= 'Z') goto basic_json_parser_2;
9846 goto basic_json_parser_12;
9847 }
9848 }
9849 } else {
9850 if (yych <= 'n') {
9851 if (yych <= 'e') {
9852 if (yych == ']') goto basic_json_parser_13;
9853 goto basic_json_parser_2;
9854 } else {
9855 if (yych <= 'f') goto basic_json_parser_14;
9856 if (yych <= 'm') goto basic_json_parser_2;
9857 goto basic_json_parser_15;
9858 }
9859 } else {
9860 if (yych <= 'z') {
9861 if (yych == 't') goto basic_json_parser_16;
9862 goto basic_json_parser_2;
9863 } else {
9864 if (yych <= '{') goto basic_json_parser_17;
9865 if (yych == '}') goto basic_json_parser_18;
9866 goto basic_json_parser_2;
9867 }
9868 }
9869 }
9870basic_json_parser_1:
9871 ++m_cursor;
9872 { last_token_type = token_type::end_of_input; break; }
9873basic_json_parser_2:
9874 ++m_cursor;
9875basic_json_parser_3:
9876 { last_token_type = token_type::parse_error; break; }
9877basic_json_parser_4:
9878 ++m_cursor;
9879 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
9880 yych = *m_cursor;
9881 if (yybm[0+yych] & 32) {
9882 goto basic_json_parser_4;
9883 }
9884 { continue; }
9885basic_json_parser_5:
9886 yyaccept = 0;
9887 yych = *(m_marker = ++m_cursor);
9888 if (yych <= 0x1F) goto basic_json_parser_3;
9889 if (yych <= 0x7F) goto basic_json_parser_20;
9890 if (yych <= 0xC1) goto basic_json_parser_3;
9891 if (yych <= 0xF4) goto basic_json_parser_20;
9892 goto basic_json_parser_3;
9893basic_json_parser_6:
9894 ++m_cursor;
9895 { last_token_type = token_type::value_separator; break; }
9896basic_json_parser_7:
9897 yych = *++m_cursor;
9898 if (yych <= '/') goto basic_json_parser_3;
9899 if (yych <= '0') goto basic_json_parser_31;
9900 if (yych <= '9') goto basic_json_parser_33;
9901 goto basic_json_parser_3;
9902basic_json_parser_8:
9903 yyaccept = 1;
9904 yych = *(m_marker = ++m_cursor);
9905 if (yych <= '9') {
9906 if (yych == '.') goto basic_json_parser_34;
9907 if (yych >= '0') goto basic_json_parser_35;
9908 } else {
9909 if (yych <= 'E') {
9910 if (yych >= 'E') goto basic_json_parser_37;
9911 } else {
9912 if (yych == 'e') goto basic_json_parser_37;
9913 }
9914 }
9915basic_json_parser_9:
9916 { last_token_type = token_type::value_unsigned; break; }
9917basic_json_parser_10:
9918 yyaccept = 1;
9919 m_marker = ++m_cursor;
9920 if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE
9921 yych = *m_cursor;
9922 if (yybm[0+yych] & 64) {
9923 goto basic_json_parser_10;
9924 }
9925 if (yych <= 'D') {
9926 if (yych == '.') goto basic_json_parser_34;
9927 goto basic_json_parser_9;
9928 } else {
9929 if (yych <= 'E') goto basic_json_parser_37;
9930 if (yych == 'e') goto basic_json_parser_37;
9931 goto basic_json_parser_9;
9932 }
9933basic_json_parser_11:
9934 ++m_cursor;
9935 { last_token_type = token_type::name_separator; break; }
9936basic_json_parser_12:
9937 ++m_cursor;
9938 { last_token_type = token_type::begin_array; break; }
9939basic_json_parser_13:
9940 ++m_cursor;
9941 { last_token_type = token_type::end_array; break; }
9942basic_json_parser_14:
9943 yyaccept = 0;
9944 yych = *(m_marker = ++m_cursor);
9945 if (yych == 'a') goto basic_json_parser_38;
9946 goto basic_json_parser_3;
9947basic_json_parser_15:
9948 yyaccept = 0;
9949 yych = *(m_marker = ++m_cursor);
9950 if (yych == 'u') goto basic_json_parser_39;
9951 goto basic_json_parser_3;
9952basic_json_parser_16:
9953 yyaccept = 0;
9954 yych = *(m_marker = ++m_cursor);
9955 if (yych == 'r') goto basic_json_parser_40;
9956 goto basic_json_parser_3;
9957basic_json_parser_17:
9958 ++m_cursor;
9959 { last_token_type = token_type::begin_object; break; }
9960basic_json_parser_18:
9961 ++m_cursor;
9962 { last_token_type = token_type::end_object; break; }
9963basic_json_parser_19:
9964 ++m_cursor;
9965 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
9966 yych = *m_cursor;
9967basic_json_parser_20:
9968 if (yybm[0+yych] & 128) {
9969 goto basic_json_parser_19;
9970 }
9971 if (yych <= 0xE0) {
9972 if (yych <= '\\') {
9973 if (yych <= 0x1F) goto basic_json_parser_21;
9974 if (yych <= '"') goto basic_json_parser_22;
9975 goto basic_json_parser_23;
9976 } else {
9977 if (yych <= 0xC1) goto basic_json_parser_21;
9978 if (yych <= 0xDF) goto basic_json_parser_24;
9979 goto basic_json_parser_25;
9980 }
9981 } else {
9982 if (yych <= 0xEF) {
9983 if (yych == 0xED) goto basic_json_parser_27;
9984 goto basic_json_parser_26;
9985 } else {
9986 if (yych <= 0xF0) goto basic_json_parser_28;
9987 if (yych <= 0xF3) goto basic_json_parser_29;
9988 if (yych <= 0xF4) goto basic_json_parser_30;
9989 }
9990 }
9991basic_json_parser_21:
9992 m_cursor = m_marker;
9993 if (yyaccept <= 1) {
9994 if (yyaccept == 0) {
9995 goto basic_json_parser_3;
9996 } else {
9997 goto basic_json_parser_9;
9998 }
9999 } else {
10000 if (yyaccept == 2) {
10001 goto basic_json_parser_32;
10002 } else {
10003 goto basic_json_parser_43;
10004 }
10005 }
10006basic_json_parser_22:
10007 ++m_cursor;
10008 { last_token_type = token_type::value_string; break; }
10009basic_json_parser_23:
10010 ++m_cursor;
10011 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10012 yych = *m_cursor;
10013 if (yych <= 'e') {
10014 if (yych <= '/') {
10015 if (yych == '"') goto basic_json_parser_19;
10016 if (yych <= '.') goto basic_json_parser_21;
10017 goto basic_json_parser_19;
10018 } else {
10019 if (yych <= '\\') {
10020 if (yych <= '[') goto basic_json_parser_21;
10021 goto basic_json_parser_19;
10022 } else {
10023 if (yych == 'b') goto basic_json_parser_19;
10024 goto basic_json_parser_21;
10025 }
10026 }
10027 } else {
10028 if (yych <= 'q') {
10029 if (yych <= 'f') goto basic_json_parser_19;
10030 if (yych == 'n') goto basic_json_parser_19;
10031 goto basic_json_parser_21;
10032 } else {
10033 if (yych <= 's') {
10034 if (yych <= 'r') goto basic_json_parser_19;
10035 goto basic_json_parser_21;
10036 } else {
10037 if (yych <= 't') goto basic_json_parser_19;
10038 if (yych <= 'u') goto basic_json_parser_41;
10039 goto basic_json_parser_21;
10040 }
10041 }
10042 }
10043basic_json_parser_24:
10044 ++m_cursor;
10045 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10046 yych = *m_cursor;
10047 if (yych <= 0x7F) goto basic_json_parser_21;
10048 if (yych <= 0xBF) goto basic_json_parser_19;
10049 goto basic_json_parser_21;
10050basic_json_parser_25:
10051 ++m_cursor;
10052 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10053 yych = *m_cursor;
10054 if (yych <= 0x9F) goto basic_json_parser_21;
10055 if (yych <= 0xBF) goto basic_json_parser_24;
10056 goto basic_json_parser_21;
10057basic_json_parser_26:
10058 ++m_cursor;
10059 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10060 yych = *m_cursor;
10061 if (yych <= 0x7F) goto basic_json_parser_21;
10062 if (yych <= 0xBF) goto basic_json_parser_24;
10063 goto basic_json_parser_21;
10064basic_json_parser_27:
10065 ++m_cursor;
10066 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10067 yych = *m_cursor;
10068 if (yych <= 0x7F) goto basic_json_parser_21;
10069 if (yych <= 0x9F) goto basic_json_parser_24;
10070 goto basic_json_parser_21;
10071basic_json_parser_28:
10072 ++m_cursor;
10073 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10074 yych = *m_cursor;
10075 if (yych <= 0x8F) goto basic_json_parser_21;
10076 if (yych <= 0xBF) goto basic_json_parser_26;
10077 goto basic_json_parser_21;
10078basic_json_parser_29:
10079 ++m_cursor;
10080 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10081 yych = *m_cursor;
10082 if (yych <= 0x7F) goto basic_json_parser_21;
10083 if (yych <= 0xBF) goto basic_json_parser_26;
10084 goto basic_json_parser_21;
10085basic_json_parser_30:
10086 ++m_cursor;
10087 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10088 yych = *m_cursor;
10089 if (yych <= 0x7F) goto basic_json_parser_21;
10090 if (yych <= 0x8F) goto basic_json_parser_26;
10091 goto basic_json_parser_21;
10092basic_json_parser_31:
10093 yyaccept = 2;
10094 yych = *(m_marker = ++m_cursor);
10095 if (yych <= '9') {
10096 if (yych == '.') goto basic_json_parser_34;
10097 if (yych >= '0') goto basic_json_parser_35;
10098 } else {
10099 if (yych <= 'E') {
10100 if (yych >= 'E') goto basic_json_parser_37;
10101 } else {
10102 if (yych == 'e') goto basic_json_parser_37;
10103 }
10104 }
10105basic_json_parser_32:
10106 { last_token_type = token_type::value_integer; break; }
10107basic_json_parser_33:
10108 yyaccept = 2;
10109 m_marker = ++m_cursor;
10110 if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE
10111 yych = *m_cursor;
10112 if (yych <= '9') {
10113 if (yych == '.') goto basic_json_parser_34;
10114 if (yych <= '/') goto basic_json_parser_32;
10115 goto basic_json_parser_33;
10116 } else {
10117 if (yych <= 'E') {
10118 if (yych <= 'D') goto basic_json_parser_32;
10119 goto basic_json_parser_37;
10120 } else {
10121 if (yych == 'e') goto basic_json_parser_37;
10122 goto basic_json_parser_32;
10123 }
10124 }
10125basic_json_parser_34:
10126 yych = *++m_cursor;
10127 if (yych <= '/') goto basic_json_parser_21;
10128 if (yych <= '9') goto basic_json_parser_42;
10129 goto basic_json_parser_21;
10130basic_json_parser_35:
10131 ++m_cursor;
10132 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10133 yych = *m_cursor;
10134 if (yych <= '/') goto basic_json_parser_36;
10135 if (yych <= '9') goto basic_json_parser_35;
10136basic_json_parser_36:
10137 { last_token_type = token_type::parse_error; break; }
10138basic_json_parser_37:
10139 yych = *++m_cursor;
10140 if (yych <= ',') {
10141 if (yych == '+') goto basic_json_parser_44;
10142 goto basic_json_parser_21;
10143 } else {
10144 if (yych <= '-') goto basic_json_parser_44;
10145 if (yych <= '/') goto basic_json_parser_21;
10146 if (yych <= '9') goto basic_json_parser_45;
10147 goto basic_json_parser_21;
10148 }
10149basic_json_parser_38:
10150 yych = *++m_cursor;
10151 if (yych == 'l') goto basic_json_parser_46;
10152 goto basic_json_parser_21;
10153basic_json_parser_39:
10154 yych = *++m_cursor;
10155 if (yych == 'l') goto basic_json_parser_47;
10156 goto basic_json_parser_21;
10157basic_json_parser_40:
10158 yych = *++m_cursor;
10159 if (yych == 'u') goto basic_json_parser_48;
10160 goto basic_json_parser_21;
10161basic_json_parser_41:
10162 ++m_cursor;
10163 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10164 yych = *m_cursor;
10165 if (yych <= '@') {
10166 if (yych <= '/') goto basic_json_parser_21;
10167 if (yych <= '9') goto basic_json_parser_49;
10168 goto basic_json_parser_21;
10169 } else {
10170 if (yych <= 'F') goto basic_json_parser_49;
10171 if (yych <= '`') goto basic_json_parser_21;
10172 if (yych <= 'f') goto basic_json_parser_49;
10173 goto basic_json_parser_21;
10174 }
10175basic_json_parser_42:
10176 yyaccept = 3;
10177 m_marker = ++m_cursor;
10178 if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE
10179 yych = *m_cursor;
10180 if (yych <= 'D') {
10181 if (yych <= '/') goto basic_json_parser_43;
10182 if (yych <= '9') goto basic_json_parser_42;
10183 } else {
10184 if (yych <= 'E') goto basic_json_parser_37;
10185 if (yych == 'e') goto basic_json_parser_37;
10186 }
10187basic_json_parser_43:
10188 { last_token_type = token_type::value_float; break; }
10189basic_json_parser_44:
10190 yych = *++m_cursor;
10191 if (yych <= '/') goto basic_json_parser_21;
10192 if (yych >= ':') goto basic_json_parser_21;
10193basic_json_parser_45:
10194 ++m_cursor;
10195 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10196 yych = *m_cursor;
10197 if (yych <= '/') goto basic_json_parser_43;
10198 if (yych <= '9') goto basic_json_parser_45;
10199 goto basic_json_parser_43;
10200basic_json_parser_46:
10201 yych = *++m_cursor;
10202 if (yych == 's') goto basic_json_parser_50;
10203 goto basic_json_parser_21;
10204basic_json_parser_47:
10205 yych = *++m_cursor;
10206 if (yych == 'l') goto basic_json_parser_51;
10207 goto basic_json_parser_21;
10208basic_json_parser_48:
10209 yych = *++m_cursor;
10210 if (yych == 'e') goto basic_json_parser_52;
10211 goto basic_json_parser_21;
10212basic_json_parser_49:
10213 ++m_cursor;
10214 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10215 yych = *m_cursor;
10216 if (yych <= '@') {
10217 if (yych <= '/') goto basic_json_parser_21;
10218 if (yych <= '9') goto basic_json_parser_53;
10219 goto basic_json_parser_21;
10220 } else {
10221 if (yych <= 'F') goto basic_json_parser_53;
10222 if (yych <= '`') goto basic_json_parser_21;
10223 if (yych <= 'f') goto basic_json_parser_53;
10224 goto basic_json_parser_21;
10225 }
10226basic_json_parser_50:
10227 yych = *++m_cursor;
10228 if (yych == 'e') goto basic_json_parser_54;
10229 goto basic_json_parser_21;
10230basic_json_parser_51:
10231 ++m_cursor;
10232 { last_token_type = token_type::literal_null; break; }
10233basic_json_parser_52:
10234 ++m_cursor;
10235 { last_token_type = token_type::literal_true; break; }
10236basic_json_parser_53:
10237 ++m_cursor;
10238 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10239 yych = *m_cursor;
10240 if (yych <= '@') {
10241 if (yych <= '/') goto basic_json_parser_21;
10242 if (yych <= '9') goto basic_json_parser_55;
10243 goto basic_json_parser_21;
10244 } else {
10245 if (yych <= 'F') goto basic_json_parser_55;
10246 if (yych <= '`') goto basic_json_parser_21;
10247 if (yych <= 'f') goto basic_json_parser_55;
10248 goto basic_json_parser_21;
10249 }
10250basic_json_parser_54:
10251 ++m_cursor;
10252 { last_token_type = token_type::literal_false; break; }
10253basic_json_parser_55:
10254 ++m_cursor;
10255 if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10256 yych = *m_cursor;
10257 if (yych <= '@') {
10258 if (yych <= '/') goto basic_json_parser_21;
10259 if (yych <= '9') goto basic_json_parser_19;
10260 goto basic_json_parser_21;
10261 } else {
10262 if (yych <= 'F') goto basic_json_parser_19;
10263 if (yych <= '`') goto basic_json_parser_21;
10264 if (yych <= 'f') goto basic_json_parser_19;
10265 goto basic_json_parser_21;
10266 }
10267 }
10268
10269 }
10270
10271 return last_token_type;
10272 }
10273
10302 void fill_line_buffer(size_t n = 0)
10303 {
10304 // if line buffer is used, m_content points to its data
10305 assert(m_line_buffer.empty()
10306 or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
10307
10308 // if line buffer is used, m_limit is set past the end of its data
10309 assert(m_line_buffer.empty()
10310 or m_limit == m_content + m_line_buffer.size());
10311
10312 // pointer relationships
10313 assert(m_content <= m_start);
10314 assert(m_start <= m_cursor);
10315 assert(m_cursor <= m_limit);
10316 assert(m_marker == nullptr or m_marker <= m_limit);
10317
10318 // number of processed characters (p)
10319 const auto num_processed_chars = static_cast<size_t>(m_start - m_content);
10320 // offset for m_marker wrt. to m_start
10321 const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
10322 // number of unprocessed characters (u)
10323 const auto offset_cursor = m_cursor - m_start;
10324
10325 // no stream is used or end of file is reached
10326 if (m_stream == nullptr or m_stream->eof())
10327 {
10328 // m_start may or may not be pointing into m_line_buffer at
10329 // this point. We trust the standard library to do the right
10330 // thing. See http://stackoverflow.com/q/28142011/266378
10331 m_line_buffer.assign(m_start, m_limit);
10332
10333 // append n characters to make sure that there is sufficient
10334 // space between m_cursor and m_limit
10335 m_line_buffer.append(1, '\x00');
10336 if (n > 0)
10337 {
10338 m_line_buffer.append(n - 1, '\x01');
10339 }
10340 }
10341 else
10342 {
10343 // delete processed characters from line buffer
10344 m_line_buffer.erase(0, num_processed_chars);
10345 // read next line from input stream
10346 m_line_buffer_tmp.clear();
10347 std::getline(*m_stream, m_line_buffer_tmp, '\n');
10348
10349 // add line with newline symbol to the line buffer
10350 m_line_buffer += m_line_buffer_tmp;
10351 m_line_buffer.push_back('\n');
10352 }
10353
10354 // set pointers
10355 m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
10356 assert(m_content != nullptr);
10357 m_start = m_content;
10358 m_marker = m_start + offset_marker;
10359 m_cursor = m_start + offset_cursor;
10360 m_limit = m_start + m_line_buffer.size();
10361 }
10362
10364 string_t get_token_string() const
10365 {
10366 assert(m_start != nullptr);
10367 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10368 static_cast<size_t>(m_cursor - m_start));
10369 }
10370
10428 string_t get_string() const
10429 {
10430 assert(m_cursor - m_start >= 2);
10431
10432 string_t result;
10433 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10434
10435 // iterate the result between the quotes
10436 for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10437 {
10438 // find next escape character
10439 auto e = std::find(i, m_cursor - 1, '\\');
10440 if (e != i)
10441 {
10442 // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
10443 for (auto k = i; k < e; k++)
10444 {
10445 result.push_back(static_cast<typename string_t::value_type>(*k));
10446 }
10447 i = e - 1; // -1 because of ++i
10448 }
10449 else
10450 {
10451 // processing escaped character
10452 // read next character
10453 ++i;
10454
10455 switch (*i)
10456 {
10457 // the default escapes
10458 case 't':
10459 {
10460 result += "\t";
10461 break;
10462 }
10463 case 'b':
10464 {
10465 result += "\b";
10466 break;
10467 }
10468 case 'f':
10469 {
10470 result += "\f";
10471 break;
10472 }
10473 case 'n':
10474 {
10475 result += "\n";
10476 break;
10477 }
10478 case 'r':
10479 {
10480 result += "\r";
10481 break;
10482 }
10483 case '\\':
10484 {
10485 result += "\\";
10486 break;
10487 }
10488 case '/':
10489 {
10490 result += "/";
10491 break;
10492 }
10493 case '"':
10494 {
10495 result += "\"";
10496 break;
10497 }
10498
10499 // unicode
10500 case 'u':
10501 {
10502 // get code xxxx from uxxxx
10503 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10504 4).c_str(), nullptr, 16);
10505
10506 // check if codepoint is a high surrogate
10507 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10508 {
10509 // make sure there is a subsequent unicode
10510 if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
10511 {
10512 JSON_THROW(std::invalid_argument("missing low surrogate"));
10513 }
10514
10515 // get code yyyy from uxxxx\uyyyy
10516 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10517 (i + 7), 4).c_str(), nullptr, 16);
10518 result += to_unicode(codepoint, codepoint2);
10519 // skip the next 10 characters (xxxx\uyyyy)
10520 i += 10;
10521 }
10522 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10523 {
10524 // we found a lone low surrogate
10525 JSON_THROW(std::invalid_argument("missing high surrogate"));
10526 }
10527 else
10528 {
10529 // add unicode character(s)
10530 result += to_unicode(codepoint);
10531 // skip the next four characters (xxxx)
10532 i += 4;
10533 }
10534 break;
10535 }
10536 }
10537 }
10538 }
10539
10540 return result;
10541 }
10542
10543
10554 {
10555 public:
10556 strtonum(const char* start, const char* end)
10557 : m_start(start), m_end(end)
10558 {}
10559
10566 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
10567 bool to(T& val) const
10568 {
10569 return parse(val, std::is_integral<T>());
10570 }
10571
10572 private:
10573 const char* const m_start = nullptr;
10574 const char* const m_end = nullptr;
10575
10576 // floating-point conversion
10577
10578 // overloaded wrappers for strtod/strtof/strtold
10579 // that will be called from parse<floating_point_t>
10580 static void strtof(float& f, const char* str, char** endptr)
10581 {
10582 f = std::strtof(str, endptr);
10583 }
10584
10585 static void strtof(double& f, const char* str, char** endptr)
10586 {
10587 f = std::strtod(str, endptr);
10588 }
10589
10590 static void strtof(long double& f, const char* str, char** endptr)
10591 {
10592 f = std::strtold(str, endptr);
10593 }
10594
10595 template<typename T>
10596 bool parse(T& value, /*is_integral=*/std::false_type) const
10597 {
10598 // replace decimal separator with locale-specific version,
10599 // when necessary; data will point to either the original
10600 // string, or buf, or tempstr containing the fixed string.
10601 std::string tempstr;
10602 std::array<char, 64> buf;
10603 const size_t len = static_cast<size_t>(m_end - m_start);
10604
10605 // lexer will reject empty numbers
10606 assert(len > 0);
10607
10608 // since dealing with strtod family of functions, we're
10609 // getting the decimal point char from the C locale facilities
10610 // instead of C++'s numpunct facet of the current std::locale
10611 const auto loc = localeconv();
10612 assert(loc != nullptr);
10613 const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];
10614
10615 const char* data = m_start;
10616
10617 if (decimal_point_char != '.')
10618 {
10619 const size_t ds_pos = static_cast<size_t>(std::find(m_start, m_end, '.') - m_start);
10620
10621 if (ds_pos != len)
10622 {
10623 // copy the data into the local buffer or tempstr, if
10624 // buffer is too small; replace decimal separator, and
10625 // update data to point to the modified bytes
10626 if ((len + 1) < buf.size())
10627 {
10628 std::copy(m_start, m_end, buf.begin());
10629 buf[len] = 0;
10630 buf[ds_pos] = decimal_point_char;
10631 data = buf.data();
10632 }
10633 else
10634 {
10635 tempstr.assign(m_start, m_end);
10636 tempstr[ds_pos] = decimal_point_char;
10637 data = tempstr.c_str();
10638 }
10639 }
10640 }
10641
10642 char* endptr = nullptr;
10643 value = 0;
10644 // this calls appropriate overload depending on T
10645 strtof(value, data, &endptr);
10646
10647 // parsing was successful iff strtof parsed exactly the number
10648 // of characters determined by the lexer (len)
10649 const bool ok = (endptr == (data + len));
10650
10651 if (ok and (value == static_cast<T>(0.0)) and (*data == '-'))
10652 {
10653 // some implementations forget to negate the zero
10654 value = -0.0;
10655 }
10656
10657 return ok;
10658 }
10659
10660 // integral conversion
10661
10662 signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const
10663 {
10664 return std::strtoll(m_start, endptr, 10);
10665 }
10666
10667 unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const
10668 {
10669 return std::strtoull(m_start, endptr, 10);
10670 }
10671
10672 template<typename T>
10673 bool parse(T& value, /*is_integral=*/std::true_type) const
10674 {
10675 char* endptr = nullptr;
10676 errno = 0; // these are thread-local
10677 const auto x = parse_integral(&endptr, std::is_signed<T>());
10678
10679 // called right overload?
10680 static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(), "");
10681
10682 value = static_cast<T>(x);
10683
10684 return (x == static_cast<decltype(x)>(value)) // x fits into destination T
10685 and (x < 0) == (value < 0) // preserved sign
10686 //and ((x != 0) or is_integral()) // strto[u]ll did nto fail
10687 and (errno == 0) // strto[u]ll did not overflow
10688 and (m_start < m_end) // token was not empty
10689 and (endptr == m_end); // parsed entire token exactly
10690 }
10691 };
10692
10712 bool get_number(basic_json& result, const token_type token) const
10713 {
10714 assert(m_start != nullptr);
10715 assert(m_start < m_cursor);
10716 assert((token == token_type::value_unsigned) or
10717 (token == token_type::value_integer) or
10718 (token == token_type::value_float));
10719
10720 strtonum num_converter(reinterpret_cast<const char*>(m_start),
10721 reinterpret_cast<const char*>(m_cursor));
10722
10723 switch (token)
10724 {
10725 case lexer::token_type::value_unsigned:
10726 {
10727 number_unsigned_t val;
10728 if (num_converter.to(val))
10729 {
10730 // parsing successful
10731 result.m_type = value_t::number_unsigned;
10732 result.m_value = val;
10733 return true;
10734 }
10735 break;
10736 }
10737
10738 case lexer::token_type::value_integer:
10739 {
10740 number_integer_t val;
10741 if (num_converter.to(val))
10742 {
10743 // parsing successful
10744 result.m_type = value_t::number_integer;
10745 result.m_value = val;
10746 return true;
10747 }
10748 break;
10749 }
10750
10751 default:
10752 {
10753 break;
10754 }
10755 }
10756
10757 // parse float (either explicitly or because a previous conversion
10758 // failed)
10759 number_float_t val;
10760 if (num_converter.to(val))
10761 {
10762 // parsing successful
10763 result.m_type = value_t::number_float;
10764 result.m_value = val;
10765
10766 // replace infinity and NAN by null
10767 if (not std::isfinite(result.m_value.number_float))
10768 {
10769 result.m_type = value_t::null;
10770 result.m_value = basic_json::json_value();
10771 }
10772
10773 return true;
10774 }
10775
10776 // couldn't parse number in any format
10777 return false;
10778 }
10779
10780 private:
10782 std::istream* m_stream = nullptr;
10784 string_t m_line_buffer {};
10786 string_t m_line_buffer_tmp {};
10788 const lexer_char_t* m_content = nullptr;
10790 const lexer_char_t* m_start = nullptr;
10792 const lexer_char_t* m_marker = nullptr;
10794 const lexer_char_t* m_cursor = nullptr;
10796 const lexer_char_t* m_limit = nullptr;
10798 token_type last_token_type = token_type::end_of_input;
10799 };
10800
10806 class parser
10807 {
10808 public:
10810 parser(const char* buff, const parser_callback_t cb = nullptr)
10811 : callback(cb),
10812 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10813 {}
10814
10816 parser(std::istream& is, const parser_callback_t cb = nullptr)
10817 : callback(cb), m_lexer(is)
10818 {}
10819
10821 template<class IteratorType, typename std::enable_if<
10822 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10823 , int>::type
10824 = 0>
10825 parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
10826 : callback(cb),
10827 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10828 static_cast<size_t>(std::distance(first, last)))
10829 {}
10830
10832 basic_json parse()
10833 {
10834 // read first token
10835 get_token();
10836
10837 basic_json result = parse_internal(true);
10838 result.assert_invariant();
10839
10840 expect(lexer::token_type::end_of_input);
10841
10842 // return parser result and replace it with null in case the
10843 // top-level value was discarded by the callback function
10844 return result.is_discarded() ? basic_json() : std::move(result);
10845 }
10846
10847 private:
10849 basic_json parse_internal(bool keep)
10850 {
10851 auto result = basic_json(value_t::discarded);
10852
10853 switch (last_token)
10854 {
10855 case lexer::token_type::begin_object:
10856 {
10857 if (keep and (not callback
10858 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10859 {
10860 // explicitly set result to object to cope with {}
10861 result.m_type = value_t::object;
10862 result.m_value = value_t::object;
10863 }
10864
10865 // read next token
10866 get_token();
10867
10868 // closing } -> we are done
10869 if (last_token == lexer::token_type::end_object)
10870 {
10871 get_token();
10872 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10873 {
10874 result = basic_json(value_t::discarded);
10875 }
10876 return result;
10877 }
10878
10879 // no comma is expected here
10880 unexpect(lexer::token_type::value_separator);
10881
10882 // otherwise: parse key-value pairs
10883 do
10884 {
10885 // ugly, but could be fixed with loop reorganization
10886 if (last_token == lexer::token_type::value_separator)
10887 {
10888 get_token();
10889 }
10890
10891 // store key
10892 expect(lexer::token_type::value_string);
10893 const auto key = m_lexer.get_string();
10894
10895 bool keep_tag = false;
10896 if (keep)
10897 {
10898 if (callback)
10899 {
10900 basic_json k(key);
10901 keep_tag = callback(depth, parse_event_t::key, k);
10902 }
10903 else
10904 {
10905 keep_tag = true;
10906 }
10907 }
10908
10909 // parse separator (:)
10910 get_token();
10911 expect(lexer::token_type::name_separator);
10912
10913 // parse and add value
10914 get_token();
10915 auto value = parse_internal(keep);
10916 if (keep and keep_tag and not value.is_discarded())
10917 {
10918 result[key] = std::move(value);
10919 }
10920 }
10921 while (last_token == lexer::token_type::value_separator);
10922
10923 // closing }
10924 expect(lexer::token_type::end_object);
10925 get_token();
10926 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10927 {
10928 result = basic_json(value_t::discarded);
10929 }
10930
10931 return result;
10932 }
10933
10934 case lexer::token_type::begin_array:
10935 {
10936 if (keep and (not callback
10937 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10938 {
10939 // explicitly set result to object to cope with []
10940 result.m_type = value_t::array;
10941 result.m_value = value_t::array;
10942 }
10943
10944 // read next token
10945 get_token();
10946
10947 // closing ] -> we are done
10948 if (last_token == lexer::token_type::end_array)
10949 {
10950 get_token();
10951 if (callback and not callback(--depth, parse_event_t::array_end, result))
10952 {
10953 result = basic_json(value_t::discarded);
10954 }
10955 return result;
10956 }
10957
10958 // no comma is expected here
10959 unexpect(lexer::token_type::value_separator);
10960
10961 // otherwise: parse values
10962 do
10963 {
10964 // ugly, but could be fixed with loop reorganization
10965 if (last_token == lexer::token_type::value_separator)
10966 {
10967 get_token();
10968 }
10969
10970 // parse value
10971 auto value = parse_internal(keep);
10972 if (keep and not value.is_discarded())
10973 {
10974 result.push_back(std::move(value));
10975 }
10976 }
10977 while (last_token == lexer::token_type::value_separator);
10978
10979 // closing ]
10980 expect(lexer::token_type::end_array);
10981 get_token();
10982 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10983 {
10984 result = basic_json(value_t::discarded);
10985 }
10986
10987 return result;
10988 }
10989
10990 case lexer::token_type::literal_null:
10991 {
10992 get_token();
10993 result.m_type = value_t::null;
10994 break;
10995 }
10996
10997 case lexer::token_type::value_string:
10998 {
10999 const auto s = m_lexer.get_string();
11000 get_token();
11001 result = basic_json(s);
11002 break;
11003 }
11004
11005 case lexer::token_type::literal_true:
11006 {
11007 get_token();
11008 result.m_type = value_t::boolean;
11009 result.m_value = true;
11010 break;
11011 }
11012
11013 case lexer::token_type::literal_false:
11014 {
11015 get_token();
11016 result.m_type = value_t::boolean;
11017 result.m_value = false;
11018 break;
11019 }
11020
11021 case lexer::token_type::value_unsigned:
11022 case lexer::token_type::value_integer:
11023 case lexer::token_type::value_float:
11024 {
11025 m_lexer.get_number(result, last_token);
11026 get_token();
11027 break;
11028 }
11029
11030 default:
11031 {
11032 // the last token was unexpected
11033 unexpect(last_token);
11034 }
11035 }
11036
11037 if (keep and callback and not callback(depth, parse_event_t::value, result))
11038 {
11039 result = basic_json(value_t::discarded);
11040 }
11041 return result;
11042 }
11043
11045 typename lexer::token_type get_token()
11046 {
11047 last_token = m_lexer.scan();
11048 return last_token;
11049 }
11050
11051 void expect(typename lexer::token_type t) const
11052 {
11053 if (t != last_token)
11054 {
11055 std::string error_msg = "parse error - unexpected ";
11056 error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
11057 "'") :
11058 lexer::token_type_name(last_token));
11059 error_msg += "; expected " + lexer::token_type_name(t);
11060 JSON_THROW(std::invalid_argument(error_msg));
11061 }
11062 }
11063
11064 void unexpect(typename lexer::token_type t) const
11065 {
11066 if (t == last_token)
11067 {
11068 std::string error_msg = "parse error - unexpected ";
11069 error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
11070 "'") :
11071 lexer::token_type_name(last_token));
11072 JSON_THROW(std::invalid_argument(error_msg));
11073 }
11074 }
11075
11076 private:
11078 int depth = 0;
11080 const parser_callback_t callback = nullptr;
11082 typename lexer::token_type last_token = lexer::token_type::uninitialized;
11084 lexer m_lexer;
11085 };
11086
11087 public:
11100 {
11102 friend class basic_json;
11103
11104 public:
11127 explicit json_pointer(const std::string& s = "")
11128 : reference_tokens(split(s))
11129 {}
11130
11146 std::string to_string() const noexcept
11147 {
11148 return std::accumulate(reference_tokens.begin(),
11149 reference_tokens.end(), std::string{},
11150 [](const std::string & a, const std::string & b)
11151 {
11152 return a + "/" + escape(b);
11153 });
11154 }
11155
11157 operator std::string() const
11158 {
11159 return to_string();
11160 }
11162 private:
11164 std::string pop_back()
11165 {
11166 if (is_root())
11167 {
11168 JSON_THROW(std::domain_error("JSON pointer has no parent"));
11169 }
11170
11171 auto last = reference_tokens.back();
11172 reference_tokens.pop_back();
11173 return last;
11174 }
11175
11177 bool is_root() const
11178 {
11179 return reference_tokens.empty();
11180 }
11181
11182 json_pointer top() const
11183 {
11184 if (is_root())
11185 {
11186 JSON_THROW(std::domain_error("JSON pointer has no parent"));
11187 }
11188
11189 json_pointer result = *this;
11190 result.reference_tokens = {reference_tokens[0]};
11191 return result;
11192 }
11193
11199 reference get_and_create(reference j) const
11200 {
11201 pointer result = &j;
11202
11203 // in case no reference tokens exist, return a reference to the
11204 // JSON value j which will be overwritten by a primitive value
11205 for (const auto& reference_token : reference_tokens)
11206 {
11207 switch (result->m_type)
11208 {
11209 case value_t::null:
11210 {
11211 if (reference_token == "0")
11212 {
11213 // start a new array if reference token is 0
11214 result = &result->operator[](0);
11215 }
11216 else
11217 {
11218 // start a new object otherwise
11219 result = &result->operator[](reference_token);
11220 }
11221 break;
11222 }
11223
11224 case value_t::object:
11225 {
11226 // create an entry in the object
11227 result = &result->operator[](reference_token);
11228 break;
11229 }
11230
11231 case value_t::array:
11232 {
11233 // create an entry in the array
11234 result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
11235 break;
11236 }
11237
11238 /*
11239 The following code is only reached if there exists a
11240 reference token _and_ the current value is primitive. In
11241 this case, we have an error situation, because primitive
11242 values may only occur as single value; that is, with an
11243 empty list of reference tokens.
11244 */
11245 default:
11246 {
11247 JSON_THROW(std::domain_error("invalid value to unflatten"));
11248 }
11249 }
11250 }
11251
11252 return *result;
11253 }
11254
11274 reference get_unchecked(pointer ptr) const
11275 {
11276 for (const auto& reference_token : reference_tokens)
11277 {
11278 // convert null values to arrays or objects before continuing
11279 if (ptr->m_type == value_t::null)
11280 {
11281 // check if reference token is a number
11282 const bool nums = std::all_of(reference_token.begin(),
11283 reference_token.end(),
11284 [](const char x)
11285 {
11286 return std::isdigit(x);
11287 });
11288
11289 // change value to array for numbers or "-" or to object
11290 // otherwise
11291 if (nums or reference_token == "-")
11292 {
11293 *ptr = value_t::array;
11294 }
11295 else
11296 {
11297 *ptr = value_t::object;
11298 }
11299 }
11300
11301 switch (ptr->m_type)
11302 {
11303 case value_t::object:
11304 {
11305 // use unchecked object access
11306 ptr = &ptr->operator[](reference_token);
11307 break;
11308 }
11309
11310 case value_t::array:
11311 {
11312 // error condition (cf. RFC 6901, Sect. 4)
11313 if (reference_token.size() > 1 and reference_token[0] == '0')
11314 {
11315 JSON_THROW(std::domain_error("array index must not begin with '0'"));
11316 }
11317
11318 if (reference_token == "-")
11319 {
11320 // explicitly treat "-" as index beyond the end
11321 ptr = &ptr->operator[](ptr->m_value.array->size());
11322 }
11323 else
11324 {
11325 // convert array index to number; unchecked access
11326 ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11327 }
11328 break;
11329 }
11330
11331 default:
11332 {
11333 JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11334 }
11335 }
11336 }
11337
11338 return *ptr;
11339 }
11340
11341 reference get_checked(pointer ptr) const
11342 {
11343 for (const auto& reference_token : reference_tokens)
11344 {
11345 switch (ptr->m_type)
11346 {
11347 case value_t::object:
11348 {
11349 // note: at performs range check
11350 ptr = &ptr->at(reference_token);
11351 break;
11352 }
11353
11354 case value_t::array:
11355 {
11356 if (reference_token == "-")
11357 {
11358 // "-" always fails the range check
11359 JSON_THROW(std::out_of_range("array index '-' (" +
11360 std::to_string(ptr->m_value.array->size()) +
11361 ") is out of range"));
11362 }
11363
11364 // error condition (cf. RFC 6901, Sect. 4)
11365 if (reference_token.size() > 1 and reference_token[0] == '0')
11366 {
11367 JSON_THROW(std::domain_error("array index must not begin with '0'"));
11368 }
11369
11370 // note: at performs range check
11371 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11372 break;
11373 }
11374
11375 default:
11376 {
11377 JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11378 }
11379 }
11380 }
11381
11382 return *ptr;
11383 }
11384
11393 const_reference get_unchecked(const_pointer ptr) const
11394 {
11395 for (const auto& reference_token : reference_tokens)
11396 {
11397 switch (ptr->m_type)
11398 {
11399 case value_t::object:
11400 {
11401 // use unchecked object access
11402 ptr = &ptr->operator[](reference_token);
11403 break;
11404 }
11405
11406 case value_t::array:
11407 {
11408 if (reference_token == "-")
11409 {
11410 // "-" cannot be used for const access
11411 JSON_THROW(std::out_of_range("array index '-' (" +
11412 std::to_string(ptr->m_value.array->size()) +
11413 ") is out of range"));
11414 }
11415
11416 // error condition (cf. RFC 6901, Sect. 4)
11417 if (reference_token.size() > 1 and reference_token[0] == '0')
11418 {
11419 JSON_THROW(std::domain_error("array index must not begin with '0'"));
11420 }
11421
11422 // use unchecked array access
11423 ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11424 break;
11425 }
11426
11427 default:
11428 {
11429 JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11430 }
11431 }
11432 }
11433
11434 return *ptr;
11435 }
11436
11437 const_reference get_checked(const_pointer ptr) const
11438 {
11439 for (const auto& reference_token : reference_tokens)
11440 {
11441 switch (ptr->m_type)
11442 {
11443 case value_t::object:
11444 {
11445 // note: at performs range check
11446 ptr = &ptr->at(reference_token);
11447 break;
11448 }
11449
11450 case value_t::array:
11451 {
11452 if (reference_token == "-")
11453 {
11454 // "-" always fails the range check
11455 JSON_THROW(std::out_of_range("array index '-' (" +
11456 std::to_string(ptr->m_value.array->size()) +
11457 ") is out of range"));
11458 }
11459
11460 // error condition (cf. RFC 6901, Sect. 4)
11461 if (reference_token.size() > 1 and reference_token[0] == '0')
11462 {
11463 JSON_THROW(std::domain_error("array index must not begin with '0'"));
11464 }
11465
11466 // note: at performs range check
11467 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11468 break;
11469 }
11470
11471 default:
11472 {
11473 JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11474 }
11475 }
11476 }
11477
11478 return *ptr;
11479 }
11480
11482 static std::vector<std::string> split(const std::string& reference_string)
11483 {
11484 std::vector<std::string> result;
11485
11486 // special case: empty reference string -> no reference tokens
11487 if (reference_string.empty())
11488 {
11489 return result;
11490 }
11491
11492 // check if nonempty reference string begins with slash
11493 if (reference_string[0] != '/')
11494 {
11495 JSON_THROW(std::domain_error("JSON pointer must be empty or begin with '/'"));
11496 }
11497
11498 // extract the reference tokens:
11499 // - slash: position of the last read slash (or end of string)
11500 // - start: position after the previous slash
11501 for (
11502 // search for the first slash after the first character
11503 size_t slash = reference_string.find_first_of('/', 1),
11504 // set the beginning of the first reference token
11505 start = 1;
11506 // we can stop if start == string::npos+1 = 0
11507 start != 0;
11508 // set the beginning of the next reference token
11509 // (will eventually be 0 if slash == std::string::npos)
11510 start = slash + 1,
11511 // find next slash
11512 slash = reference_string.find_first_of('/', start))
11513 {
11514 // use the text between the beginning of the reference token
11515 // (start) and the last slash (slash).
11516 auto reference_token = reference_string.substr(start, slash - start);
11517
11518 // check reference tokens are properly escaped
11519 for (size_t pos = reference_token.find_first_of('~');
11520 pos != std::string::npos;
11521 pos = reference_token.find_first_of('~', pos + 1))
11522 {
11523 assert(reference_token[pos] == '~');
11524
11525 // ~ must be followed by 0 or 1
11526 if (pos == reference_token.size() - 1 or
11527 (reference_token[pos + 1] != '0' and
11528 reference_token[pos + 1] != '1'))
11529 {
11530 JSON_THROW(std::domain_error("escape error: '~' must be followed with '0' or '1'"));
11531 }
11532 }
11533
11534 // finally, store the reference token
11535 unescape(reference_token);
11536 result.push_back(reference_token);
11537 }
11538
11539 return result;
11540 }
11541
11542 private:
11555 static void replace_substring(std::string& s,
11556 const std::string& f,
11557 const std::string& t)
11558 {
11559 assert(not f.empty());
11560
11561 for (
11562 size_t pos = s.find(f); // find first occurrence of f
11563 pos != std::string::npos; // make sure f was found
11564 s.replace(pos, f.size(), t), // replace with t
11565 pos = s.find(f, pos + t.size()) // find next occurrence of f
11566 );
11567 }
11568
11570 static std::string escape(std::string s)
11571 {
11572 // escape "~"" to "~0" and "/" to "~1"
11573 replace_substring(s, "~", "~0");
11574 replace_substring(s, "/", "~1");
11575 return s;
11576 }
11577
11579 static void unescape(std::string& s)
11580 {
11581 // first transform any occurrence of the sequence '~1' to '/'
11582 replace_substring(s, "~1", "/");
11583 // then transform any occurrence of the sequence '~0' to '~'
11584 replace_substring(s, "~0", "~");
11585 }
11586
11594 static void flatten(const std::string& reference_string,
11595 const basic_json& value,
11596 basic_json& result)
11597 {
11598 switch (value.m_type)
11599 {
11600 case value_t::array:
11601 {
11602 if (value.m_value.array->empty())
11603 {
11604 // flatten empty array as null
11605 result[reference_string] = nullptr;
11606 }
11607 else
11608 {
11609 // iterate array and use index as reference string
11610 for (size_t i = 0; i < value.m_value.array->size(); ++i)
11611 {
11612 flatten(reference_string + "/" + std::to_string(i),
11613 value.m_value.array->operator[](i), result);
11614 }
11615 }
11616 break;
11617 }
11618
11619 case value_t::object:
11620 {
11621 if (value.m_value.object->empty())
11622 {
11623 // flatten empty object as null
11624 result[reference_string] = nullptr;
11625 }
11626 else
11627 {
11628 // iterate object and use keys as reference string
11629 for (const auto& element : *value.m_value.object)
11630 {
11631 flatten(reference_string + "/" + escape(element.first),
11632 element.second, result);
11633 }
11634 }
11635 break;
11636 }
11637
11638 default:
11639 {
11640 // add primitive value with its reference string
11641 result[reference_string] = value;
11642 break;
11643 }
11644 }
11645 }
11646
11652 static basic_json unflatten(const basic_json& value)
11653 {
11654 if (not value.is_object())
11655 {
11656 JSON_THROW(std::domain_error("only objects can be unflattened"));
11657 }
11658
11659 basic_json result;
11660
11661 // iterate the JSON object values
11662 for (const auto& element : *value.m_value.object)
11663 {
11664 if (not element.second.is_primitive())
11665 {
11666 JSON_THROW(std::domain_error("values in object must be primitive"));
11667 }
11668
11669 // assign value to reference pointed to by JSON pointer; Note
11670 // that if the JSON pointer is "" (i.e., points to the whole
11671 // value), function get_and_create returns a reference to
11672 // result itself. An assignment will then create a primitive
11673 // value.
11674 json_pointer(element.first).get_and_create(result) = element.second;
11675 }
11676
11677 return result;
11678 }
11679
11680 private:
11681 friend bool operator==(json_pointer const& lhs,
11682 json_pointer const& rhs) noexcept
11683 {
11684 return lhs.reference_tokens == rhs.reference_tokens;
11686
11687 friend bool operator!=(json_pointer const& lhs,
11688 json_pointer const& rhs) noexcept
11689 {
11690 return !(lhs == rhs);
11692
11694 std::vector<std::string> reference_tokens {};
11695 };
11696
11698 // JSON Pointer support //
11700
11703
11737 reference operator[](const json_pointer& ptr)
11738 {
11739 return ptr.get_unchecked(this);
11740 }
11764 const_reference operator[](const json_pointer& ptr) const
11765 {
11766 return ptr.get_unchecked(this);
11767 }
11789 reference at(const json_pointer& ptr)
11790 {
11791 return ptr.get_checked(this);
11792 }
11814 const_reference at(const json_pointer& ptr) const
11815 {
11816 return ptr.get_checked(this);
11817 }
11841 basic_json flatten() const
11842 {
11843 basic_json result(value_t::object);
11844 json_pointer::flatten("", *this, result);
11845 return result;
11846 }
11847
11875 basic_json unflatten() const
11876 {
11877 return json_pointer::unflatten(*this);
11878 }
11881
11883 // JSON Patch functions //
11885
11888
11925 basic_json patch(const basic_json& json_patch) const
11926 {
11927 // make a working copy to apply the patch to
11928 basic_json result = *this;
11930 // the valid JSON Patch operations
11931 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
11932
11933 const auto get_op = [](const std::string op)
11934 {
11935 if (op == "add")
11936 {
11937 return patch_operations::add;
11938 }
11939 if (op == "remove")
11940 {
11941 return patch_operations::remove;
11942 }
11943 if (op == "replace")
11944 {
11945 return patch_operations::replace;
11946 }
11947 if (op == "move")
11948 {
11949 return patch_operations::move;
11950 }
11951 if (op == "copy")
11952 {
11953 return patch_operations::copy;
11954 }
11955 if (op == "test")
11956 {
11957 return patch_operations::test;
11958 }
11959
11960 return patch_operations::invalid;
11961 };
11962
11963 // wrapper for "add" operation; add value at ptr
11964 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
11965 {
11966 // adding to the root of the target document means replacing it
11967 if (ptr.is_root())
11968 {
11969 result = val;
11970 }
11971 else
11972 {
11973 // make sure the top element of the pointer exists
11974 json_pointer top_pointer = ptr.top();
11975 if (top_pointer != ptr)
11976 {
11977 result.at(top_pointer);
11978 }
11979
11980 // get reference to parent of JSON pointer ptr
11981 const auto last_path = ptr.pop_back();
11982 basic_json& parent = result[ptr];
11983
11984 switch (parent.m_type)
11985 {
11986 case value_t::null:
11987 case value_t::object:
11988 {
11989 // use operator[] to add value
11990 parent[last_path] = val;
11991 break;
11992 }
11993
11994 case value_t::array:
11995 {
11996 if (last_path == "-")
11997 {
11998 // special case: append to back
11999 parent.push_back(val);
12000 }
12001 else
12002 {
12003 const auto idx = std::stoi(last_path);
12004 if (static_cast<size_type>(idx) > parent.size())
12005 {
12006 // avoid undefined behavior
12007 JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
12008 }
12009 else
12010 {
12011 // default case: insert add offset
12012 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
12013 }
12014 }
12015 break;
12016 }
12017
12018 default:
12019 {
12020 // if there exists a parent it cannot be primitive
12021 assert(false); // LCOV_EXCL_LINE
12022 }
12023 }
12024 }
12025 };
12026
12027 // wrapper for "remove" operation; remove value at ptr
12028 const auto operation_remove = [&result](json_pointer & ptr)
12029 {
12030 // get reference to parent of JSON pointer ptr
12031 const auto last_path = ptr.pop_back();
12032 basic_json& parent = result.at(ptr);
12033
12034 // remove child
12035 if (parent.is_object())
12036 {
12037 // perform range check
12038 auto it = parent.find(last_path);
12039 if (it != parent.end())
12040 {
12041 parent.erase(it);
12042 }
12043 else
12044 {
12045 JSON_THROW(std::out_of_range("key '" + last_path + "' not found"));
12046 }
12047 }
12048 else if (parent.is_array())
12049 {
12050 // note erase performs range check
12051 parent.erase(static_cast<size_type>(std::stoi(last_path)));
12052 }
12053 };
12054
12055 // type check
12056 if (not json_patch.is_array())
12057 {
12058 // a JSON patch must be an array of objects
12059 JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));
12060 }
12061
12062 // iterate and apply the operations
12063 for (const auto& val : json_patch)
12064 {
12065 // wrapper to get a value for an operation
12066 const auto get_value = [&val](const std::string & op,
12067 const std::string & member,
12068 bool string_type) -> basic_json&
12069 {
12070 // find value
12071 auto it = val.m_value.object->find(member);
12072
12073 // context-sensitive error message
12074 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
12075
12076 // check if desired value is present
12077 if (it == val.m_value.object->end())
12078 {
12079 JSON_THROW(std::invalid_argument(error_msg + " must have member '" + member + "'"));
12080 }
12081
12082 // check if result is of type string
12083 if (string_type and not it->second.is_string())
12084 {
12085 JSON_THROW(std::invalid_argument(error_msg + " must have string member '" + member + "'"));
12086 }
12087
12088 // no error: return value
12089 return it->second;
12090 };
12091
12092 // type check
12093 if (not val.is_object())
12094 {
12095 JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));
12096 }
12097
12098 // collect mandatory members
12099 const std::string op = get_value("op", "op", true);
12100 const std::string path = get_value(op, "path", true);
12101 json_pointer ptr(path);
12102
12103 switch (get_op(op))
12104 {
12105 case patch_operations::add:
12106 {
12107 operation_add(ptr, get_value("add", "value", false));
12108 break;
12109 }
12110
12111 case patch_operations::remove:
12112 {
12113 operation_remove(ptr);
12114 break;
12115 }
12116
12117 case patch_operations::replace:
12118 {
12119 // the "path" location must exist - use at()
12120 result.at(ptr) = get_value("replace", "value", false);
12121 break;
12122 }
12123
12124 case patch_operations::move:
12125 {
12126 const std::string from_path = get_value("move", "from", true);
12127 json_pointer from_ptr(from_path);
12128
12129 // the "from" location must exist - use at()
12130 basic_json v = result.at(from_ptr);
12131
12132 // The move operation is functionally identical to a
12133 // "remove" operation on the "from" location, followed
12134 // immediately by an "add" operation at the target
12135 // location with the value that was just removed.
12136 operation_remove(from_ptr);
12137 operation_add(ptr, v);
12138 break;
12139 }
12140
12141 case patch_operations::copy:
12142 {
12143 const std::string from_path = get_value("copy", "from", true);;
12144 const json_pointer from_ptr(from_path);
12145
12146 // the "from" location must exist - use at()
12147 result[ptr] = result.at(from_ptr);
12148 break;
12149 }
12150
12151 case patch_operations::test:
12152 {
12153 bool success = false;
12154 JSON_TRY
12155 {
12156 // check if "value" matches the one at "path"
12157 // the "path" location must exist - use at()
12158 success = (result.at(ptr) == get_value("test", "value", false));
12159 }
12160 JSON_CATCH (std::out_of_range&)
12161 {
12162 // ignore out of range errors: success remains false
12163 }
12164
12165 // throw an exception if test fails
12166 if (not success)
12167 {
12168 JSON_THROW(std::domain_error("unsuccessful: " + val.dump()));
12169 }
12170
12171 break;
12172 }
12173
12174 case patch_operations::invalid:
12175 {
12176 // op must be "add", "remove", "replace", "move", "copy", or
12177 // "test"
12178 JSON_THROW(std::invalid_argument("operation value '" + op + "' is invalid"));
12179 }
12180 }
12181 }
12182
12183 return result;
12184 }
12185
12218 static basic_json diff(const basic_json& source,
12219 const basic_json& target,
12220 const std::string& path = "")
12221 {
12222 // the patch
12223 basic_json result(value_t::array);
12224
12225 // if the values are the same, return empty patch
12226 if (source == target)
12227 {
12228 return result;
12229 }
12230
12231 if (source.type() != target.type())
12232 {
12233 // different types: replace value
12234 result.push_back(
12235 {
12236 {"op", "replace"},
12237 {"path", path},
12238 {"value", target}
12239 });
12240 }
12241 else
12242 {
12243 switch (source.type())
12244 {
12245 case value_t::array:
12246 {
12247 // first pass: traverse common elements
12248 size_t i = 0;
12249 while (i < source.size() and i < target.size())
12250 {
12251 // recursive call to compare array values at index i
12252 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
12253 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12254 ++i;
12255 }
12256
12257 // i now reached the end of at least one array
12258 // in a second pass, traverse the remaining elements
12259
12260 // remove my remaining elements
12261 const auto end_index = static_cast<difference_type>(result.size());
12262 while (i < source.size())
12263 {
12264 // add operations in reverse order to avoid invalid
12265 // indices
12266 result.insert(result.begin() + end_index, object(
12267 {
12268 {"op", "remove"},
12269 {"path", path + "/" + std::to_string(i)}
12270 }));
12271 ++i;
12272 }
12273
12274 // add other remaining elements
12275 while (i < target.size())
12276 {
12277 result.push_back(
12278 {
12279 {"op", "add"},
12280 {"path", path + "/" + std::to_string(i)},
12281 {"value", target[i]}
12282 });
12283 ++i;
12284 }
12285
12286 break;
12287 }
12288
12289 case value_t::object:
12290 {
12291 // first pass: traverse this object's elements
12292 for (auto it = source.begin(); it != source.end(); ++it)
12293 {
12294 // escape the key name to be used in a JSON patch
12295 const auto key = json_pointer::escape(it.key());
12296
12297 if (target.find(it.key()) != target.end())
12298 {
12299 // recursive call to compare object values at key it
12300 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
12301 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12302 }
12303 else
12304 {
12305 // found a key that is not in o -> remove it
12306 result.push_back(object(
12307 {
12308 {"op", "remove"},
12309 {"path", path + "/" + key}
12310 }));
12311 }
12312 }
12313
12314 // second pass: traverse other object's elements
12315 for (auto it = target.begin(); it != target.end(); ++it)
12316 {
12317 if (source.find(it.key()) == source.end())
12318 {
12319 // found a key that is not in this -> add it
12320 const auto key = json_pointer::escape(it.key());
12321 result.push_back(
12322 {
12323 {"op", "add"},
12324 {"path", path + "/" + key},
12325 {"value", it.value()}
12326 });
12327 }
12328 }
12329
12330 break;
12331 }
12332
12333 default:
12334 {
12335 // both primitive type: replace value
12336 result.push_back(
12337 {
12338 {"op", "replace"},
12339 {"path", path},
12340 {"value", target}
12341 });
12342 break;
12343 }
12344 }
12345 }
12346
12347 return result;
12348 }
12349
12351};
12352
12354// presets //
12356
12365using json = basic_json<>;
12366} // namespace nlohmann
12367
12368
12370// nonmember support //
12372
12373// specialization of std::swap, and std::hash
12374namespace std
12375{
12381template<>
12382inline void swap(nlohmann::json& j1,
12383 nlohmann::json& j2) noexcept(
12384 is_nothrow_move_constructible<nlohmann::json>::value and
12385 is_nothrow_move_assignable<nlohmann::json>::value
12386 )
12387{
12388 j1.swap(j2);
12389}
12390
12392template<>
12393struct hash<nlohmann::json>
12394{
12400 std::size_t operator()(const nlohmann::json& j) const
12401 {
12402 // a naive hashing via the string representation
12403 const auto& h = hash<nlohmann::json::string_t>();
12404 return h(j.dump());
12405 }
12406};
12407} // namespace std
12408
12422inline nlohmann::json operator "" _json(const char* s, std::size_t n)
12423{
12424 return nlohmann::json::parse(s, s + n);
12425}
12426
12440inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
12441{
12442 return nlohmann::json::json_pointer(std::string(s, n));
12443}
12444
12445// restore GCC/clang diagnostic settings
12446#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
12447 #pragma GCC diagnostic pop
12448#endif
12449
12450// clean up
12451#undef JSON_CATCH
12452#undef JSON_DEPRECATED
12453#undef JSON_THROW
12454#undef JSON_TRY
12455
12456#endif
object_t::key_type key() const
return the key of an object iterator
Definition json.hpp:9406
iter_impl operator--(int)
post-decrement (it–)
Definition json.hpp:9135
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:9311
iter_impl operator+(difference_type i)
add to iterator
Definition json.hpp:9320
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:9146
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:9342
typename std::conditional< std::is_const< U >::value, typename basic_json::const_pointer, typename basic_json::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.hpp:8855
iter_impl()=default
default constructor
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:8849
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:9271
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:9253
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:9220
iter_impl operator++(int)
post-increment (it++)
Definition json.hpp:9092
iter_impl operator-(difference_type i)
subtract from iterator
Definition json.hpp:9331
reference value() const
return the value of an iterator
Definition json.hpp:9422
iter_impl(const iter_impl &other) noexcept
copy constructor
Definition json.hpp:8925
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:9103
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:8851
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition json.hpp:8872
iter_impl & operator=(iter_impl other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition json.hpp:8934
reference operator[](difference_type n) const
access to successor
Definition json.hpp:9369
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition json.hpp:8861
typename std::conditional< std::is_const< U >::value, typename basic_json::const_reference, typename basic_json::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.hpp:8859
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:9019
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:9262
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:9280
bool operator==(const iter_impl &other) const
comparison: equal
Definition json.hpp:9178
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition json.hpp:9211
pointer operator->() const
dereference the iterator
Definition json.hpp:9058
a template for a random access iterator for the basic_json class
Definition json.hpp:8838
json_pointer(const std::string &s="")
create JSON pointer
Definition json.hpp:11127
json_reverse_iterator operator++(int)
post-increment (it++)
Definition json.hpp:9471
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:9461
object_t::key_type key() const
return the key of an object iterator
Definition json.hpp:9532
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:9520
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:9477
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition json.hpp:9456
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:9490
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:9504
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:9512
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:9497
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:9458
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition json.hpp:9484
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:9466
reference operator[](difference_type n) const
access to successor
Definition json.hpp:9526
reference value() const
return the value of an iterator
Definition json.hpp:9539
a template for a reverse iterator class
Definition json.hpp:9453
reference back()
access the last element
Definition json.hpp:4235
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition json.hpp:5540
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:4301
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition json.hpp:5416
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:4670
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition json.hpp:5882
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:4741
reference operator[](T *(&key)[n])
access specified object element
Definition json.hpp:3887
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition json.hpp:3389
bool empty() const noexcept
checks whether the container is empty
Definition json.hpp:4995
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition json.hpp:4751
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:4885
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition json.hpp:5564
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:4811
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition json.hpp:3798
size_type size() const noexcept
returns the number of elements
Definition json.hpp:5063
const_reference operator[](T *key) const
read-only access specified object element
Definition json.hpp:4005
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:2681
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:2812
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:5129
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:4496
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition json.hpp:5593
basic_json(const value_t value_type)
create an empty value with a given type
Definition json.hpp:1916
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:2897
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
Definition json.hpp:6412
std::size_t size_type
a type to represent container sizes
Definition json.hpp:1077
reference front()
access the first element
Definition json.hpp:4192
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition json.hpp:6361
static basic_json from_msgpack(const std::vector< uint8_t > &v, const size_t start_index=0)
create a JSON value from a byte vector in MessagePack format
Definition json.hpp:7974
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition json.hpp:5643
~basic_json()
destructor
Definition json.hpp:2575
constexpr const PointerType get() const noexcept
get a pointer value (explicit)
Definition json.hpp:3327
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
Definition json.hpp:2165
const_reference front() const
access the first element
Definition json.hpp:4200
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:4408
BooleanType boolean_t
a type for a boolean
Definition json.hpp:1407
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition json.hpp:6352
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition json.hpp:4680
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:4856
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:4819
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:4630
string_t dump(const int indent=-1) const
serialization
Definition json.hpp:2647
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:5492
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:4914
ValueType get() const noexcept(noexcept(JSONSerializer< ValueTypeCV >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition json.hpp:3278
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition json.hpp:6222
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition json.hpp:6141
StringType string_t
a type for a string
Definition json.hpp:1381
friend struct detail::external_constructor
Definition json.hpp:1042
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:2711
PointerType get() noexcept
get a pointer value (explicit)
Definition json.hpp:3315
void swap(array_t &other)
exchanges the values
Definition json.hpp:5770
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:2963
basic_json get() const
get special-case overload
Definition json.hpp:3173
std::string type_name() const
return the type as string
Definition json.hpp:8065
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition json.hpp:4597
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition json.hpp:5995
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition json.hpp:6484
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition json.hpp:4935
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:1094
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:3531
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition json.hpp:6185
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:7941
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition json.hpp:2396
basic_json(CompatibleType &&val) noexcept(noexcept(JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value
Definition json.hpp:2006
JSONSerializer< T, SFINAE > json_serializer
Definition json.hpp:1055
const_reference back() const
access the last element
Definition json.hpp:4245
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:8004
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition json.hpp:4162
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:1080
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition json.hpp:6284
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition json.hpp:6163
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:4531
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:1618
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:5738
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition json.hpp:4781
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:2760
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition json.hpp:4943
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:3621
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:2782
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:1479
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:2505
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:3760
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
Definition json.hpp:2205
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:2738
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.hpp:1282
ValueType get() const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition json.hpp:3225
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:2990
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition json.hpp:6046
void emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:5444
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition json.hpp:6017
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:3574
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition json.hpp:3922
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition json.hpp:3847
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition json.hpp:5399
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition json.hpp:6322
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:5294
static basic_json from_cbor(const std::vector< uint8_t > &v, const size_t start_index=0)
create a JSON value from a byte vector in CBOR format
Definition json.hpp:8037
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:2229
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:4139
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:1550
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition json.hpp:5963
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:2841
reference operator[](T *key)
access specified object element
Definition json.hpp:3955
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:2869
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:2276
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:5368
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition json.hpp:6241
void clear() noexcept
clears the contents
Definition json.hpp:5185
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:1092
void swap(object_t &other)
exchanges the values
Definition json.hpp:5803
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:3451
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:4848
reference operator[](size_type idx)
access specified array element
Definition json.hpp:3714
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:5258
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:3668
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition json.hpp:5701
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition json.hpp:4091
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:4710
void swap(string_t &other)
exchanges the values
Definition json.hpp:5836
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:5318
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:1328
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:5344
detail::value_t value_t
Definition json.hpp:1049
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition json.hpp:2542
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:1940
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:6524
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:5284
parse_event_t
JSON callback events.
Definition json.hpp:1808
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition json.hpp:1877
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition json.hpp:4581
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition json.hpp:5974
static basic_json meta()
returns version information on the library
Definition json.hpp:1130
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:2941
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition json.hpp:3361
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:1083
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:1102
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:2428
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:2919
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition json.hpp:6514
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition json.hpp:4067
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:2082
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:3438
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:1075
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition json.hpp:6006
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:1085
a class to store JSON values
Definition json.hpp:1040
constexpr const auto & to_json
Definition json.hpp:898
constexpr const auto & from_json
Definition json.hpp:899
basic_json<> json
default JSON class
Definition json.hpp:12369
namespace for Niels Lohmann
Definition json.hpp:109
STL namespace.
static void from_json(BasicJsonType &&j, ValueType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val)))
convert a JSON value to any value type
Definition json.hpp:923
static void to_json(BasicJsonType &j, ValueType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< ValueType >(val))))
convert any value type to a JSON value
Definition json.hpp:939
default JSONSerializer template argument
Definition json.hpp:912
strtonum(const char *start, const char *end)
Definition json.hpp:10556
parse string into a built-in arithmetic type as if the current locale is POSIX.
Definition json.hpp:10554