JSON for Modern C++ 2.1.1

json.hpp
1 /*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.1.1
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
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 <ciso646> // and, not, or
36 #include <clocale> // lconv, localeconv
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 <iostream> // istream, ostream
46 #include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
47 #include <limits> // numeric_limits
48 #include <locale> // locale
49 #include <map> // map
50 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
51 #include <numeric> // accumulate
52 #include <sstream> // stringstream
53 #include <string> // getline, stoi, string, to_string
54 #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
55 #include <utility> // declval, forward, make_pair, move, pair, swap
56 #include <vector> // vector
57
58 // exclude unsupported compilers
59 #if defined(__clang__)
60 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
61 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
62 #endif
63 #elif defined(__GNUC__)
64 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
65 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
66 #endif
67 #endif
68
69 // disable float-equal warnings on GCC/clang
70 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
71 #pragma GCC diagnostic push
72 #pragma GCC diagnostic ignored "-Wfloat-equal"
73 #endif
74
75 // disable documentation warnings on clang
76 #if defined(__clang__)
77 #pragma GCC diagnostic push
78 #pragma GCC diagnostic ignored "-Wdocumentation"
79 #endif
80
81 // allow for portable deprecation warnings
82 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
83 #define JSON_DEPRECATED __attribute__((deprecated))
84 #elif defined(_MSC_VER)
85 #define JSON_DEPRECATED __declspec(deprecated)
86 #else
87 #define JSON_DEPRECATED
88 #endif
89
90 // allow to disable exceptions
91 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION)
92 #define JSON_THROW(exception) throw exception
93 #define JSON_TRY try
94 #define JSON_CATCH(exception) catch(exception)
95 #else
96 #define JSON_THROW(exception) std::abort()
97 #define JSON_TRY if(true)
98 #define JSON_CATCH(exception) if(false)
99 #endif
100
106 namespace nlohmann
107 {
108
117 namespace detail
118 {
120 // exceptions //
122
135 class exception : public std::exception
136 {
137 public:
139 virtual const char* what() const noexcept override
140 {
141 return m.what();
142 }
143
145 const int id;
146
147 protected:
148 exception(int id_, const char* what_arg)
149 : id(id_), m(what_arg)
150 {}
151
152 static std::string name(const std::string& ename, int id)
153 {
154 return "[json.exception." + ename + "." + std::to_string(id) + "] ";
155 }
156
157 private:
159 std::runtime_error m;
160 };
161
197 class parse_error : public exception
198 {
199 public:
208 static parse_error create(int id, size_t byte_, const std::string& what_arg)
209 {
210 std::string w = exception::name("parse_error", id) + "parse error" +
211 (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") +
212 ": " + what_arg;
213 return parse_error(id, byte_, w.c_str());
214 }
215
226 const size_t byte;
227
228 private:
229 parse_error(int id_, size_t byte_, const char* what_arg)
230 : exception(id_, what_arg), byte(byte_)
231 {}
232 };
233
258 class invalid_iterator : public exception
259 {
260 public:
261 static invalid_iterator create(int id, const std::string& what_arg)
262 {
263 std::string w = exception::name("invalid_iterator", id) + what_arg;
264 return invalid_iterator(id, w.c_str());
265 }
266
267 private:
268 invalid_iterator(int id_, const char* what_arg)
269 : exception(id_, what_arg)
270 {}
271 };
272
297 class type_error : public exception
298 {
299 public:
300 static type_error create(int id, const std::string& what_arg)
301 {
302 std::string w = exception::name("type_error", id) + what_arg;
303 return type_error(id, w.c_str());
304 }
305
306 private:
307 type_error(int id_, const char* what_arg)
308 : exception(id_, what_arg)
309 {}
310 };
311
328 class out_of_range : public exception
329 {
330 public:
331 static out_of_range create(int id, const std::string& what_arg)
332 {
333 std::string w = exception::name("out_of_range", id) + what_arg;
334 return out_of_range(id, w.c_str());
335 }
336
337 private:
338 out_of_range(int id_, const char* what_arg)
339 : exception(id_, what_arg)
340 {}
341 };
342
354 class other_error : public exception
355 {
356 public:
357 static other_error create(int id, const std::string& what_arg)
358 {
359 std::string w = exception::name("other_error", id) + what_arg;
360 return other_error(id, w.c_str());
361 }
362
363 private:
364 other_error(int id_, const char* what_arg)
365 : exception(id_, what_arg)
366 {}
367 };
368
369
370
372 // JSON type enumeration //
374
399 enum class value_t : uint8_t
400 {
401 null,
402 object,
403 array,
404 string,
405 boolean,
406 number_integer,
407 number_unsigned,
408 number_float,
409 discarded
410 };
411
421 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
422 {
423 static constexpr std::array<uint8_t, 8> order = {{
424 0, // null
425 3, // object
426 4, // array
427 5, // string
428 1, // boolean
429 2, // integer
430 2, // unsigned
431 2, // float
432 }
433 };
434
435 // discarded values are not comparable
436 if (lhs == value_t::discarded or rhs == value_t::discarded)
437 {
438 return false;
439 }
440
441 return order[static_cast<std::size_t>(lhs)] <
442 order[static_cast<std::size_t>(rhs)];
443 }
444
445
447 // helpers //
449
450 // alias templates to reduce boilerplate
451 template<bool B, typename T = void>
452 using enable_if_t = typename std::enable_if<B, T>::type;
453
454 template<typename T>
455 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
456
457 /*
458 Implementation of two C++17 constructs: conjunction, negation. This is needed
459 to avoid evaluating all the traits in a condition
460
461 For example: not std::is_same<void, T>::value and has_value_type<T>::value
462 will not compile when T = void (on MSVC at least). Whereas
463 conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
464 stop evaluating if negation<...>::value == false
465
466 Please note that those constructs must be used with caution, since symbols can
467 become very long quickly (which can slow down compilation and cause MSVC
468 internal compiler errors). Only use it when you have to (see example ahead).
469 */
470 template<class...> struct conjunction : std::true_type {};
471 template<class B1> struct conjunction<B1> : B1 {};
472 template<class B1, class... Bn>
473 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
474
475 template<class B> struct negation : std::integral_constant < bool, !B::value > {};
476
477 // dispatch utility (taken from ranges-v3)
478 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
479 template<> struct priority_tag<0> {};
480
481
483 // constructors //
485
486 template<value_t> struct external_constructor;
487
488 template<>
489 struct external_constructor<value_t::boolean>
490 {
491 template<typename BasicJsonType>
492 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
493 {
494 j.m_type = value_t::boolean;
495 j.m_value = b;
496 j.assert_invariant();
497 }
498 };
499
500 template<>
501 struct external_constructor<value_t::string>
502 {
503 template<typename BasicJsonType>
504 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
505 {
506 j.m_type = value_t::string;
507 j.m_value = s;
508 j.assert_invariant();
509 }
510 };
511
512 template<>
513 struct external_constructor<value_t::number_float>
514 {
515 template<typename BasicJsonType>
516 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
517 {
518 j.m_type = value_t::number_float;
519 j.m_value = val;
520 j.assert_invariant();
521 }
522 };
523
524 template<>
525 struct external_constructor<value_t::number_unsigned>
526 {
527 template<typename BasicJsonType>
528 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
529 {
530 j.m_type = value_t::number_unsigned;
531 j.m_value = val;
532 j.assert_invariant();
533 }
534 };
535
536 template<>
537 struct external_constructor<value_t::number_integer>
538 {
539 template<typename BasicJsonType>
540 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
541 {
542 j.m_type = value_t::number_integer;
543 j.m_value = val;
544 j.assert_invariant();
545 }
546 };
547
548 template<>
549 struct external_constructor<value_t::array>
550 {
551 template<typename BasicJsonType>
552 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
553 {
554 j.m_type = value_t::array;
555 j.m_value = arr;
556 j.assert_invariant();
557 }
558
559 template<typename BasicJsonType, typename CompatibleArrayType,
560 enable_if_t<not std::is_same<CompatibleArrayType,
561 typename BasicJsonType::array_t>::value,
562 int> = 0>
563 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
564 {
565 using std::begin;
566 using std::end;
567 j.m_type = value_t::array;
568 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
569 j.assert_invariant();
570 }
571
572 template<typename BasicJsonType>
573 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
574 {
575 j.m_type = value_t::array;
576 j.m_value = value_t::array;
577 j.m_value.array->reserve(arr.size());
578 for (bool x : arr)
579 {
580 j.m_value.array->push_back(x);
581 }
582 j.assert_invariant();
583 }
584 };
585
586 template<>
587 struct external_constructor<value_t::object>
588 {
589 template<typename BasicJsonType>
590 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
591 {
592 j.m_type = value_t::object;
593 j.m_value = obj;
594 j.assert_invariant();
595 }
596
597 template<typename BasicJsonType, typename CompatibleObjectType,
598 enable_if_t<not std::is_same<CompatibleObjectType,
599 typename BasicJsonType::object_t>::value,
600 int> = 0>
601 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
602 {
603 using std::begin;
604 using std::end;
605
606 j.m_type = value_t::object;
607 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
608 j.assert_invariant();
609 }
610 };
611
612
614 // has_/is_ functions //
616
627 #define NLOHMANN_JSON_HAS_HELPER(type) \
628 template<typename T> struct has_##type { \
629 private: \
630 template<typename U, typename = typename U::type> \
631 static int detect(U &&); \
632 static void detect(...); \
633 public: \
634 static constexpr bool value = \
635 std::is_integral<decltype(detect(std::declval<T>()))>::value; \
636 }
637
638 NLOHMANN_JSON_HAS_HELPER(mapped_type);
639 NLOHMANN_JSON_HAS_HELPER(key_type);
640 NLOHMANN_JSON_HAS_HELPER(value_type);
641 NLOHMANN_JSON_HAS_HELPER(iterator);
642
643 #undef NLOHMANN_JSON_HAS_HELPER
644
645
646 template<bool B, class RealType, class CompatibleObjectType>
647 struct is_compatible_object_type_impl : std::false_type {};
648
649 template<class RealType, class CompatibleObjectType>
650 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
651 {
652 static constexpr auto value =
653 std::is_constructible<typename RealType::key_type,
654 typename CompatibleObjectType::key_type>::value and
655 std::is_constructible<typename RealType::mapped_type,
656 typename CompatibleObjectType::mapped_type>::value;
657 };
658
659 template<class BasicJsonType, class CompatibleObjectType>
660 struct is_compatible_object_type
661 {
662 static auto constexpr value = is_compatible_object_type_impl <
663 conjunction<negation<std::is_same<void, CompatibleObjectType>>,
664 has_mapped_type<CompatibleObjectType>,
665 has_key_type<CompatibleObjectType>>::value,
666 typename BasicJsonType::object_t, CompatibleObjectType >::value;
667 };
668
669 template<typename BasicJsonType, typename T>
670 struct is_basic_json_nested_type
671 {
672 static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
673 std::is_same<T, typename BasicJsonType::const_iterator>::value or
674 std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
675 std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value or
676 std::is_same<T, typename BasicJsonType::json_pointer>::value;
677 };
678
679 template<class BasicJsonType, class CompatibleArrayType>
680 struct is_compatible_array_type
681 {
682 static auto constexpr value =
683 conjunction<negation<std::is_same<void, CompatibleArrayType>>,
684 negation<is_compatible_object_type<
685 BasicJsonType, CompatibleArrayType>>,
686 negation<std::is_constructible<typename BasicJsonType::string_t,
687 CompatibleArrayType>>,
688 negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,
689 has_value_type<CompatibleArrayType>,
690 has_iterator<CompatibleArrayType>>::value;
691 };
692
693 template<bool, typename, typename>
694 struct is_compatible_integer_type_impl : std::false_type {};
695
696 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
697 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
698 {
699 // is there an assert somewhere on overflows?
700 using RealLimits = std::numeric_limits<RealIntegerType>;
701 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
702
703 static constexpr auto value =
704 std::is_constructible<RealIntegerType,
705 CompatibleNumberIntegerType>::value and
706 CompatibleLimits::is_integer and
707 RealLimits::is_signed == CompatibleLimits::is_signed;
708 };
709
710 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
711 struct is_compatible_integer_type
712 {
713 static constexpr auto value =
714 is_compatible_integer_type_impl <
715 std::is_integral<CompatibleNumberIntegerType>::value and
716 not std::is_same<bool, CompatibleNumberIntegerType>::value,
717 RealIntegerType, CompatibleNumberIntegerType > ::value;
718 };
719
720
721 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
722 template<typename BasicJsonType, typename T>
723 struct has_from_json
724 {
725 private:
726 // also check the return type of from_json
727 template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
728 std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
729 static int detect(U&&);
730 static void detect(...);
731
732 public:
733 static constexpr bool value = std::is_integral<decltype(
734 detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
735 };
736
737 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
738 // this overload is used for non-default-constructible user-defined-types
739 template<typename BasicJsonType, typename T>
740 struct has_non_default_from_json
741 {
742 private:
743 template <
744 typename U,
745 typename = enable_if_t<std::is_same<
746 T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
747 static int detect(U&&);
748 static void detect(...);
749
750 public:
751 static constexpr bool value = std::is_integral<decltype(detect(
752 std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
753 };
754
755 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
756 template<typename BasicJsonType, typename T>
757 struct has_to_json
758 {
759 private:
760 template<typename U, typename = decltype(uncvref_t<U>::to_json(
761 std::declval<BasicJsonType&>(), std::declval<T>()))>
762 static int detect(U&&);
763 static void detect(...);
764
765 public:
766 static constexpr bool value = std::is_integral<decltype(detect(
767 std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
768 };
769
770
772 // to_json //
774
775 template<typename BasicJsonType, typename T, enable_if_t<
776 std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
777 void to_json(BasicJsonType& j, T b) noexcept
778 {
779 external_constructor<value_t::boolean>::construct(j, b);
780 }
781
782 template<typename BasicJsonType, typename CompatibleString,
783 enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
784 CompatibleString>::value, int> = 0>
785 void to_json(BasicJsonType& j, const CompatibleString& s)
786 {
787 external_constructor<value_t::string>::construct(j, s);
788 }
789
790 template<typename BasicJsonType, typename FloatType,
791 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
792 void to_json(BasicJsonType& j, FloatType val) noexcept
793 {
794 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
795 }
796
797 template <
798 typename BasicJsonType, typename CompatibleNumberUnsignedType,
799 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,
800 CompatibleNumberUnsignedType>::value, int> = 0 >
801 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
802 {
803 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
804 }
805
806 template <
807 typename BasicJsonType, typename CompatibleNumberIntegerType,
808 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t,
809 CompatibleNumberIntegerType>::value, int> = 0 >
810 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
811 {
812 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
813 }
814
815 template<typename BasicJsonType, typename EnumType,
816 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
817 void to_json(BasicJsonType& j, EnumType e) noexcept
818 {
819 using underlying_type = typename std::underlying_type<EnumType>::type;
820 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
821 }
822
823 template<typename BasicJsonType>
824 void to_json(BasicJsonType& j, const std::vector<bool>& e)
825 {
826 external_constructor<value_t::array>::construct(j, e);
827 }
828
829 template <
830 typename BasicJsonType, typename CompatibleArrayType,
831 enable_if_t <
832 is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
833 std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
834 int > = 0 >
835 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
836 {
837 external_constructor<value_t::array>::construct(j, arr);
838 }
839
840 template <
841 typename BasicJsonType, typename CompatibleObjectType,
842 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
843 int> = 0 >
844 void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
845 {
846 external_constructor<value_t::object>::construct(j, arr);
847 }
848
849 template <typename BasicJsonType, typename T, std::size_t N,
850 enable_if_t<not std::is_constructible<
851 typename BasicJsonType::string_t, T (&)[N]>::value,
852 int> = 0>
853 void to_json(BasicJsonType& j, T (&arr)[N])
854 {
855 external_constructor<value_t::array>::construct(j, arr);
856 }
857
859 // from_json //
861
862 // overloads for basic_json template parameters
863 template<typename BasicJsonType, typename ArithmeticType,
864 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
865 not std::is_same<ArithmeticType,
866 typename BasicJsonType::boolean_t>::value,
867 int> = 0>
868 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
869 {
870 switch (static_cast<value_t>(j))
871 {
872 case value_t::number_unsigned:
873 {
874 val = static_cast<ArithmeticType>(
875 *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
876 break;
877 }
878 case value_t::number_integer:
879 {
880 val = static_cast<ArithmeticType>(
881 *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
882 break;
883 }
884 case value_t::number_float:
885 {
886 val = static_cast<ArithmeticType>(
887 *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
888 break;
889 }
890 default:
891 {
892 JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name()));
893 }
894 }
895 }
896
897 template<typename BasicJsonType>
898 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
899 {
900 if (not j.is_boolean())
901 {
902 JSON_THROW(type_error::create(302, "type must be boolean, but is " + j.type_name()));
903 }
904 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
905 }
906
907 template<typename BasicJsonType>
908 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
909 {
910 if (not j.is_string())
911 {
912 JSON_THROW(type_error::create(302, "type must be string, but is " + j.type_name()));
913 }
914 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
915 }
916
917 template<typename BasicJsonType>
918 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
919 {
920 get_arithmetic_value(j, val);
921 }
922
923 template<typename BasicJsonType>
924 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
925 {
926 get_arithmetic_value(j, val);
927 }
928
929 template<typename BasicJsonType>
930 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
931 {
932 get_arithmetic_value(j, val);
933 }
934
935 template<typename BasicJsonType, typename EnumType,
936 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
937 void from_json(const BasicJsonType& j, EnumType& e)
938 {
939 typename std::underlying_type<EnumType>::type val;
940 get_arithmetic_value(j, val);
941 e = static_cast<EnumType>(val);
942 }
943
944 template<typename BasicJsonType>
945 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
946 {
947 if (not j.is_array())
948 {
949 JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name()));
950 }
951 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
952 }
953
954 // forward_list doesn't have an insert method
955 template<typename BasicJsonType, typename T, typename Allocator,
956 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
957 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
958 {
959 if (not j.is_array())
960 {
961 JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name()));
962 }
963
964 for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)
965 {
966 l.push_front(it->template get<T>());
967 }
968 }
969
970 template<typename BasicJsonType, typename CompatibleArrayType>
971 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)
972 {
973 using std::begin;
974 using std::end;
975
976 std::transform(j.begin(), j.end(),
977 std::inserter(arr, end(arr)), [](const BasicJsonType & i)
978 {
979 // get<BasicJsonType>() returns *this, this won't call a from_json
980 // method when value_type is BasicJsonType
981 return i.template get<typename CompatibleArrayType::value_type>();
982 });
983 }
984
985 template<typename BasicJsonType, typename CompatibleArrayType>
986 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)
987 -> decltype(
988 arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
989 void())
990 {
991 using std::begin;
992 using std::end;
993
994 arr.reserve(j.size());
995 std::transform(j.begin(), j.end(),
996 std::inserter(arr, end(arr)), [](const BasicJsonType & i)
997 {
998 // get<BasicJsonType>() returns *this, this won't call a from_json
999 // method when value_type is BasicJsonType
1000 return i.template get<typename CompatibleArrayType::value_type>();
1001 });
1002 }
1003
1004 template<typename BasicJsonType, typename CompatibleArrayType,
1005 enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
1006 std::is_convertible<BasicJsonType, typename CompatibleArrayType::value_type>::value and
1007 not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
1008 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
1009 {
1010 if (not j.is_array())
1011 {
1012 JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name()));
1013 }
1014
1015 from_json_array_impl(j, arr, priority_tag<1> {});
1016 }
1017
1018 template<typename BasicJsonType, typename CompatibleObjectType,
1019 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
1020 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
1021 {
1022 if (not j.is_object())
1023 {
1024 JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name()));
1025 }
1026
1027 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1028 using std::begin;
1029 using std::end;
1030 // we could avoid the assignment, but this might require a for loop, which
1031 // might be less efficient than the container constructor for some
1032 // containers (would it?)
1033 obj = CompatibleObjectType(begin(*inner_object), end(*inner_object));
1034 }
1035
1036 // overload for arithmetic types, not chosen for basic_json template arguments
1037 // (BooleanType, etc..); note: Is it really necessary to provide explicit
1038 // overloads for boolean_t etc. in case of a custom BooleanType which is not
1039 // an arithmetic type?
1040 template<typename BasicJsonType, typename ArithmeticType,
1041 enable_if_t <
1042 std::is_arithmetic<ArithmeticType>::value and
1043 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1044 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1045 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1046 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1047 int> = 0>
1048 void from_json(const BasicJsonType& j, ArithmeticType& val)
1049 {
1050 switch (static_cast<value_t>(j))
1051 {
1052 case value_t::number_unsigned:
1053 {
1054 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1055 break;
1056 }
1057 case value_t::number_integer:
1058 {
1059 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1060 break;
1061 }
1062 case value_t::number_float:
1063 {
1064 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1065 break;
1066 }
1067 case value_t::boolean:
1068 {
1069 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1070 break;
1071 }
1072 default:
1073 {
1074 JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name()));
1075 }
1076 }
1077 }
1078
1079 struct to_json_fn
1080 {
1081 private:
1082 template<typename BasicJsonType, typename T>
1083 auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1084 -> decltype(to_json(j, std::forward<T>(val)), void())
1085 {
1086 return to_json(j, std::forward<T>(val));
1087 }
1088
1089 template<typename BasicJsonType, typename T>
1090 void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept
1091 {
1092 static_assert(sizeof(BasicJsonType) == 0,
1093 "could not find to_json() method in T's namespace");
1094 }
1095
1096 public:
1097 template<typename BasicJsonType, typename T>
1098 void operator()(BasicJsonType& j, T&& val) const
1099 noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
1100 {
1101 return call(j, std::forward<T>(val), priority_tag<1> {});
1102 }
1103 };
1104
1105 struct from_json_fn
1106 {
1107 private:
1108 template<typename BasicJsonType, typename T>
1109 auto call(const BasicJsonType& j, T& val, priority_tag<1>) const
1110 noexcept(noexcept(from_json(j, val)))
1111 -> decltype(from_json(j, val), void())
1112 {
1113 return from_json(j, val);
1114 }
1115
1116 template<typename BasicJsonType, typename T>
1117 void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept
1118 {
1119 static_assert(sizeof(BasicJsonType) == 0,
1120 "could not find from_json() method in T's namespace");
1121 }
1122
1123 public:
1124 template<typename BasicJsonType, typename T>
1125 void operator()(const BasicJsonType& j, T& val) const
1126 noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
1127 {
1128 return call(j, val, priority_tag<1> {});
1129 }
1130 };
1131
1132 // taken from ranges-v3
1133 template<typename T>
1134 struct static_const
1135 {
1136 static constexpr T value{};
1137 };
1138
1139 template<typename T>
1140 constexpr T static_const<T>::value;
1141 } // namespace detail
1142
1143
1145 namespace
1146 {
1147 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1148 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1149 }
1150
1151
1159 template<typename = void, typename = void>
1160 struct adl_serializer
1161 {
1171 template<typename BasicJsonType, typename ValueType>
1172 static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
1173 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
1174 {
1175 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
1176 }
1177
1187 template<typename BasicJsonType, typename ValueType>
1188 static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
1189 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
1190 {
1191 ::nlohmann::to_json(j, std::forward<ValueType>(val));
1192 }
1193 };
1194
1195
1277 template <
1278 template<typename U, typename V, typename... Args> class ObjectType = std::map,
1279 template<typename U, typename... Args> class ArrayType = std::vector,
1280 class StringType = std::string,
1281 class BooleanType = bool,
1282 class NumberIntegerType = std::int64_t,
1283 class NumberUnsignedType = std::uint64_t,
1284 class NumberFloatType = double,
1285 template<typename U> class AllocatorType = std::allocator,
1286 template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer
1287 >
1288 class basic_json
1289 {
1290 private:
1291 template<detail::value_t> friend struct detail::external_constructor;
1293 using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
1294 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
1295 AllocatorType, JSONSerializer>;
1296
1297 public:
1298 using value_t = detail::value_t;
1299 // forward declarations
1300 template<typename U> class iter_impl;
1301 template<typename Base> class json_reverse_iterator;
1302 class json_pointer;
1303 template<typename T, typename SFINAE>
1304 using json_serializer = JSONSerializer<T, SFINAE>;
1305
1306
1308 // exceptions //
1310
1314
1316 using exception = detail::exception;
1318 using parse_error = detail::parse_error;
1320 using invalid_iterator = detail::invalid_iterator;
1322 using type_error = detail::type_error;
1324 using out_of_range = detail::out_of_range;
1326 using other_error = detail::other_error;
1327
1329
1330
1332 // container types //
1334
1339
1341 using value_type = basic_json;
1342
1344 using reference = value_type&;
1346 using const_reference = const value_type&;
1347
1349 using difference_type = std::ptrdiff_t;
1351 using size_type = std::size_t;
1352
1354 using allocator_type = AllocatorType<basic_json>;
1355
1357 using pointer = typename std::allocator_traits<allocator_type>::pointer;
1359 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
1360
1362 using iterator = iter_impl<basic_json>;
1364 using const_iterator = iter_impl<const basic_json>;
1366 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
1368 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
1369
1371
1372
1376 static allocator_type get_allocator()
1377 {
1378 return allocator_type();
1379 }
1380
1404 static basic_json meta()
1405 {
1406 basic_json result;
1407
1408 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
1409 result["name"] = "JSON for Modern C++";
1410 result["url"] = "https://github.com/nlohmann/json";
1411 result["version"] =
1412 {
1413 {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, {"patch", 1}
1414 };
1415
1416 #ifdef _WIN32
1417 result["platform"] = "win32";
1418 #elif defined __linux__
1419 result["platform"] = "linux";
1420 #elif defined __APPLE__
1421 result["platform"] = "apple";
1422 #elif defined __unix__
1423 result["platform"] = "unix";
1424 #else
1425 result["platform"] = "unknown";
1426 #endif
1427
1428 #if defined(__clang__)
1429 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
1430 #elif defined(__ICC) || defined(__INTEL_COMPILER)
1431 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
1432 #elif defined(__GNUC__) || defined(__GNUG__)
1433 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
1434 #elif defined(__HP_cc) || defined(__HP_aCC)
1435 result["compiler"] = "hp"
1436 #elif defined(__IBMCPP__)
1437 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
1438 #elif defined(_MSC_VER)
1439 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
1440 #elif defined(__PGI)
1441 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
1442 #elif defined(__SUNPRO_CC)
1443 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
1444 #else
1445 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
1446 #endif
1447
1448 #ifdef __cplusplus
1449 result["compiler"]["c++"] = std::to_string(__cplusplus);
1450 #else
1451 result["compiler"]["c++"] = "unknown";
1452 #endif
1453 return result;
1454 }
1455
1456
1458 // JSON value data types //
1460
1465
1549 using object_t = ObjectType<StringType,
1550 basic_json,
1551 std::less<StringType>,
1552 AllocatorType<std::pair<const StringType,
1553 basic_json>>>;
1554
1599 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
1600
1652 using string_t = StringType;
1653
1678 using boolean_t = BooleanType;
1679
1750 using number_integer_t = NumberIntegerType;
1751
1821 using number_unsigned_t = NumberUnsignedType;
1822
1889 using number_float_t = NumberFloatType;
1890
1892
1893 private:
1894
1896 template<typename T, typename... Args>
1897 static T* create(Args&& ... args)
1898 {
1899 AllocatorType<T> alloc;
1900 auto deleter = [&](T * object)
1901 {
1902 alloc.deallocate(object, 1);
1903 };
1904 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
1905 alloc.construct(object.get(), std::forward<Args>(args)...);
1906 assert(object != nullptr);
1907 return object.release();
1908 }
1909
1911 // JSON value storage //
1913
1938 union json_value
1939 {
1941 object_t* object;
1943 array_t* array;
1945 string_t* string;
1947 boolean_t boolean;
1949 number_integer_t number_integer;
1951 number_unsigned_t number_unsigned;
1953 number_float_t number_float;
1954
1956 json_value() = default;
1958 json_value(boolean_t v) noexcept : boolean(v) {}
1960 json_value(number_integer_t v) noexcept : number_integer(v) {}
1962 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
1964 json_value(number_float_t v) noexcept : number_float(v) {}
1966 json_value(value_t t)
1967 {
1968 switch (t)
1969 {
1970 case value_t::object:
1971 {
1972 object = create<object_t>();
1973 break;
1974 }
1975
1976 case value_t::array:
1977 {
1978 array = create<array_t>();
1979 break;
1980 }
1981
1982 case value_t::string:
1983 {
1984 string = create<string_t>("");
1985 break;
1986 }
1987
1988 case value_t::boolean:
1989 {
1990 boolean = boolean_t(false);
1991 break;
1992 }
1993
1994 case value_t::number_integer:
1995 {
1996 number_integer = number_integer_t(0);
1997 break;
1998 }
1999
2000 case value_t::number_unsigned:
2001 {
2002 number_unsigned = number_unsigned_t(0);
2003 break;
2004 }
2005
2006 case value_t::number_float:
2007 {
2008 number_float = number_float_t(0.0);
2009 break;
2010 }
2011
2012 case value_t::null:
2013 {
2014 break;
2015 }
2016
2017 default:
2018 {
2019 if (t == value_t::null)
2020 {
2021 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE
2022 }
2023 break;
2024 }
2025 }
2026 }
2027
2029 json_value(const string_t& value)
2030 {
2031 string = create<string_t>(value);
2032 }
2033
2035 json_value(const object_t& value)
2036 {
2037 object = create<object_t>(value);
2038 }
2039
2041 json_value(const array_t& value)
2042 {
2043 array = create<array_t>(value);
2044 }
2045 };
2046
2056 void assert_invariant() const
2057 {
2058 assert(m_type != value_t::object or m_value.object != nullptr);
2059 assert(m_type != value_t::array or m_value.array != nullptr);
2060 assert(m_type != value_t::string or m_value.string != nullptr);
2061 }
2062
2063 public:
2065 // JSON parser callback //
2067
2078 enum class parse_event_t : uint8_t
2079 {
2081 object_start,
2083 object_end,
2085 array_start,
2087 array_end,
2089 key,
2091 value
2092 };
2093
2146 using parser_callback_t = std::function<bool(int depth,
2147 parse_event_t event,
2148 basic_json& parsed)>;
2149
2150
2152 // constructors //
2154
2159
2184 basic_json(const value_t value_type)
2185 : m_type(value_type), m_value(value_type)
2186 {
2187 assert_invariant();
2188 }
2189
2208 basic_json(std::nullptr_t = nullptr) noexcept
2209 : basic_json(value_t::null)
2210 {
2211 assert_invariant();
2212 }
2213
2267 template<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
2268 detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
2269 not std::is_same<U, basic_json_t>::value and
2270 not detail::is_basic_json_nested_type<
2271 basic_json_t, U>::value and
2272 detail::has_to_json<basic_json, U>::value,
2273 int> = 0>
2274 basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(
2275 std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
2276 {
2277 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
2278 assert_invariant();
2279 }
2280
2352 basic_json(std::initializer_list<basic_json> init,
2353 bool type_deduction = true,
2354 value_t manual_type = value_t::array)
2355 {
2356 // check if each element is an array with two elements whose first
2357 // element is a string
2358 bool is_an_object = std::all_of(init.begin(), init.end(),
2359 [](const basic_json & element)
2360 {
2361 return element.is_array() and element.size() == 2 and element[0].is_string();
2362 });
2363
2364 // adjust type if type deduction is not wanted
2365 if (not type_deduction)
2366 {
2367 // if array is wanted, do not create an object though possible
2368 if (manual_type == value_t::array)
2369 {
2370 is_an_object = false;
2371 }
2372
2373 // if object is wanted but impossible, throw an exception
2374 if (manual_type == value_t::object and not is_an_object)
2375 {
2376 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
2377 }
2378 }
2379
2380 if (is_an_object)
2381 {
2382 // the initializer list is a list of pairs -> create object
2383 m_type = value_t::object;
2384 m_value = value_t::object;
2385
2386 std::for_each(init.begin(), init.end(), [this](const basic_json & element)
2387 {
2388 m_value.object->emplace(*(element[0].m_value.string), element[1]);
2389 });
2390 }
2391 else
2392 {
2393 // the initializer list describes an array -> create array
2394 m_type = value_t::array;
2395 m_value.array = create<array_t>(init);
2396 }
2397
2398 assert_invariant();
2399 }
2400
2435 static basic_json array(std::initializer_list<basic_json> init =
2436 std::initializer_list<basic_json>())
2437 {
2438 return basic_json(init, false, value_t::array);
2439 }
2440
2476 static basic_json object(std::initializer_list<basic_json> init =
2477 std::initializer_list<basic_json>())
2478 {
2479 return basic_json(init, false, value_t::object);
2480 }
2481
2500 basic_json(size_type cnt, const basic_json& val)
2501 : m_type(value_t::array)
2502 {
2503 m_value.array = create<array_t>(cnt, val);
2504 assert_invariant();
2505 }
2506
2549 template<class InputIT, typename std::enable_if<
2550 std::is_same<InputIT, typename basic_json_t::iterator>::value or
2551 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
2552 basic_json(InputIT first, InputIT last)
2553 {
2554 assert(first.m_object != nullptr);
2555 assert(last.m_object != nullptr);
2556
2557 // make sure iterator fits the current value
2558 if (first.m_object != last.m_object)
2559 {
2560 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
2561 }
2562
2563 // copy type from first iterator
2564 m_type = first.m_object->m_type;
2565
2566 // check if iterator range is complete for primitive values
2567 switch (m_type)
2568 {
2569 case value_t::boolean:
2570 case value_t::number_float:
2571 case value_t::number_integer:
2572 case value_t::number_unsigned:
2573 case value_t::string:
2574 {
2575 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
2576 {
2577 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
2578 }
2579 break;
2580 }
2581
2582 default:
2583 {
2584 break;
2585 }
2586 }
2587
2588 switch (m_type)
2589 {
2590 case value_t::number_integer:
2591 {
2592 m_value.number_integer = first.m_object->m_value.number_integer;
2593 break;
2594 }
2595
2596 case value_t::number_unsigned:
2597 {
2598 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2599 break;
2600 }
2601
2602 case value_t::number_float:
2603 {
2604 m_value.number_float = first.m_object->m_value.number_float;
2605 break;
2606 }
2607
2608 case value_t::boolean:
2609 {
2610 m_value.boolean = first.m_object->m_value.boolean;
2611 break;
2612 }
2613
2614 case value_t::string:
2615 {
2616 m_value = *first.m_object->m_value.string;
2617 break;
2618 }
2619
2620 case value_t::object:
2621 {
2622 m_value.object = create<object_t>(first.m_it.object_iterator,
2623 last.m_it.object_iterator);
2624 break;
2625 }
2626
2627 case value_t::array:
2628 {
2629 m_value.array = create<array_t>(first.m_it.array_iterator,
2630 last.m_it.array_iterator);
2631 break;
2632 }
2633
2634 default:
2635 {
2636 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
2637 first.m_object->type_name()));
2638 }
2639 }
2640
2641 assert_invariant();
2642 }
2643
2644
2646 // other constructors and destructor //
2648
2669 basic_json(const basic_json& other)
2670 : m_type(other.m_type)
2671 {
2672 // check of passed value is valid
2673 other.assert_invariant();
2674
2675 switch (m_type)
2676 {
2677 case value_t::object:
2678 {
2679 m_value = *other.m_value.object;
2680 break;
2681 }
2682
2683 case value_t::array:
2684 {
2685 m_value = *other.m_value.array;
2686 break;
2687 }
2688
2689 case value_t::string:
2690 {
2691 m_value = *other.m_value.string;
2692 break;
2693 }
2694
2695 case value_t::boolean:
2696 {
2697 m_value = other.m_value.boolean;
2698 break;
2699 }
2700
2701 case value_t::number_integer:
2702 {
2703 m_value = other.m_value.number_integer;
2704 break;
2705 }
2706
2707 case value_t::number_unsigned:
2708 {
2709 m_value = other.m_value.number_unsigned;
2710 break;
2711 }
2712
2713 case value_t::number_float:
2714 {
2715 m_value = other.m_value.number_float;
2716 break;
2717 }
2718
2719 default:
2720 {
2721 break;
2722 }
2723 }
2724
2725 assert_invariant();
2726 }
2727
2746 basic_json(basic_json&& other) noexcept
2747 : m_type(std::move(other.m_type)),
2748 m_value(std::move(other.m_value))
2749 {
2750 // check that passed value is valid
2751 other.assert_invariant();
2752
2753 // invalidate payload
2754 other.m_type = value_t::null;
2755 other.m_value = {};
2756
2757 assert_invariant();
2758 }
2759
2783 reference& operator=(basic_json other) noexcept (
2784 std::is_nothrow_move_constructible<value_t>::value and
2785 std::is_nothrow_move_assignable<value_t>::value and
2786 std::is_nothrow_move_constructible<json_value>::value and
2787 std::is_nothrow_move_assignable<json_value>::value
2788 )
2789 {
2790 // check that passed value is valid
2791 other.assert_invariant();
2792
2793 using std::swap;
2794 swap(m_type, other.m_type);
2795 swap(m_value, other.m_value);
2796
2797 assert_invariant();
2798 return *this;
2799 }
2800
2816 ~basic_json()
2817 {
2818 assert_invariant();
2819
2820 switch (m_type)
2821 {
2822 case value_t::object:
2823 {
2824 AllocatorType<object_t> alloc;
2825 alloc.destroy(m_value.object);
2826 alloc.deallocate(m_value.object, 1);
2827 break;
2828 }
2829
2830 case value_t::array:
2831 {
2832 AllocatorType<array_t> alloc;
2833 alloc.destroy(m_value.array);
2834 alloc.deallocate(m_value.array, 1);
2835 break;
2836 }
2837
2838 case value_t::string:
2839 {
2840 AllocatorType<string_t> alloc;
2841 alloc.destroy(m_value.string);
2842 alloc.deallocate(m_value.string, 1);
2843 break;
2844 }
2845
2846 default:
2847 {
2848 // all other types need no specific destructor
2849 break;
2850 }
2851 }
2852 }
2853
2855
2856 public:
2858 // object inspection //
2860
2864
2888 string_t dump(const int indent = -1) const
2889 {
2890 std::stringstream ss;
2891 serializer s(ss);
2892
2893 if (indent >= 0)
2894 {
2895 s.dump(*this, true, static_cast<unsigned int>(indent));
2896 }
2897 else
2898 {
2899 s.dump(*this, false, 0);
2900 }
2901
2902 return ss.str();
2903 }
2904
2923 constexpr value_t type() const noexcept
2924 {
2925 return m_type;
2926 }
2927
2953 constexpr bool is_primitive() const noexcept
2954 {
2955 return is_null() or is_string() or is_boolean() or is_number();
2956 }
2957
2980 constexpr bool is_structured() const noexcept
2981 {
2982 return is_array() or is_object();
2983 }
2984
3002 constexpr bool is_null() const noexcept
3003 {
3004 return m_type == value_t::null;
3005 }
3006
3024 constexpr bool is_boolean() const noexcept
3025 {
3026 return m_type == value_t::boolean;
3027 }
3028
3054 constexpr bool is_number() const noexcept
3055 {
3056 return is_number_integer() or is_number_float();
3057 }
3058
3083 constexpr bool is_number_integer() const noexcept
3084 {
3085 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
3086 }
3087
3111 constexpr bool is_number_unsigned() const noexcept
3112 {
3113 return m_type == value_t::number_unsigned;
3114 }
3115
3139 constexpr bool is_number_float() const noexcept
3140 {
3141 return m_type == value_t::number_float;
3142 }
3143
3161 constexpr bool is_object() const noexcept
3162 {
3163 return m_type == value_t::object;
3164 }
3165
3183 constexpr bool is_array() const noexcept
3184 {
3185 return m_type == value_t::array;
3186 }
3187
3205 constexpr bool is_string() const noexcept
3206 {
3207 return m_type == value_t::string;
3208 }
3209
3232 constexpr bool is_discarded() const noexcept
3233 {
3234 return m_type == value_t::discarded;
3235 }
3236
3255 constexpr operator value_t() const noexcept
3256 {
3257 return m_type;
3258 }
3259
3261
3262 private:
3264 // value access //
3266
3268 boolean_t get_impl(boolean_t* /*unused*/) const
3269 {
3270 if (is_boolean())
3271 {
3272 return m_value.boolean;
3273 }
3274
3275 JSON_THROW(type_error::create(302, "type must be boolean, but is " + type_name()));
3276 }
3277
3279 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
3280 {
3281 return is_object() ? m_value.object : nullptr;
3282 }
3283
3285 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
3286 {
3287 return is_object() ? m_value.object : nullptr;
3288 }
3289
3291 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
3292 {
3293 return is_array() ? m_value.array : nullptr;
3294 }
3295
3297 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
3298 {
3299 return is_array() ? m_value.array : nullptr;
3300 }
3301
3303 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
3304 {
3305 return is_string() ? m_value.string : nullptr;
3306 }
3307
3309 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
3310 {
3311 return is_string() ? m_value.string : nullptr;
3312 }
3313
3315 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
3316 {
3317 return is_boolean() ? &m_value.boolean : nullptr;
3318 }
3319
3321 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
3322 {
3323 return is_boolean() ? &m_value.boolean : nullptr;
3324 }
3325
3327 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
3328 {
3329 return is_number_integer() ? &m_value.number_integer : nullptr;
3330 }
3331
3333 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
3334 {
3335 return is_number_integer() ? &m_value.number_integer : nullptr;
3336 }
3337
3339 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
3340 {
3341 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3342 }
3343
3345 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
3346 {
3347 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3348 }
3349
3351 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
3352 {
3353 return is_number_float() ? &m_value.number_float : nullptr;
3354 }
3355
3357 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
3358 {
3359 return is_number_float() ? &m_value.number_float : nullptr;
3360 }
3361
3373 template<typename ReferenceType, typename ThisType>
3374 static ReferenceType get_ref_impl(ThisType& obj)
3375 {
3376 // helper type
3377 using PointerType = typename std::add_pointer<ReferenceType>::type;
3378
3379 // delegate the call to get_ptr<>()
3380 auto ptr = obj.template get_ptr<PointerType>();
3381
3382 if (ptr != nullptr)
3383 {
3384 return *ptr;
3385 }
3386
3387 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + obj.type_name()));
3388 }
3389
3390 public:
3394
3409 template <
3410 typename BasicJsonType,
3411 detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,
3412 basic_json_t>::value,
3413 int> = 0 >
3414 basic_json get() const
3415 {
3416 return *this;
3417 }
3418
3458 template <
3459 typename ValueTypeCV,
3460 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3461 detail::enable_if_t <
3462 not std::is_same<basic_json_t, ValueType>::value and
3463 detail::has_from_json<basic_json_t, ValueType>::value and
3464 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
3465 int > = 0 >
3466 ValueType get() const noexcept(noexcept(
3467 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
3468 {
3469 // we cannot static_assert on ValueTypeCV being non-const, because
3470 // there is support for get<const basic_json_t>(), which is why we
3471 // still need the uncvref
3472 static_assert(not std::is_reference<ValueTypeCV>::value,
3473 "get() cannot be used with reference types, you might want to use get_ref()");
3474 static_assert(std::is_default_constructible<ValueType>::value,
3475 "types must be DefaultConstructible when used with get()");
3476
3477 ValueType ret;
3478 JSONSerializer<ValueType>::from_json(*this, ret);
3479 return ret;
3480 }
3481
3513 template <
3514 typename ValueTypeCV,
3515 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3516 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
3517 detail::has_non_default_from_json<basic_json_t,
3518 ValueType>::value, int> = 0 >
3519 ValueType get() const noexcept(noexcept(
3520 JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
3521 {
3522 static_assert(not std::is_reference<ValueTypeCV>::value,
3523 "get() cannot be used with reference types, you might want to use get_ref()");
3524 return JSONSerializer<ValueTypeCV>::from_json(*this);
3525 }
3526
3554 template<typename PointerType, typename std::enable_if<
3555 std::is_pointer<PointerType>::value, int>::type = 0>
3556 PointerType get() noexcept
3557 {
3558 // delegate the call to get_ptr
3559 return get_ptr<PointerType>();
3560 }
3561
3566 template<typename PointerType, typename std::enable_if<
3567 std::is_pointer<PointerType>::value, int>::type = 0>
3568 constexpr const PointerType get() const noexcept
3569 {
3570 // delegate the call to get_ptr
3571 return get_ptr<PointerType>();
3572 }
3573
3600 template<typename PointerType, typename std::enable_if<
3601 std::is_pointer<PointerType>::value, int>::type = 0>
3602 PointerType get_ptr() noexcept
3603 {
3604 // get the type of the PointerType (remove pointer and const)
3605 using pointee_t = typename std::remove_const<typename
3606 std::remove_pointer<typename
3607 std::remove_const<PointerType>::type>::type>::type;
3608 // make sure the type matches the allowed types
3609 static_assert(
3610 std::is_same<object_t, pointee_t>::value
3611 or std::is_same<array_t, pointee_t>::value
3612 or std::is_same<string_t, pointee_t>::value
3613 or std::is_same<boolean_t, pointee_t>::value
3614 or std::is_same<number_integer_t, pointee_t>::value
3615 or std::is_same<number_unsigned_t, pointee_t>::value
3616 or std::is_same<number_float_t, pointee_t>::value
3617 , "incompatible pointer type");
3618
3619 // delegate the call to get_impl_ptr<>()
3620 return get_impl_ptr(static_cast<PointerType>(nullptr));
3621 }
3622
3627 template<typename PointerType, typename std::enable_if<
3628 std::is_pointer<PointerType>::value and
3629 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3630 constexpr const PointerType get_ptr() const noexcept
3631 {
3632 // get the type of the PointerType (remove pointer and const)
3633 using pointee_t = typename std::remove_const<typename
3634 std::remove_pointer<typename
3635 std::remove_const<PointerType>::type>::type>::type;
3636 // make sure the type matches the allowed types
3637 static_assert(
3638 std::is_same<object_t, pointee_t>::value
3639 or std::is_same<array_t, pointee_t>::value
3640 or std::is_same<string_t, pointee_t>::value
3641 or std::is_same<boolean_t, pointee_t>::value
3642 or std::is_same<number_integer_t, pointee_t>::value
3643 or std::is_same<number_unsigned_t, pointee_t>::value
3644 or std::is_same<number_float_t, pointee_t>::value
3645 , "incompatible pointer type");
3646
3647 // delegate the call to get_impl_ptr<>() const
3648 return get_impl_ptr(static_cast<const PointerType>(nullptr));
3649 }
3650
3677 template<typename ReferenceType, typename std::enable_if<
3678 std::is_reference<ReferenceType>::value, int>::type = 0>
3679 ReferenceType get_ref()
3680 {
3681 // delegate call to get_ref_impl
3682 return get_ref_impl<ReferenceType>(*this);
3683 }
3684
3689 template<typename ReferenceType, typename std::enable_if<
3690 std::is_reference<ReferenceType>::value and
3691 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3692 ReferenceType get_ref() const
3693 {
3694 // delegate call to get_ref_impl
3695 return get_ref_impl<ReferenceType>(*this);
3696 }
3697
3727 template < typename ValueType, typename std::enable_if <
3728 not std::is_pointer<ValueType>::value and
3729 not std::is_same<ValueType, typename string_t::value_type>::value
3730 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
3731 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3732 #endif
3733 #if defined(_MSC_VER) && _MSC_VER >1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1 // fix for issue #464
3734 and not std::is_same<ValueType, typename std::string_view>::value
3735 #endif
3736 , int >::type = 0 >
3737 operator ValueType() const
3738 {
3739 // delegate the call to get<>() const
3740 return get<ValueType>();
3741 }
3742
3744
3745
3747 // element access //
3749
3753
3780 reference at(size_type idx)
3781 {
3782 // at only works for arrays
3783 if (is_array())
3784 {
3785 JSON_TRY
3786 {
3787 return m_value.array->at(idx);
3788 }
3789 JSON_CATCH (std::out_of_range&)
3790 {
3791 // create better exception explanation
3792 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
3793 }
3794 }
3795 else
3796 {
3797 JSON_THROW(type_error::create(304, "cannot use at() with " + type_name()));
3798 }
3799 }
3800
3827 const_reference at(size_type idx) const
3828 {
3829 // at only works for arrays
3830 if (is_array())
3831 {
3832 JSON_TRY
3833 {
3834 return m_value.array->at(idx);
3835 }
3836 JSON_CATCH (std::out_of_range&)
3837 {
3838 // create better exception explanation
3839 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
3840 }
3841 }
3842 else
3843 {
3844 JSON_THROW(type_error::create(304, "cannot use at() with " + type_name()));
3845 }
3846 }
3847
3878 reference at(const typename object_t::key_type& key)
3879 {
3880 // at only works for objects
3881 if (is_object())
3882 {
3883 JSON_TRY
3884 {
3885 return m_value.object->at(key);
3886 }
3887 JSON_CATCH (std::out_of_range&)
3888 {
3889 // create better exception explanation
3890 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
3891 }
3892 }
3893 else
3894 {
3895 JSON_THROW(type_error::create(304, "cannot use at() with " + type_name()));
3896 }
3897 }
3898
3929 const_reference at(const typename object_t::key_type& key) const
3930 {
3931 // at only works for objects
3932 if (is_object())
3933 {
3934 JSON_TRY
3935 {
3936 return m_value.object->at(key);
3937 }
3938 JSON_CATCH (std::out_of_range&)
3939 {
3940 // create better exception explanation
3941 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
3942 }
3943 }
3944 else
3945 {
3946 JSON_THROW(type_error::create(304, "cannot use at() with " + type_name()));
3947 }
3948 }
3949
3975 reference operator[](size_type idx)
3976 {
3977 // implicitly convert null value to an empty array
3978 if (is_null())
3979 {
3980 m_type = value_t::array;
3981 m_value.array = create<array_t>();
3982 assert_invariant();
3983 }
3984
3985 // operator[] only works for arrays
3986 if (is_array())
3987 {
3988 // fill up array with null values if given idx is outside range
3989 if (idx >= m_value.array->size())
3990 {
3991 m_value.array->insert(m_value.array->end(),
3992 idx - m_value.array->size() + 1,
3993 basic_json());
3994 }
3995
3996 return m_value.array->operator[](idx);
3997 }
3998
3999 JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name()));
4000 }
4001
4021 const_reference operator[](size_type idx) const
4022 {
4023 // const operator[] only works for arrays
4024 if (is_array())
4025 {
4026 return m_value.array->operator[](idx);
4027 }
4028
4029 JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name()));
4030 }
4031
4059 reference operator[](const typename object_t::key_type& key)
4060 {
4061 // implicitly convert null value to an empty object
4062 if (is_null())
4063 {
4064 m_type = value_t::object;
4065 m_value.object = create<object_t>();
4066 assert_invariant();
4067 }
4068
4069 // operator[] only works for objects
4070 if (is_object())
4071 {
4072 return m_value.object->operator[](key);
4073 }
4074
4075 JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name()));
4076 }
4077
4108 const_reference operator[](const typename object_t::key_type& key) const
4109 {
4110 // const operator[] only works for objects
4111 if (is_object())
4112 {
4113 assert(m_value.object->find(key) != m_value.object->end());
4114 return m_value.object->find(key)->second;
4115 }
4116
4117 JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name()));
4118 }
4119
4147 template<typename T, std::size_t n>
4148 reference operator[](T * (&key)[n])
4149 {
4150 return operator[](static_cast<const T>(key));
4151 }
4152
4182 template<typename T, std::size_t n>
4183 const_reference operator[](T * (&key)[n]) const
4184 {
4185 return operator[](static_cast<const T>(key));
4186 }
4187
4215 template<typename T>
4216 reference operator[](T* key)
4217 {
4218 // implicitly convert null to object
4219 if (is_null())
4220 {
4221 m_type = value_t::object;
4222 m_value = value_t::object;
4223 assert_invariant();
4224 }
4225
4226 // at only works for objects
4227 if (is_object())
4228 {
4229 return m_value.object->operator[](key);
4230 }
4231
4232 JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name()));
4233 }
4234
4265 template<typename T>
4266 const_reference operator[](T* key) const
4267 {
4268 // at only works for objects
4269 if (is_object())
4270 {
4271 assert(m_value.object->find(key) != m_value.object->end());
4272 return m_value.object->find(key)->second;
4273 }
4274
4275 JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name()));
4276 }
4277
4326 template<class ValueType, typename std::enable_if<
4327 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4328 ValueType value(const typename object_t::key_type& key, ValueType default_value) const
4329 {
4330 // at only works for objects
4331 if (is_object())
4332 {
4333 // if key is found, return value and given default value otherwise
4334 const auto it = find(key);
4335 if (it != end())
4336 {
4337 return *it;
4338 }
4339
4340 return default_value;
4341 }
4342 else
4343 {
4344 JSON_THROW(type_error::create(306, "cannot use value() with " + type_name()));
4345 }
4346 }
4347
4352 string_t value(const typename object_t::key_type& key, const char* default_value) const
4353 {
4354 return value(key, string_t(default_value));
4355 }
4356
4398 template<class ValueType, typename std::enable_if<
4399 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4400 ValueType value(const json_pointer& ptr, ValueType default_value) const
4401 {
4402 // at only works for objects
4403 if (is_object())
4404 {
4405 // if pointer resolves a value, return it or use default value
4406 JSON_TRY
4407 {
4408 return ptr.get_checked(this);
4409 }
4410 JSON_CATCH (out_of_range&)
4411 {
4412 return default_value;
4413 }
4414 }
4415
4416 JSON_THROW(type_error::create(306, "cannot use value() with " + type_name()));
4417 }
4418
4423 string_t value(const json_pointer& ptr, const char* default_value) const
4424 {
4425 return value(ptr, string_t(default_value));
4426 }
4427
4453 reference front()
4454 {
4455 return *begin();
4456 }
4457
4461 const_reference front() const
4462 {
4463 return *cbegin();
4464 }
4465
4497 reference back()
4498 {
4499 auto tmp = end();
4500 --tmp;
4501 return *tmp;
4502 }
4503
4507 const_reference back() const
4508 {
4509 auto tmp = cend();
4510 --tmp;
4511 return *tmp;
4512 }
4513
4560 template<class IteratorType, typename std::enable_if<
4561 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4562 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4563 = 0>
4564 IteratorType erase(IteratorType pos)
4565 {
4566 // make sure iterator fits the current value
4567 if (this != pos.m_object)
4568 {
4569 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
4570 }
4571
4572 IteratorType result = end();
4573
4574 switch (m_type)
4575 {
4576 case value_t::boolean:
4577 case value_t::number_float:
4578 case value_t::number_integer:
4579 case value_t::number_unsigned:
4580 case value_t::string:
4581 {
4582 if (not pos.m_it.primitive_iterator.is_begin())
4583 {
4584 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
4585 }
4586
4587 if (is_string())
4588 {
4589 AllocatorType<string_t> alloc;
4590 alloc.destroy(m_value.string);
4591 alloc.deallocate(m_value.string, 1);
4592 m_value.string = nullptr;
4593 }
4594
4595 m_type = value_t::null;
4596 assert_invariant();
4597 break;
4598 }
4599
4600 case value_t::object:
4601 {
4602 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4603 break;
4604 }
4605
4606 case value_t::array:
4607 {
4608 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4609 break;
4610 }
4611
4612 default:
4613 {
4614 JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name()));
4615 }
4616 }
4617
4618 return result;
4619 }
4620
4667 template<class IteratorType, typename std::enable_if<
4668 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4669 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4670 = 0>
4671 IteratorType erase(IteratorType first, IteratorType last)
4672 {
4673 // make sure iterator fits the current value
4674 if (this != first.m_object or this != last.m_object)
4675 {
4676 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
4677 }
4678
4679 IteratorType result = end();
4680
4681 switch (m_type)
4682 {
4683 case value_t::boolean:
4684 case value_t::number_float:
4685 case value_t::number_integer:
4686 case value_t::number_unsigned:
4687 case value_t::string:
4688 {
4689 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4690 {
4691 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
4692 }
4693
4694 if (is_string())
4695 {
4696 AllocatorType<string_t> alloc;
4697 alloc.destroy(m_value.string);
4698 alloc.deallocate(m_value.string, 1);
4699 m_value.string = nullptr;
4700 }
4701
4702 m_type = value_t::null;
4703 assert_invariant();
4704 break;
4705 }
4706
4707 case value_t::object:
4708 {
4709 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4710 last.m_it.object_iterator);
4711 break;
4712 }
4713
4714 case value_t::array:
4715 {
4716 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4717 last.m_it.array_iterator);
4718 break;
4719 }
4720
4721 default:
4722 {
4723 JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name()));
4724 }
4725 }
4726
4727 return result;
4728 }
4729
4759 size_type erase(const typename object_t::key_type& key)
4760 {
4761 // this erase only works for objects
4762 if (is_object())
4763 {
4764 return m_value.object->erase(key);
4765 }
4766
4767 JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name()));
4768 }
4769
4794 void erase(const size_type idx)
4795 {
4796 // this erase only works for arrays
4797 if (is_array())
4798 {
4799 if (idx >= size())
4800 {
4801 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
4802 }
4803
4804 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4805 }
4806 else
4807 {
4808 JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name()));
4809 }
4810 }
4811
4813
4814
4816 // lookup //
4818
4821
4844 iterator find(typename object_t::key_type key)
4845 {
4846 auto result = end();
4847
4848 if (is_object())
4849 {
4850 result.m_it.object_iterator = m_value.object->find(key);
4851 }
4852
4853 return result;
4854 }
4855
4860 const_iterator find(typename object_t::key_type key) const
4861 {
4862 auto result = cend();
4863
4864 if (is_object())
4865 {
4866 result.m_it.object_iterator = m_value.object->find(key);
4867 }
4868
4869 return result;
4870 }
4871
4893 size_type count(typename object_t::key_type key) const
4894 {
4895 // return 0 for all nonobject types
4896 return is_object() ? m_value.object->count(key) : 0;
4897 }
4898
4900
4901
4903 // iterators //
4905
4908
4933 iterator begin() noexcept
4934 {
4935 iterator result(this);
4936 result.set_begin();
4937 return result;
4938 }
4939
4943 const_iterator begin() const noexcept
4944 {
4945 return cbegin();
4946 }
4947
4973 const_iterator cbegin() const noexcept
4974 {
4975 const_iterator result(this);
4976 result.set_begin();
4977 return result;
4978 }
4979
5004 iterator end() noexcept
5005 {
5006 iterator result(this);
5007 result.set_end();
5008 return result;
5009 }
5010
5014 const_iterator end() const noexcept
5015 {
5016 return cend();
5017 }
5018
5044 const_iterator cend() const noexcept
5045 {
5046 const_iterator result(this);
5047 result.set_end();
5048 return result;
5049 }
5050
5074 reverse_iterator rbegin() noexcept
5075 {
5076 return reverse_iterator(end());
5077 }
5078
5082 const_reverse_iterator rbegin() const noexcept
5083 {
5084 return crbegin();
5085 }
5086
5111 reverse_iterator rend() noexcept
5112 {
5113 return reverse_iterator(begin());
5114 }
5115
5119 const_reverse_iterator rend() const noexcept
5120 {
5121 return crend();
5122 }
5123
5148 const_reverse_iterator crbegin() const noexcept
5149 {
5150 return const_reverse_iterator(cend());
5151 }
5152
5177 const_reverse_iterator crend() const noexcept
5178 {
5179 return const_reverse_iterator(cbegin());
5180 }
5181
5182 private:
5183 // forward declaration
5184 template<typename IteratorType> class iteration_proxy;
5185
5186 public:
5198 static iteration_proxy<iterator> iterator_wrapper(reference cont)
5199 {
5200 return iteration_proxy<iterator>(cont);
5201 }
5202
5206 static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
5207 {
5208 return iteration_proxy<const_iterator>(cont);
5209 }
5210
5212
5213
5215 // capacity //
5217
5220
5258 bool empty() const noexcept
5259 {
5260 switch (m_type)
5261 {
5262 case value_t::null:
5263 {
5264 // null values are empty
5265 return true;
5266 }
5267
5268 case value_t::array:
5269 {
5270 // delegate call to array_t::empty()
5271 return m_value.array->empty();
5272 }
5273
5274 case value_t::object:
5275 {
5276 // delegate call to object_t::empty()
5277 return m_value.object->empty();
5278 }
5279
5280 default:
5281 {
5282 // all other types are nonempty
5283 return false;
5284 }
5285 }
5286 }
5287
5326 size_type size() const noexcept
5327 {
5328 switch (m_type)
5329 {
5330 case value_t::null:
5331 {
5332 // null values are empty
5333 return 0;
5334 }
5335
5336 case value_t::array:
5337 {
5338 // delegate call to array_t::size()
5339 return m_value.array->size();
5340 }
5341
5342 case value_t::object:
5343 {
5344 // delegate call to object_t::size()
5345 return m_value.object->size();
5346 }
5347
5348 default:
5349 {
5350 // all other types have size 1
5351 return 1;
5352 }
5353 }
5354 }
5355
5392 size_type max_size() const noexcept
5393 {
5394 switch (m_type)
5395 {
5396 case value_t::array:
5397 {
5398 // delegate call to array_t::max_size()
5399 return m_value.array->max_size();
5400 }
5401
5402 case value_t::object:
5403 {
5404 // delegate call to object_t::max_size()
5405 return m_value.object->max_size();
5406 }
5407
5408 default:
5409 {
5410 // all other types have max_size() == size()
5411 return size();
5412 }
5413 }
5414 }
5415
5417
5418
5420 // modifiers //
5422
5425
5448 void clear() noexcept
5449 {
5450 switch (m_type)
5451 {
5452 case value_t::number_integer:
5453 {
5454 m_value.number_integer = 0;
5455 break;
5456 }
5457
5458 case value_t::number_unsigned:
5459 {
5460 m_value.number_unsigned = 0;
5461 break;
5462 }
5463
5464 case value_t::number_float:
5465 {
5466 m_value.number_float = 0.0;
5467 break;
5468 }
5469
5470 case value_t::boolean:
5471 {
5472 m_value.boolean = false;
5473 break;
5474 }
5475
5476 case value_t::string:
5477 {
5478 m_value.string->clear();
5479 break;
5480 }
5481
5482 case value_t::array:
5483 {
5484 m_value.array->clear();
5485 break;
5486 }
5487
5488 case value_t::object:
5489 {
5490 m_value.object->clear();
5491 break;
5492 }
5493
5494 default:
5495 {
5496 break;
5497 }
5498 }
5499 }
5500
5521 void push_back(basic_json&& val)
5522 {
5523 // push_back only works for null objects or arrays
5524 if (not(is_null() or is_array()))
5525 {
5526 JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name()));
5527 }
5528
5529 // transform null object into an array
5530 if (is_null())
5531 {
5532 m_type = value_t::array;
5533 m_value = value_t::array;
5534 assert_invariant();
5535 }
5536
5537 // add element to array (move semantics)
5538 m_value.array->push_back(std::move(val));
5539 // invalidate object
5540 val.m_type = value_t::null;
5541 }
5542
5547 reference operator+=(basic_json&& val)
5548 {
5549 push_back(std::move(val));
5550 return *this;
5551 }
5552
5557 void push_back(const basic_json& val)
5558 {
5559 // push_back only works for null objects or arrays
5560 if (not(is_null() or is_array()))
5561 {
5562 JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name()));
5563 }
5564
5565 // transform null object into an array
5566 if (is_null())
5567 {
5568 m_type = value_t::array;
5569 m_value = value_t::array;
5570 assert_invariant();
5571 }
5572
5573 // add element to array
5574 m_value.array->push_back(val);
5575 }
5576
5581 reference operator+=(const basic_json& val)
5582 {
5583 push_back(val);
5584 return *this;
5585 }
5586
5607 void push_back(const typename object_t::value_type& val)
5608 {
5609 // push_back only works for null objects or objects
5610 if (not(is_null() or is_object()))
5611 {
5612 JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name()));
5613 }
5614
5615 // transform null object into an object
5616 if (is_null())
5617 {
5618 m_type = value_t::object;
5619 m_value = value_t::object;
5620 assert_invariant();
5621 }
5622
5623 // add element to array
5624 m_value.object->insert(val);
5625 }
5626
5631 reference operator+=(const typename object_t::value_type& val)
5632 {
5633 push_back(val);
5634 return *this;
5635 }
5636
5662 void push_back(std::initializer_list<basic_json> init)
5663 {
5664 if (is_object() and init.size() == 2 and init.begin()->is_string())
5665 {
5666 const string_t key = *init.begin();
5667 push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5668 }
5669 else
5670 {
5671 push_back(basic_json(init));
5672 }
5673 }
5674
5679 reference operator+=(std::initializer_list<basic_json> init)
5680 {
5681 push_back(init);
5682 return *this;
5683 }
5684
5706 template<class... Args>
5707 void emplace_back(Args&& ... args)
5708 {
5709 // emplace_back only works for null objects or arrays
5710 if (not(is_null() or is_array()))
5711 {
5712 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + type_name()));
5713 }
5714
5715 // transform null object into an array
5716 if (is_null())
5717 {
5718 m_type = value_t::array;
5719 m_value = value_t::array;
5720 assert_invariant();
5721 }
5722
5723 // add element to array (perfect forwarding)
5724 m_value.array->emplace_back(std::forward<Args>(args)...);
5725 }
5726
5754 template<class... Args>
5755 std::pair<iterator, bool> emplace(Args&& ... args)
5756 {
5757 // emplace only works for null objects or arrays
5758 if (not(is_null() or is_object()))
5759 {
5760 JSON_THROW(type_error::create(311, "cannot use emplace() with " + type_name()));
5761 }
5762
5763 // transform null object into an object
5764 if (is_null())
5765 {
5766 m_type = value_t::object;
5767 m_value = value_t::object;
5768 assert_invariant();
5769 }
5770
5771 // add element to array (perfect forwarding)
5772 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5773 // create result iterator and set iterator to the result of emplace
5774 auto it = begin();
5775 it.m_it.object_iterator = res.first;
5776
5777 // return pair of iterator and boolean
5778 return {it, res.second};
5779 }
5780
5803 iterator insert(const_iterator pos, const basic_json& val)
5804 {
5805 // insert only works for arrays
5806 if (is_array())
5807 {
5808 // check if iterator pos fits to this JSON value
5809 if (pos.m_object != this)
5810 {
5811 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5812 }
5813
5814 // insert to array and return iterator
5815 iterator result(this);
5816 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5817 return result;
5818 }
5819
5820 JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name()));
5821 }
5822
5827 iterator insert(const_iterator pos, basic_json&& val)
5828 {
5829 return insert(pos, val);
5830 }
5831
5856 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
5857 {
5858 // insert only works for arrays
5859 if (is_array())
5860 {
5861 // check if iterator pos fits to this JSON value
5862 if (pos.m_object != this)
5863 {
5864 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5865 }
5866
5867 // insert to array and return iterator
5868 iterator result(this);
5869 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5870 return result;
5871 }
5872
5873 JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name()));
5874 }
5875
5906 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
5907 {
5908 // insert only works for arrays
5909 if (not is_array())
5910 {
5911 JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name()));
5912 }
5913
5914 // check if iterator pos fits to this JSON value
5915 if (pos.m_object != this)
5916 {
5917 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5918 }
5919
5920 // check if range iterators belong to the same JSON object
5921 if (first.m_object != last.m_object)
5922 {
5923 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
5924 }
5925
5926 if (first.m_object == this or last.m_object == this)
5927 {
5928 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
5929 }
5930
5931 // insert to array and return iterator
5932 iterator result(this);
5933 result.m_it.array_iterator = m_value.array->insert(
5934 pos.m_it.array_iterator,
5935 first.m_it.array_iterator,
5936 last.m_it.array_iterator);
5937 return result;
5938 }
5939
5964 iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5965 {
5966 // insert only works for arrays
5967 if (not is_array())
5968 {
5969 JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name()));
5970 }
5971
5972 // check if iterator pos fits to this JSON value
5973 if (pos.m_object != this)
5974 {
5975 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5976 }
5977
5978 // insert to array and return iterator
5979 iterator result(this);
5980 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5981 return result;
5982 }
5983
6007 void insert(const_iterator first, const_iterator last)
6008 {
6009 // insert only works for objects
6010 if (not is_object())
6011 {
6012 JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name()));
6013 }
6014
6015 // check if range iterators belong to the same JSON object
6016 if (first.m_object != last.m_object)
6017 {
6018 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
6019 }
6020
6021 // passed iterators must belong to objects
6022 if (not first.m_object->is_object() or not first.m_object->is_object())
6023 {
6024 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
6025 }
6026
6027 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
6028 }
6029
6047 void swap(reference other) noexcept (
6048 std::is_nothrow_move_constructible<value_t>::value and
6049 std::is_nothrow_move_assignable<value_t>::value and
6050 std::is_nothrow_move_constructible<json_value>::value and
6051 std::is_nothrow_move_assignable<json_value>::value
6052 )
6053 {
6054 std::swap(m_type, other.m_type);
6055 std::swap(m_value, other.m_value);
6056 assert_invariant();
6057 }
6058
6079 void swap(array_t& other)
6080 {
6081 // swap only works for arrays
6082 if (is_array())
6083 {
6084 std::swap(*(m_value.array), other);
6085 }
6086 else
6087 {
6088 JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name()));
6089 }
6090 }
6091
6112 void swap(object_t& other)
6113 {
6114 // swap only works for objects
6115 if (is_object())
6116 {
6117 std::swap(*(m_value.object), other);
6118 }
6119 else
6120 {
6121 JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name()));
6122 }
6123 }
6124
6145 void swap(string_t& other)
6146 {
6147 // swap only works for strings
6148 if (is_string())
6149 {
6150 std::swap(*(m_value.string), other);
6151 }
6152 else
6153 {
6154 JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name()));
6155 }
6156 }
6157
6159
6160 public:
6162 // lexicographical comparison operators //
6164
6167
6195 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
6196 {
6197 const auto lhs_type = lhs.type();
6198 const auto rhs_type = rhs.type();
6199
6200 if (lhs_type == rhs_type)
6201 {
6202 switch (lhs_type)
6203 {
6204 case value_t::array:
6205 {
6206 return *lhs.m_value.array == *rhs.m_value.array;
6207 }
6208 case value_t::object:
6209 {
6210 return *lhs.m_value.object == *rhs.m_value.object;
6211 }
6212 case value_t::null:
6213 {
6214 return true;
6215 }
6216 case value_t::string:
6217 {
6218 return *lhs.m_value.string == *rhs.m_value.string;
6219 }
6220 case value_t::boolean:
6221 {
6222 return lhs.m_value.boolean == rhs.m_value.boolean;
6223 }
6224 case value_t::number_integer:
6225 {
6226 return lhs.m_value.number_integer == rhs.m_value.number_integer;
6227 }
6228 case value_t::number_unsigned:
6229 {
6230 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
6231 }
6232 case value_t::number_float:
6233 {
6234 return lhs.m_value.number_float == rhs.m_value.number_float;
6235 }
6236 default:
6237 {
6238 return false;
6239 }
6240 }
6241 }
6242 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
6243 {
6244 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
6245 }
6246 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
6247 {
6248 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
6249 }
6250 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
6251 {
6252 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
6253 }
6254 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
6255 {
6256 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
6257 }
6258 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
6259 {
6260 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
6261 }
6262 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
6263 {
6264 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6265 }
6266
6267 return false;
6268 }
6269
6274 template<typename ScalarType, typename std::enable_if<
6275 std::is_scalar<ScalarType>::value, int>::type = 0>
6276 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
6277 {
6278 return (lhs == basic_json(rhs));
6279 }
6280
6285 template<typename ScalarType, typename std::enable_if<
6286 std::is_scalar<ScalarType>::value, int>::type = 0>
6287 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
6288 {
6289 return (basic_json(lhs) == rhs);
6290 }
6291
6308 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
6309 {
6310 return not (lhs == rhs);
6311 }
6312
6317 template<typename ScalarType, typename std::enable_if<
6318 std::is_scalar<ScalarType>::value, int>::type = 0>
6319 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
6320 {
6321 return (lhs != basic_json(rhs));
6322 }
6323
6328 template<typename ScalarType, typename std::enable_if<
6329 std::is_scalar<ScalarType>::value, int>::type = 0>
6330 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
6331 {
6332 return (basic_json(lhs) != rhs);
6333 }
6334
6359 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
6360 {
6361 const auto lhs_type = lhs.type();
6362 const auto rhs_type = rhs.type();
6363
6364 if (lhs_type == rhs_type)
6365 {
6366 switch (lhs_type)
6367 {
6368 case value_t::array:
6369 {
6370 return *lhs.m_value.array < *rhs.m_value.array;
6371 }
6372 case value_t::object:
6373 {
6374 return *lhs.m_value.object < *rhs.m_value.object;
6375 }
6376 case value_t::null:
6377 {
6378 return false;
6379 }
6380 case value_t::string:
6381 {
6382 return *lhs.m_value.string < *rhs.m_value.string;
6383 }
6384 case value_t::boolean:
6385 {
6386 return lhs.m_value.boolean < rhs.m_value.boolean;
6387 }
6388 case value_t::number_integer:
6389 {
6390 return lhs.m_value.number_integer < rhs.m_value.number_integer;
6391 }
6392 case value_t::number_unsigned:
6393 {
6394 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
6395 }
6396 case value_t::number_float:
6397 {
6398 return lhs.m_value.number_float < rhs.m_value.number_float;
6399 }
6400 default:
6401 {
6402 return false;
6403 }
6404 }
6405 }
6406 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
6407 {
6408 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
6409 }
6410 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
6411 {
6412 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
6413 }
6414 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
6415 {
6416 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
6417 }
6418 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
6419 {
6420 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
6421 }
6422 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
6423 {
6424 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6425 }
6426 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
6427 {
6428 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
6429 }
6430
6431 // We only reach this line if we cannot compare values. In that case,
6432 // we compare types. Note we have to call the operator explicitly,
6433 // because MSVC has problems otherwise.
6434 return operator<(lhs_type, rhs_type);
6435 }
6436
6441 template<typename ScalarType, typename std::enable_if<
6442 std::is_scalar<ScalarType>::value, int>::type = 0>
6443 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
6444 {
6445 return (lhs < basic_json(rhs));
6446 }
6447
6452 template<typename ScalarType, typename std::enable_if<
6453 std::is_scalar<ScalarType>::value, int>::type = 0>
6454 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
6455 {
6456 return (basic_json(lhs) < rhs);
6457 }
6458
6476 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
6477 {
6478 return not (rhs < lhs);
6479 }
6480
6485 template<typename ScalarType, typename std::enable_if<
6486 std::is_scalar<ScalarType>::value, int>::type = 0>
6487 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
6488 {
6489 return (lhs <= basic_json(rhs));
6490 }
6491
6496 template<typename ScalarType, typename std::enable_if<
6497 std::is_scalar<ScalarType>::value, int>::type = 0>
6498 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
6499 {
6500 return (basic_json(lhs) <= rhs);
6501 }
6502
6520 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
6521 {
6522 return not (lhs <= rhs);
6523 }
6524
6529 template<typename ScalarType, typename std::enable_if<
6530 std::is_scalar<ScalarType>::value, int>::type = 0>
6531 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
6532 {
6533 return (lhs > basic_json(rhs));
6534 }
6535
6540 template<typename ScalarType, typename std::enable_if<
6541 std::is_scalar<ScalarType>::value, int>::type = 0>
6542 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
6543 {
6544 return (basic_json(lhs) > rhs);
6545 }
6546
6564 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
6565 {
6566 return not (lhs < rhs);
6567 }
6568
6573 template<typename ScalarType, typename std::enable_if<
6574 std::is_scalar<ScalarType>::value, int>::type = 0>
6575 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
6576 {
6577 return (lhs >= basic_json(rhs));
6578 }
6579
6584 template<typename ScalarType, typename std::enable_if<
6585 std::is_scalar<ScalarType>::value, int>::type = 0>
6586 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
6587 {
6588 return (basic_json(lhs) >= rhs);
6589 }
6590
6592
6593
6595 // serialization //
6597
6600
6601 private:
6605 class serializer
6606 {
6607 private:
6608 serializer(const serializer&) = delete;
6609 serializer& operator=(const serializer&) = delete;
6610
6611 public:
6615 serializer(std::ostream& s)
6616 : o(s), loc(std::localeconv()),
6617 thousands_sep(!loc->thousands_sep ? '\0' : loc->thousands_sep[0]),
6618 decimal_point(!loc->decimal_point ? '\0' : loc->decimal_point[0])
6619 {}
6620
6638 void dump(const basic_json& val,
6639 const bool pretty_print,
6640 const unsigned int indent_step,
6641 const unsigned int current_indent = 0)
6642 {
6643 switch (val.m_type)
6644 {
6645 case value_t::object:
6646 {
6647 if (val.m_value.object->empty())
6648 {
6649 o.write("{}", 2);
6650 return;
6651 }
6652
6653 if (pretty_print)
6654 {
6655 o.write("{\n", 2);
6656
6657 // variable to hold indentation for recursive calls
6658 const auto new_indent = current_indent + indent_step;
6659 if (indent_string.size() < new_indent)
6660 {
6661 indent_string.resize(new_indent, ' ');
6662 }
6663
6664 // first n-1 elements
6665 auto i = val.m_value.object->cbegin();
6666 for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
6667 {
6668 o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
6669 o.put('\"');
6670 dump_escaped(i->first);
6671 o.write("\": ", 3);
6672 dump(i->second, true, indent_step, new_indent);
6673 o.write(",\n", 2);
6674 }
6675
6676 // last element
6677 assert(i != val.m_value.object->cend());
6678 o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
6679 o.put('\"');
6680 dump_escaped(i->first);
6681 o.write("\": ", 3);
6682 dump(i->second, true, indent_step, new_indent);
6683
6684 o.put('\n');
6685 o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
6686 o.put('}');
6687 }
6688 else
6689 {
6690 o.put('{');
6691
6692 // first n-1 elements
6693 auto i = val.m_value.object->cbegin();
6694 for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
6695 {
6696 o.put('\"');
6697 dump_escaped(i->first);
6698 o.write("\":", 2);
6699 dump(i->second, false, indent_step, current_indent);
6700 o.put(',');
6701 }
6702
6703 // last element
6704 assert(i != val.m_value.object->cend());
6705 o.put('\"');
6706 dump_escaped(i->first);
6707 o.write("\":", 2);
6708 dump(i->second, false, indent_step, current_indent);
6709
6710 o.put('}');
6711 }
6712
6713 return;
6714 }
6715
6716 case value_t::array:
6717 {
6718 if (val.m_value.array->empty())
6719 {
6720 o.write("[]", 2);
6721 return;
6722 }
6723
6724 if (pretty_print)
6725 {
6726 o.write("[\n", 2);
6727
6728 // variable to hold indentation for recursive calls
6729 const auto new_indent = current_indent + indent_step;
6730 if (indent_string.size() < new_indent)
6731 {
6732 indent_string.resize(new_indent, ' ');
6733 }
6734
6735 // first n-1 elements
6736 for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
6737 {
6738 o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
6739 dump(*i, true, indent_step, new_indent);
6740 o.write(",\n", 2);
6741 }
6742
6743 // last element
6744 assert(not val.m_value.array->empty());
6745 o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
6746 dump(val.m_value.array->back(), true, indent_step, new_indent);
6747
6748 o.put('\n');
6749 o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
6750 o.put(']');
6751 }
6752 else
6753 {
6754 o.put('[');
6755
6756 // first n-1 elements
6757 for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
6758 {
6759 dump(*i, false, indent_step, current_indent);
6760 o.put(',');
6761 }
6762
6763 // last element
6764 assert(not val.m_value.array->empty());
6765 dump(val.m_value.array->back(), false, indent_step, current_indent);
6766
6767 o.put(']');
6768 }
6769
6770 return;
6771 }
6772
6773 case value_t::string:
6774 {
6775 o.put('\"');
6776 dump_escaped(*val.m_value.string);
6777 o.put('\"');
6778 return;
6779 }
6780
6781 case value_t::boolean:
6782 {
6783 if (val.m_value.boolean)
6784 {
6785 o.write("true", 4);
6786 }
6787 else
6788 {
6789 o.write("false", 5);
6790 }
6791 return;
6792 }
6793
6794 case value_t::number_integer:
6795 {
6796 dump_integer(val.m_value.number_integer);
6797 return;
6798 }
6799
6800 case value_t::number_unsigned:
6801 {
6802 dump_integer(val.m_value.number_unsigned);
6803 return;
6804 }
6805
6806 case value_t::number_float:
6807 {
6808 dump_float(val.m_value.number_float);
6809 return;
6810 }
6811
6812 case value_t::discarded:
6813 {
6814 o.write("<discarded>", 11);
6815 return;
6816 }
6817
6818 case value_t::null:
6819 {
6820 o.write("null", 4);
6821 return;
6822 }
6823 }
6824 }
6825
6826 private:
6835 static std::size_t extra_space(const string_t& s) noexcept
6836 {
6837 return std::accumulate(s.begin(), s.end(), size_t{},
6838 [](size_t res, typename string_t::value_type c)
6839 {
6840 switch (c)
6841 {
6842 case '"':
6843 case '\\':
6844 case '\b':
6845 case '\f':
6846 case '\n':
6847 case '\r':
6848 case '\t':
6849 {
6850 // from c (1 byte) to \x (2 bytes)
6851 return res + 1;
6852 }
6853
6854 case 0x00:
6855 case 0x01:
6856 case 0x02:
6857 case 0x03:
6858 case 0x04:
6859 case 0x05:
6860 case 0x06:
6861 case 0x07:
6862 case 0x0b:
6863 case 0x0e:
6864 case 0x0f:
6865 case 0x10:
6866 case 0x11:
6867 case 0x12:
6868 case 0x13:
6869 case 0x14:
6870 case 0x15:
6871 case 0x16:
6872 case 0x17:
6873 case 0x18:
6874 case 0x19:
6875 case 0x1a:
6876 case 0x1b:
6877 case 0x1c:
6878 case 0x1d:
6879 case 0x1e:
6880 case 0x1f:
6881 {
6882 // from c (1 byte) to \uxxxx (6 bytes)
6883 return res + 5;
6884 }
6885
6886 default:
6887 {
6888 return res;
6889 }
6890 }
6891 });
6892 }
6893
6906 void dump_escaped(const string_t& s) const
6907 {
6908 const auto space = extra_space(s);
6909 if (space == 0)
6910 {
6911 o.write(s.c_str(), static_cast<std::streamsize>(s.size()));
6912 return;
6913 }
6914
6915 // create a result string of necessary size
6916 string_t result(s.size() + space, '\\');
6917 std::size_t pos = 0;
6918
6919 for (const auto& c : s)
6920 {
6921 switch (c)
6922 {
6923 // quotation mark (0x22)
6924 case '"':
6925 {
6926 result[pos + 1] = '"';
6927 pos += 2;
6928 break;
6929 }
6930
6931 // reverse solidus (0x5c)
6932 case '\\':
6933 {
6934 // nothing to change
6935 pos += 2;
6936 break;
6937 }
6938
6939 // backspace (0x08)
6940 case '\b':
6941 {
6942 result[pos + 1] = 'b';
6943 pos += 2;
6944 break;
6945 }
6946
6947 // formfeed (0x0c)
6948 case '\f':
6949 {
6950 result[pos + 1] = 'f';
6951 pos += 2;
6952 break;
6953 }
6954
6955 // newline (0x0a)
6956 case '\n':
6957 {
6958 result[pos + 1] = 'n';
6959 pos += 2;
6960 break;
6961 }
6962
6963 // carriage return (0x0d)
6964 case '\r':
6965 {
6966 result[pos + 1] = 'r';
6967 pos += 2;
6968 break;
6969 }
6970
6971 // horizontal tab (0x09)
6972 case '\t':
6973 {
6974 result[pos + 1] = 't';
6975 pos += 2;
6976 break;
6977 }
6978
6979 case 0x00:
6980 case 0x01:
6981 case 0x02:
6982 case 0x03:
6983 case 0x04:
6984 case 0x05:
6985 case 0x06:
6986 case 0x07:
6987 case 0x0b:
6988 case 0x0e:
6989 case 0x0f:
6990 case 0x10:
6991 case 0x11:
6992 case 0x12:
6993 case 0x13:
6994 case 0x14:
6995 case 0x15:
6996 case 0x16:
6997 case 0x17:
6998 case 0x18:
6999 case 0x19:
7000 case 0x1a:
7001 case 0x1b:
7002 case 0x1c:
7003 case 0x1d:
7004 case 0x1e:
7005 case 0x1f:
7006 {
7007 // convert a number 0..15 to its hex representation
7008 // (0..f)
7009 static const char hexify[16] =
7010 {
7011 '0', '1', '2', '3', '4', '5', '6', '7',
7012 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
7013 };
7014
7015 // print character c as \uxxxx
7016 for (const char m :
7017 { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
7018 })
7019 {
7020 result[++pos] = m;
7021 }
7022
7023 ++pos;
7024 break;
7025 }
7026
7027 default:
7028 {
7029 // all other characters are added as-is
7030 result[pos++] = c;
7031 break;
7032 }
7033 }
7034 }
7035
7036 assert(pos == s.size() + space);
7037 o.write(result.c_str(), static_cast<std::streamsize>(result.size()));
7038 }
7039
7049 template<typename NumberType, detail::enable_if_t <
7050 std::is_same<NumberType, number_unsigned_t>::value or
7051 std::is_same<NumberType, number_integer_t>::value, int> = 0>
7052 void dump_integer(NumberType x)
7053 {
7054 // special case for "0"
7055 if (x == 0)
7056 {
7057 o.put('0');
7058 return;
7059 }
7060
7061 const bool is_negative = x < 0;
7062 size_t i = 0;
7063
7064 // spare 1 byte for '\0'
7065 while (x != 0 and i < number_buffer.size() - 1)
7066 {
7067 const auto digit = std::labs(static_cast<long>(x % 10));
7068 number_buffer[i++] = static_cast<char>('0' + digit);
7069 x /= 10;
7070 }
7071
7072 // make sure the number has been processed completely
7073 assert(x == 0);
7074
7075 if (is_negative)
7076 {
7077 // make sure there is capacity for the '-'
7078 assert(i < number_buffer.size() - 2);
7079 number_buffer[i++] = '-';
7080 }
7081
7082 std::reverse(number_buffer.begin(), number_buffer.begin() + i);
7083 o.write(number_buffer.data(), static_cast<std::streamsize>(i));
7084 }
7085
7094 void dump_float(number_float_t x)
7095 {
7096 // NaN / inf
7097 if (not std::isfinite(x) or std::isnan(x))
7098 {
7099 o.write("null", 4);
7100 return;
7101 }
7102
7103 // special case for 0.0 and -0.0
7104 if (x == 0)
7105 {
7106 if (std::signbit(x))
7107 {
7108 o.write("-0.0", 4);
7109 }
7110 else
7111 {
7112 o.write("0.0", 3);
7113 }
7114 return;
7115 }
7116
7117 // get number of digits for a text -> float -> text round-trip
7118 static constexpr auto d = std::numeric_limits<number_float_t>::digits10;
7119
7120 // the actual conversion
7121 std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(),
7122 "%.*g", d, x);
7123
7124 // negative value indicates an error
7125 assert(len > 0);
7126 // check if buffer was large enough
7127 assert(static_cast<size_t>(len) < number_buffer.size());
7128
7129 // erase thousands separator
7130 if (thousands_sep != '\0')
7131 {
7132 const auto end = std::remove(number_buffer.begin(),
7133 number_buffer.begin() + len,
7134 thousands_sep);
7135 std::fill(end, number_buffer.end(), '\0');
7136 assert((end - number_buffer.begin()) <= len);
7137 len = (end - number_buffer.begin());
7138 }
7139
7140 // convert decimal point to '.'
7141 if (decimal_point != '\0' and decimal_point != '.')
7142 {
7143 for (auto& c : number_buffer)
7144 {
7145 if (c == decimal_point)
7146 {
7147 c = '.';
7148 break;
7149 }
7150 }
7151 }
7152
7153 o.write(number_buffer.data(), static_cast<std::streamsize>(len));
7154
7155 // determine if need to append ".0"
7156 const bool value_is_int_like = std::none_of(number_buffer.begin(),
7157 number_buffer.begin() + len + 1,
7158 [](char c)
7159 {
7160 return c == '.' or c == 'e';
7161 });
7162
7163 if (value_is_int_like)
7164 {
7165 o.write(".0", 2);
7166 }
7167 }
7168
7169 private:
7171 std::ostream& o;
7172
7174 std::array<char, 64> number_buffer{{}};
7175
7177 const std::lconv* loc = nullptr;
7179 const char thousands_sep = '\0';
7181 const char decimal_point = '\0';
7182
7184 string_t indent_string = string_t(512, ' ');
7185 };
7186
7187 public:
7210 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
7211 {
7212 // read width member and use it as indentation parameter if nonzero
7213 const bool pretty_print = (o.width() > 0);
7214 const auto indentation = (pretty_print ? o.width() : 0);
7215
7216 // reset width to 0 for subsequent calls to this stream
7217 o.width(0);
7218
7219 // do the actual serialization
7220 serializer s(o);
7221 s.dump(j, pretty_print, static_cast<unsigned int>(indentation));
7222 return o;
7223 }
7224
7232 JSON_DEPRECATED
7233 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
7234 {
7235 return o << j;
7236 }
7237
7239
7240
7242 // deserialization //
7244
7247
7280 template<class T, std::size_t N>
7281 static basic_json parse(T (&array)[N],
7282 const parser_callback_t cb = nullptr)
7283 {
7284 // delegate the call to the iterator-range parse overload
7285 return parse(std::begin(array), std::end(array), cb);
7286 }
7287
7319 template<typename CharT, typename std::enable_if<
7320 std::is_pointer<CharT>::value and
7321 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
7322 sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
7323 static basic_json parse(const CharT s,
7324 const parser_callback_t cb = nullptr)
7325 {
7326 return parser(reinterpret_cast<const char*>(s), cb).parse();
7327 }
7328
7358 static basic_json parse(std::istream& i,
7359 const parser_callback_t cb = nullptr)
7360 {
7361 return parser(i, cb).parse();
7362 }
7363
7367 static basic_json parse(std::istream&& i,
7368 const parser_callback_t cb = nullptr)
7369 {
7370 return parser(i, cb).parse();
7371 }
7372
7418 template<class IteratorType, typename std::enable_if<
7419 std::is_base_of<
7420 std::random_access_iterator_tag,
7421 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
7422 static basic_json parse(IteratorType first, IteratorType last,
7423 const parser_callback_t cb = nullptr)
7424 {
7425 // assertion to check that the iterator range is indeed contiguous,
7426 // see http://stackoverflow.com/a/35008842/266378 for more discussion
7427 assert(std::accumulate(first, last, std::pair<bool, int>(true, 0),
7428 [&first](std::pair<bool, int> res, decltype(*first) val)
7429 {
7430 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
7431 return res;
7432 }).first);
7433
7434 // assertion to check that each element is 1 byte long
7435 static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
7436 "each element in the iterator range must have the size of 1 byte");
7437
7438 // if iterator range is empty, create a parser with an empty string
7439 // to generate "unexpected EOF" error message
7440 if (std::distance(first, last) <= 0)
7441 {
7442 return parser("").parse();
7443 }
7444
7445 return parser(first, last, cb).parse();
7446 }
7447
7492 template<class ContiguousContainer, typename std::enable_if<
7493 not std::is_pointer<ContiguousContainer>::value and
7494 std::is_base_of<
7495 std::random_access_iterator_tag,
7496 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
7497 , int>::type = 0>
7498 static basic_json parse(const ContiguousContainer& c,
7499 const parser_callback_t cb = nullptr)
7500 {
7501 // delegate the call to the iterator-range parse overload
7502 return parse(std::begin(c), std::end(c), cb);
7503 }
7504
7512 JSON_DEPRECATED
7513 friend std::istream& operator<<(basic_json& j, std::istream& i)
7514 {
7515 j = parser(i).parse();
7516 return i;
7517 }
7518
7545 friend std::istream& operator>>(std::istream& i, basic_json& j)
7546 {
7547 j = parser(i).parse();
7548 return i;
7549 }
7550
7552
7554 // binary serialization/deserialization //
7556
7559
7560 private:
7566 template<typename T>
7567 static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
7568 {
7569 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
7570
7571 switch (bytes)
7572 {
7573 case 8:
7574 {
7575 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 070) & 0xff));
7576 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 060) & 0xff));
7577 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 050) & 0xff));
7578 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 040) & 0xff));
7579 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
7580 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
7581 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
7582 vec.push_back(static_cast<uint8_t>(number & 0xff));
7583 break;
7584 }
7585
7586 case 4:
7587 {
7588 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
7589 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
7590 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
7591 vec.push_back(static_cast<uint8_t>(number & 0xff));
7592 break;
7593 }
7594
7595 case 2:
7596 {
7597 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
7598 vec.push_back(static_cast<uint8_t>(number & 0xff));
7599 break;
7600 }
7601
7602 case 1:
7603 {
7604 vec.push_back(static_cast<uint8_t>(number & 0xff));
7605 break;
7606 }
7607 }
7608 }
7609
7646 template<typename T>
7647 static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
7648 {
7649 // check if we can read sizeof(T) bytes starting the next index
7650 check_length(vec.size(), sizeof(T), current_index + 1);
7651
7652 T result;
7653 auto* ptr = reinterpret_cast<uint8_t*>(&result);
7654 for (size_t i = 0; i < sizeof(T); ++i)
7655 {
7656 *ptr++ = vec[current_index + sizeof(T) - i];
7657 }
7658 return result;
7659 }
7660
7671 static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
7672 {
7673 switch (j.type())
7674 {
7675 case value_t::null:
7676 {
7677 // nil
7678 v.push_back(0xc0);
7679 break;
7680 }
7681
7682 case value_t::boolean:
7683 {
7684 // true and false
7685 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
7686 break;
7687 }
7688
7689 case value_t::number_integer:
7690 {
7691 if (j.m_value.number_integer >= 0)
7692 {
7693 // MessagePack does not differentiate between positive
7694 // signed integers and unsigned integers. Therefore, we
7695 // used the code from the value_t::number_unsigned case
7696 // here.
7697 if (j.m_value.number_unsigned < 128)
7698 {
7699 // positive fixnum
7700 add_to_vector(v, 1, j.m_value.number_unsigned);
7701 }
7702 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7703 {
7704 // uint 8
7705 v.push_back(0xcc);
7706 add_to_vector(v, 1, j.m_value.number_unsigned);
7707 }
7708 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7709 {
7710 // uint 16
7711 v.push_back(0xcd);
7712 add_to_vector(v, 2, j.m_value.number_unsigned);
7713 }
7714 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7715 {
7716 // uint 32
7717 v.push_back(0xce);
7718 add_to_vector(v, 4, j.m_value.number_unsigned);
7719 }
7720 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
7721 {
7722 // uint 64
7723 v.push_back(0xcf);
7724 add_to_vector(v, 8, j.m_value.number_unsigned);
7725 }
7726 }
7727 else
7728 {
7729 if (j.m_value.number_integer >= -32)
7730 {
7731 // negative fixnum
7732 add_to_vector(v, 1, j.m_value.number_integer);
7733 }
7734 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)())
7735 {
7736 // int 8
7737 v.push_back(0xd0);
7738 add_to_vector(v, 1, j.m_value.number_integer);
7739 }
7740 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)())
7741 {
7742 // int 16
7743 v.push_back(0xd1);
7744 add_to_vector(v, 2, j.m_value.number_integer);
7745 }
7746 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)())
7747 {
7748 // int 32
7749 v.push_back(0xd2);
7750 add_to_vector(v, 4, j.m_value.number_integer);
7751 }
7752 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)())
7753 {
7754 // int 64
7755 v.push_back(0xd3);
7756 add_to_vector(v, 8, j.m_value.number_integer);
7757 }
7758 }
7759 break;
7760 }
7761
7762 case value_t::number_unsigned:
7763 {
7764 if (j.m_value.number_unsigned < 128)
7765 {
7766 // positive fixnum
7767 add_to_vector(v, 1, j.m_value.number_unsigned);
7768 }
7769 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7770 {
7771 // uint 8
7772 v.push_back(0xcc);
7773 add_to_vector(v, 1, j.m_value.number_unsigned);
7774 }
7775 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7776 {
7777 // uint 16
7778 v.push_back(0xcd);
7779 add_to_vector(v, 2, j.m_value.number_unsigned);
7780 }
7781 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7782 {
7783 // uint 32
7784 v.push_back(0xce);
7785 add_to_vector(v, 4, j.m_value.number_unsigned);
7786 }
7787 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
7788 {
7789 // uint 64
7790 v.push_back(0xcf);
7791 add_to_vector(v, 8, j.m_value.number_unsigned);
7792 }
7793 break;
7794 }
7795
7796 case value_t::number_float:
7797 {
7798 // float 64
7799 v.push_back(0xcb);
7800 const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
7801 for (size_t i = 0; i < 8; ++i)
7802 {
7803 v.push_back(helper[7 - i]);
7804 }
7805 break;
7806 }
7807
7808 case value_t::string:
7809 {
7810 const auto N = j.m_value.string->size();
7811 if (N <= 31)
7812 {
7813 // fixstr
7814 v.push_back(static_cast<uint8_t>(0xa0 | N));
7815 }
7816 else if (N <= 255)
7817 {
7818 // str 8
7819 v.push_back(0xd9);
7820 add_to_vector(v, 1, N);
7821 }
7822 else if (N <= 65535)
7823 {
7824 // str 16
7825 v.push_back(0xda);
7826 add_to_vector(v, 2, N);
7827 }
7828 else if (N <= 4294967295)
7829 {
7830 // str 32
7831 v.push_back(0xdb);
7832 add_to_vector(v, 4, N);
7833 }
7834
7835 // append string
7836 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
7837 std::back_inserter(v));
7838 break;
7839 }
7840
7841 case value_t::array:
7842 {
7843 const auto N = j.m_value.array->size();
7844 if (N <= 15)
7845 {
7846 // fixarray
7847 v.push_back(static_cast<uint8_t>(0x90 | N));
7848 }
7849 else if (N <= 0xffff)
7850 {
7851 // array 16
7852 v.push_back(0xdc);
7853 add_to_vector(v, 2, N);
7854 }
7855 else if (N <= 0xffffffff)
7856 {
7857 // array 32
7858 v.push_back(0xdd);
7859 add_to_vector(v, 4, N);
7860 }
7861
7862 // append each element
7863 for (const auto& el : *j.m_value.array)
7864 {
7865 to_msgpack_internal(el, v);
7866 }
7867 break;
7868 }
7869
7870 case value_t::object:
7871 {
7872 const auto N = j.m_value.object->size();
7873 if (N <= 15)
7874 {
7875 // fixmap
7876 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
7877 }
7878 else if (N <= 65535)
7879 {
7880 // map 16
7881 v.push_back(0xde);
7882 add_to_vector(v, 2, N);
7883 }
7884 else if (N <= 4294967295)
7885 {
7886 // map 32
7887 v.push_back(0xdf);
7888 add_to_vector(v, 4, N);
7889 }
7890
7891 // append each element
7892 for (const auto& el : *j.m_value.object)
7893 {
7894 to_msgpack_internal(el.first, v);
7895 to_msgpack_internal(el.second, v);
7896 }
7897 break;
7898 }
7899
7900 default:
7901 {
7902 break;
7903 }
7904 }
7905 }
7906
7917 static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
7918 {
7919 switch (j.type())
7920 {
7921 case value_t::null:
7922 {
7923 v.push_back(0xf6);
7924 break;
7925 }
7926
7927 case value_t::boolean:
7928 {
7929 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
7930 break;
7931 }
7932
7933 case value_t::number_integer:
7934 {
7935 if (j.m_value.number_integer >= 0)
7936 {
7937 // CBOR does not differentiate between positive signed
7938 // integers and unsigned integers. Therefore, we used the
7939 // code from the value_t::number_unsigned case here.
7940 if (j.m_value.number_integer <= 0x17)
7941 {
7942 add_to_vector(v, 1, j.m_value.number_integer);
7943 }
7944 else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
7945 {
7946 v.push_back(0x18);
7947 // one-byte uint8_t
7948 add_to_vector(v, 1, j.m_value.number_integer);
7949 }
7950 else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
7951 {
7952 v.push_back(0x19);
7953 // two-byte uint16_t
7954 add_to_vector(v, 2, j.m_value.number_integer);
7955 }
7956 else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
7957 {
7958 v.push_back(0x1a);
7959 // four-byte uint32_t
7960 add_to_vector(v, 4, j.m_value.number_integer);
7961 }
7962 else
7963 {
7964 v.push_back(0x1b);
7965 // eight-byte uint64_t
7966 add_to_vector(v, 8, j.m_value.number_integer);
7967 }
7968 }
7969 else
7970 {
7971 // The conversions below encode the sign in the first
7972 // byte, and the value is converted to a positive number.
7973 const auto positive_number = -1 - j.m_value.number_integer;
7974 if (j.m_value.number_integer >= -24)
7975 {
7976 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
7977 }
7978 else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
7979 {
7980 // int 8
7981 v.push_back(0x38);
7982 add_to_vector(v, 1, positive_number);
7983 }
7984 else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
7985 {
7986 // int 16
7987 v.push_back(0x39);
7988 add_to_vector(v, 2, positive_number);
7989 }
7990 else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
7991 {
7992 // int 32
7993 v.push_back(0x3a);
7994 add_to_vector(v, 4, positive_number);
7995 }
7996 else
7997 {
7998 // int 64
7999 v.push_back(0x3b);
8000 add_to_vector(v, 8, positive_number);
8001 }
8002 }
8003 break;
8004 }
8005
8006 case value_t::number_unsigned:
8007 {
8008 if (j.m_value.number_unsigned <= 0x17)
8009 {
8010 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
8011 }
8012 else if (j.m_value.number_unsigned <= 0xff)
8013 {
8014 v.push_back(0x18);
8015 // one-byte uint8_t
8016 add_to_vector(v, 1, j.m_value.number_unsigned);
8017 }
8018 else if (j.m_value.number_unsigned <= 0xffff)
8019 {
8020 v.push_back(0x19);
8021 // two-byte uint16_t
8022 add_to_vector(v, 2, j.m_value.number_unsigned);
8023 }
8024 else if (j.m_value.number_unsigned <= 0xffffffff)
8025 {
8026 v.push_back(0x1a);
8027 // four-byte uint32_t
8028 add_to_vector(v, 4, j.m_value.number_unsigned);
8029 }
8030 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
8031 {
8032 v.push_back(0x1b);
8033 // eight-byte uint64_t
8034 add_to_vector(v, 8, j.m_value.number_unsigned);
8035 }
8036 break;
8037 }
8038
8039 case value_t::number_float:
8040 {
8041 // Double-Precision Float
8042 v.push_back(0xfb);
8043 const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
8044 for (size_t i = 0; i < 8; ++i)
8045 {
8046 v.push_back(helper[7 - i]);
8047 }
8048 break;
8049 }
8050
8051 case value_t::string:
8052 {
8053 const auto N = j.m_value.string->size();
8054 if (N <= 0x17)
8055 {
8056 v.push_back(static_cast<uint8_t>(0x60 + N)); // 1 byte for string + size
8057 }
8058 else if (N <= 0xff)
8059 {
8060 v.push_back(0x78); // one-byte uint8_t for N
8061 add_to_vector(v, 1, N);
8062 }
8063 else if (N <= 0xffff)
8064 {
8065 v.push_back(0x79); // two-byte uint16_t for N
8066 add_to_vector(v, 2, N);
8067 }
8068 else if (N <= 0xffffffff)
8069 {
8070 v.push_back(0x7a); // four-byte uint32_t for N
8071 add_to_vector(v, 4, N);
8072 }
8073 // LCOV_EXCL_START
8074 else if (N <= 0xffffffffffffffff)
8075 {
8076 v.push_back(0x7b); // eight-byte uint64_t for N
8077 add_to_vector(v, 8, N);
8078 }
8079 // LCOV_EXCL_STOP
8080
8081 // append string
8082 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
8083 std::back_inserter(v));
8084 break;
8085 }
8086
8087 case value_t::array:
8088 {
8089 const auto N = j.m_value.array->size();
8090 if (N <= 0x17)
8091 {
8092 v.push_back(static_cast<uint8_t>(0x80 + N)); // 1 byte for array + size
8093 }
8094 else if (N <= 0xff)
8095 {
8096 v.push_back(0x98); // one-byte uint8_t for N
8097 add_to_vector(v, 1, N);
8098 }
8099 else if (N <= 0xffff)
8100 {
8101 v.push_back(0x99); // two-byte uint16_t for N
8102 add_to_vector(v, 2, N);
8103 }
8104 else if (N <= 0xffffffff)
8105 {
8106 v.push_back(0x9a); // four-byte uint32_t for N
8107 add_to_vector(v, 4, N);
8108 }
8109 // LCOV_EXCL_START
8110 else if (N <= 0xffffffffffffffff)
8111 {
8112 v.push_back(0x9b); // eight-byte uint64_t for N
8113 add_to_vector(v, 8, N);
8114 }
8115 // LCOV_EXCL_STOP
8116
8117 // append each element
8118 for (const auto& el : *j.m_value.array)
8119 {
8120 to_cbor_internal(el, v);
8121 }
8122 break;
8123 }
8124
8125 case value_t::object:
8126 {
8127 const auto N = j.m_value.object->size();
8128 if (N <= 0x17)
8129 {
8130 v.push_back(static_cast<uint8_t>(0xa0 + N)); // 1 byte for object + size
8131 }
8132 else if (N <= 0xff)
8133 {
8134 v.push_back(0xb8);
8135 add_to_vector(v, 1, N); // one-byte uint8_t for N
8136 }
8137 else if (N <= 0xffff)
8138 {
8139 v.push_back(0xb9);
8140 add_to_vector(v, 2, N); // two-byte uint16_t for N
8141 }
8142 else if (N <= 0xffffffff)
8143 {
8144 v.push_back(0xba);
8145 add_to_vector(v, 4, N); // four-byte uint32_t for N
8146 }
8147 // LCOV_EXCL_START
8148 else if (N <= 0xffffffffffffffff)
8149 {
8150 v.push_back(0xbb);
8151 add_to_vector(v, 8, N); // eight-byte uint64_t for N
8152 }
8153 // LCOV_EXCL_STOP
8154
8155 // append each element
8156 for (const auto& el : *j.m_value.object)
8157 {
8158 to_cbor_internal(el.first, v);
8159 to_cbor_internal(el.second, v);
8160 }
8161 break;
8162 }
8163
8164 default:
8165 {
8166 break;
8167 }
8168 }
8169 }
8170
8171
8172 /*
8173 @brief checks if given lengths do not exceed the size of a given vector
8174
8175 To secure the access to the byte vector during CBOR/MessagePack
8176 deserialization, bytes are copied from the vector into buffers. This
8177 function checks if the number of bytes to copy (@a len) does not exceed
8178 the size @s size of the vector. Additionally, an @a offset is given from
8179 where to start reading the bytes.
8180
8181 This function checks whether reading the bytes is safe; that is, offset is
8182 a valid index in the vector, offset+len
8183
8184 @param[in] size size of the byte vector
8185 @param[in] len number of bytes to read
8186 @param[in] offset offset where to start reading
8187
8188 vec: x x x x x X X X X X
8189 ^ ^ ^
8190 0 offset len
8191
8192 @throws out_of_range if `len > v.size()`
8193 */
8194 static void check_length(const size_t size, const size_t len, const size_t offset)
8195 {
8196 // simple case: requested length is greater than the vector's length
8197 if (len > size or offset > size)
8198 {
8199 JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
8200 }
8201
8202 // second case: adding offset would result in overflow
8203 if ((size > ((std::numeric_limits<size_t>::max)() - offset)))
8204 {
8205 JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
8206 }
8207
8208 // last case: reading past the end of the vector
8209 if (len + offset > size)
8210 {
8211 JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
8212 }
8213 }
8214
8231 static void msgpack_expect_string(const std::vector<uint8_t>& v, size_t idx)
8232 {
8233 check_length(v.size(), 1, idx);
8234
8235 const auto byte = v[idx];
8236 if ((byte >= 0xa0 and byte <= 0xbf) or (byte >= 0xd9 and byte <= 0xdb))
8237 {
8238 return;
8239 }
8240
8241 std::stringstream ss;
8242 ss << std::hex << static_cast<int>(v[idx]);
8243 JSON_THROW(parse_error::create(113, idx + 1, "expected a MessagePack string; last byte: 0x" + ss.str()));
8244 }
8245
8261 static void cbor_expect_string(const std::vector<uint8_t>& v, size_t idx)
8262 {
8263 check_length(v.size(), 1, idx);
8264
8265 const auto byte = v[idx];
8266 if ((byte >= 0x60 and byte <= 0x7b) or byte == 0x7f)
8267 {
8268 return;
8269 }
8270
8271 std::stringstream ss;
8272 ss << std::hex << static_cast<int>(v[idx]);
8273 JSON_THROW(parse_error::create(113, idx + 1, "expected a CBOR string; last byte: 0x" + ss.str()));
8274 }
8275
8291 static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
8292 {
8293 // store and increment index
8294 const size_t current_idx = idx++;
8295
8296 // make sure reading 1 byte is safe
8297 check_length(v.size(), 1, current_idx);
8298
8299 if (v[current_idx] <= 0xbf)
8300 {
8301 if (v[current_idx] <= 0x7f) // positive fixint
8302 {
8303 return v[current_idx];
8304 }
8305 if (v[current_idx] <= 0x8f) // fixmap
8306 {
8307 basic_json result = value_t::object;
8308 const size_t len = v[current_idx] & 0x0f;
8309 for (size_t i = 0; i < len; ++i)
8310 {
8311 msgpack_expect_string(v, idx);
8312 std::string key = from_msgpack_internal(v, idx);
8313 result[key] = from_msgpack_internal(v, idx);
8314 }
8315 return result;
8316 }
8317 else if (v[current_idx] <= 0x9f) // fixarray
8318 {
8319 basic_json result = value_t::array;
8320 const size_t len = v[current_idx] & 0x0f;
8321 for (size_t i = 0; i < len; ++i)
8322 {
8323 result.push_back(from_msgpack_internal(v, idx));
8324 }
8325 return result;
8326 }
8327 else // fixstr
8328 {
8329 const size_t len = v[current_idx] & 0x1f;
8330 const size_t offset = current_idx + 1;
8331 idx += len; // skip content bytes
8332 check_length(v.size(), len, offset);
8333 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8334 }
8335 }
8336 else if (v[current_idx] >= 0xe0) // negative fixint
8337 {
8338 return static_cast<int8_t>(v[current_idx]);
8339 }
8340 else
8341 {
8342 switch (v[current_idx])
8343 {
8344 case 0xc0: // nil
8345 {
8346 return value_t::null;
8347 }
8348
8349 case 0xc2: // false
8350 {
8351 return false;
8352 }
8353
8354 case 0xc3: // true
8355 {
8356 return true;
8357 }
8358
8359 case 0xca: // float 32
8360 {
8361 // copy bytes in reverse order into the double variable
8362 float res;
8363 check_length(v.size(), sizeof(float), current_idx + 1);
8364 for (size_t byte = 0; byte < sizeof(float); ++byte)
8365 {
8366 reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
8367 }
8368 idx += sizeof(float); // skip content bytes
8369 return res;
8370 }
8371
8372 case 0xcb: // float 64
8373 {
8374 // copy bytes in reverse order into the double variable
8375 double res;
8376 check_length(v.size(), sizeof(double), current_idx + 1);
8377 for (size_t byte = 0; byte < sizeof(double); ++byte)
8378 {
8379 reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
8380 }
8381 idx += sizeof(double); // skip content bytes
8382 return res;
8383 }
8384
8385 case 0xcc: // uint 8
8386 {
8387 idx += 1; // skip content byte
8388 return get_from_vector<uint8_t>(v, current_idx);
8389 }
8390
8391 case 0xcd: // uint 16
8392 {
8393 idx += 2; // skip 2 content bytes
8394 return get_from_vector<uint16_t>(v, current_idx);
8395 }
8396
8397 case 0xce: // uint 32
8398 {
8399 idx += 4; // skip 4 content bytes
8400 return get_from_vector<uint32_t>(v, current_idx);
8401 }
8402
8403 case 0xcf: // uint 64
8404 {
8405 idx += 8; // skip 8 content bytes
8406 return get_from_vector<uint64_t>(v, current_idx);
8407 }
8408
8409 case 0xd0: // int 8
8410 {
8411 idx += 1; // skip content byte
8412 return get_from_vector<int8_t>(v, current_idx);
8413 }
8414
8415 case 0xd1: // int 16
8416 {
8417 idx += 2; // skip 2 content bytes
8418 return get_from_vector<int16_t>(v, current_idx);
8419 }
8420
8421 case 0xd2: // int 32
8422 {
8423 idx += 4; // skip 4 content bytes
8424 return get_from_vector<int32_t>(v, current_idx);
8425 }
8426
8427 case 0xd3: // int 64
8428 {
8429 idx += 8; // skip 8 content bytes
8430 return get_from_vector<int64_t>(v, current_idx);
8431 }
8432
8433 case 0xd9: // str 8
8434 {
8435 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
8436 const size_t offset = current_idx + 2;
8437 idx += len + 1; // skip size byte + content bytes
8438 check_length(v.size(), len, offset);
8439 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8440 }
8441
8442 case 0xda: // str 16
8443 {
8444 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
8445 const size_t offset = current_idx + 3;
8446 idx += len + 2; // skip 2 size bytes + content bytes
8447 check_length(v.size(), len, offset);
8448 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8449 }
8450
8451 case 0xdb: // str 32
8452 {
8453 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
8454 const size_t offset = current_idx + 5;
8455 idx += len + 4; // skip 4 size bytes + content bytes
8456 check_length(v.size(), len, offset);
8457 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8458 }
8459
8460 case 0xdc: // array 16
8461 {
8462 basic_json result = value_t::array;
8463 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
8464 idx += 2; // skip 2 size bytes
8465 for (size_t i = 0; i < len; ++i)
8466 {
8467 result.push_back(from_msgpack_internal(v, idx));
8468 }
8469 return result;
8470 }
8471
8472 case 0xdd: // array 32
8473 {
8474 basic_json result = value_t::array;
8475 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
8476 idx += 4; // skip 4 size bytes
8477 for (size_t i = 0; i < len; ++i)
8478 {
8479 result.push_back(from_msgpack_internal(v, idx));
8480 }
8481 return result;
8482 }
8483
8484 case 0xde: // map 16
8485 {
8486 basic_json result = value_t::object;
8487 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
8488 idx += 2; // skip 2 size bytes
8489 for (size_t i = 0; i < len; ++i)
8490 {
8491 msgpack_expect_string(v, idx);
8492 std::string key = from_msgpack_internal(v, idx);
8493 result[key] = from_msgpack_internal(v, idx);
8494 }
8495 return result;
8496 }
8497
8498 case 0xdf: // map 32
8499 {
8500 basic_json result = value_t::object;
8501 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
8502 idx += 4; // skip 4 size bytes
8503 for (size_t i = 0; i < len; ++i)
8504 {
8505 msgpack_expect_string(v, idx);
8506 std::string key = from_msgpack_internal(v, idx);
8507 result[key] = from_msgpack_internal(v, idx);
8508 }
8509 return result;
8510 }
8511
8512 default:
8513 {
8514 std::stringstream ss;
8515 ss << std::hex << static_cast<int>(v[current_idx]);
8516 JSON_THROW(parse_error::create(112, current_idx + 1, "error reading MessagePack; last byte: 0x" + ss.str()));
8517 }
8518 }
8519 }
8520 }
8521
8537 static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
8538 {
8539 // store and increment index
8540 const size_t current_idx = idx++;
8541
8542 // make sure reading 1 byte is safe
8543 check_length(v.size(), 1, current_idx);
8544
8545 switch (v[current_idx])
8546 {
8547 // Integer 0x00..0x17 (0..23)
8548 case 0x00:
8549 case 0x01:
8550 case 0x02:
8551 case 0x03:
8552 case 0x04:
8553 case 0x05:
8554 case 0x06:
8555 case 0x07:
8556 case 0x08:
8557 case 0x09:
8558 case 0x0a:
8559 case 0x0b:
8560 case 0x0c:
8561 case 0x0d:
8562 case 0x0e:
8563 case 0x0f:
8564 case 0x10:
8565 case 0x11:
8566 case 0x12:
8567 case 0x13:
8568 case 0x14:
8569 case 0x15:
8570 case 0x16:
8571 case 0x17:
8572 {
8573 return v[current_idx];
8574 }
8575
8576 case 0x18: // Unsigned integer (one-byte uint8_t follows)
8577 {
8578 idx += 1; // skip content byte
8579 return get_from_vector<uint8_t>(v, current_idx);
8580 }
8581
8582 case 0x19: // Unsigned integer (two-byte uint16_t follows)
8583 {
8584 idx += 2; // skip 2 content bytes
8585 return get_from_vector<uint16_t>(v, current_idx);
8586 }
8587
8588 case 0x1a: // Unsigned integer (four-byte uint32_t follows)
8589 {
8590 idx += 4; // skip 4 content bytes
8591 return get_from_vector<uint32_t>(v, current_idx);
8592 }
8593
8594 case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
8595 {
8596 idx += 8; // skip 8 content bytes
8597 return get_from_vector<uint64_t>(v, current_idx);
8598 }
8599
8600 // Negative integer -1-0x00..-1-0x17 (-1..-24)
8601 case 0x20:
8602 case 0x21:
8603 case 0x22:
8604 case 0x23:
8605 case 0x24:
8606 case 0x25:
8607 case 0x26:
8608 case 0x27:
8609 case 0x28:
8610 case 0x29:
8611 case 0x2a:
8612 case 0x2b:
8613 case 0x2c:
8614 case 0x2d:
8615 case 0x2e:
8616 case 0x2f:
8617 case 0x30:
8618 case 0x31:
8619 case 0x32:
8620 case 0x33:
8621 case 0x34:
8622 case 0x35:
8623 case 0x36:
8624 case 0x37:
8625 {
8626 return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
8627 }
8628
8629 case 0x38: // Negative integer (one-byte uint8_t follows)
8630 {
8631 idx += 1; // skip content byte
8632 // must be uint8_t !
8633 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
8634 }
8635
8636 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8637 {
8638 idx += 2; // skip 2 content bytes
8639 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
8640 }
8641
8642 case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
8643 {
8644 idx += 4; // skip 4 content bytes
8645 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
8646 }
8647
8648 case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
8649 {
8650 idx += 8; // skip 8 content bytes
8651 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
8652 }
8653
8654 // UTF-8 string (0x00..0x17 bytes follow)
8655 case 0x60:
8656 case 0x61:
8657 case 0x62:
8658 case 0x63:
8659 case 0x64:
8660 case 0x65:
8661 case 0x66:
8662 case 0x67:
8663 case 0x68:
8664 case 0x69:
8665 case 0x6a:
8666 case 0x6b:
8667 case 0x6c:
8668 case 0x6d:
8669 case 0x6e:
8670 case 0x6f:
8671 case 0x70:
8672 case 0x71:
8673 case 0x72:
8674 case 0x73:
8675 case 0x74:
8676 case 0x75:
8677 case 0x76:
8678 case 0x77:
8679 {
8680 const auto len = static_cast<size_t>(v[current_idx] - 0x60);
8681 const size_t offset = current_idx + 1;
8682 idx += len; // skip content bytes
8683 check_length(v.size(), len, offset);
8684 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8685 }
8686
8687 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8688 {
8689 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
8690 const size_t offset = current_idx + 2;
8691 idx += len + 1; // skip size byte + content bytes
8692 check_length(v.size(), len, offset);
8693 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8694 }
8695
8696 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8697 {
8698 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
8699 const size_t offset = current_idx + 3;
8700 idx += len + 2; // skip 2 size bytes + content bytes
8701 check_length(v.size(), len, offset);
8702 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8703 }
8704
8705 case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
8706 {
8707 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
8708 const size_t offset = current_idx + 5;
8709 idx += len + 4; // skip 4 size bytes + content bytes
8710 check_length(v.size(), len, offset);
8711 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8712 }
8713
8714 case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
8715 {
8716 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
8717 const size_t offset = current_idx + 9;
8718 idx += len + 8; // skip 8 size bytes + content bytes
8719 check_length(v.size(), len, offset);
8720 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
8721 }
8722
8723 case 0x7f: // UTF-8 string (indefinite length)
8724 {
8725 std::string result;
8726 while (static_cast<void>(check_length(v.size(), 1, idx)), v[idx] != 0xff)
8727 {
8728 string_t s = from_cbor_internal(v, idx);
8729 result += s;
8730 }
8731 // skip break byte (0xFF)
8732 idx += 1;
8733 return result;
8734 }
8735
8736 // array (0x00..0x17 data items follow)
8737 case 0x80:
8738 case 0x81:
8739 case 0x82:
8740 case 0x83:
8741 case 0x84:
8742 case 0x85:
8743 case 0x86:
8744 case 0x87:
8745 case 0x88:
8746 case 0x89:
8747 case 0x8a:
8748 case 0x8b:
8749 case 0x8c:
8750 case 0x8d:
8751 case 0x8e:
8752 case 0x8f:
8753 case 0x90:
8754 case 0x91:
8755 case 0x92:
8756 case 0x93:
8757 case 0x94:
8758 case 0x95:
8759 case 0x96:
8760 case 0x97:
8761 {
8762 basic_json result = value_t::array;
8763 const auto len = static_cast<size_t>(v[current_idx] - 0x80);
8764 for (size_t i = 0; i < len; ++i)
8765 {
8766 result.push_back(from_cbor_internal(v, idx));
8767 }
8768 return result;
8769 }
8770
8771 case 0x98: // array (one-byte uint8_t for n follows)
8772 {
8773 basic_json result = value_t::array;
8774 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
8775 idx += 1; // skip 1 size byte
8776 for (size_t i = 0; i < len; ++i)
8777 {
8778 result.push_back(from_cbor_internal(v, idx));
8779 }
8780 return result;
8781 }
8782
8783 case 0x99: // array (two-byte uint16_t for n follow)
8784 {
8785 basic_json result = value_t::array;
8786 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
8787 idx += 2; // skip 4 size bytes
8788 for (size_t i = 0; i < len; ++i)
8789 {
8790 result.push_back(from_cbor_internal(v, idx));
8791 }
8792 return result;
8793 }
8794
8795 case 0x9a: // array (four-byte uint32_t for n follow)
8796 {
8797 basic_json result = value_t::array;
8798 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
8799 idx += 4; // skip 4 size bytes
8800 for (size_t i = 0; i < len; ++i)
8801 {
8802 result.push_back(from_cbor_internal(v, idx));
8803 }
8804 return result;
8805 }
8806
8807 case 0x9b: // array (eight-byte uint64_t for n follow)
8808 {
8809 basic_json result = value_t::array;
8810 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
8811 idx += 8; // skip 8 size bytes
8812 for (size_t i = 0; i < len; ++i)
8813 {
8814 result.push_back(from_cbor_internal(v, idx));
8815 }
8816 return result;
8817 }
8818
8819 case 0x9f: // array (indefinite length)
8820 {
8821 basic_json result = value_t::array;
8822 while (static_cast<void>(check_length(v.size(), 1, idx)), v[idx] != 0xff)
8823 {
8824 result.push_back(from_cbor_internal(v, idx));
8825 }
8826 // skip break byte (0xFF)
8827 idx += 1;
8828 return result;
8829 }
8830
8831 // map (0x00..0x17 pairs of data items follow)
8832 case 0xa0:
8833 case 0xa1:
8834 case 0xa2:
8835 case 0xa3:
8836 case 0xa4:
8837 case 0xa5:
8838 case 0xa6:
8839 case 0xa7:
8840 case 0xa8:
8841 case 0xa9:
8842 case 0xaa:
8843 case 0xab:
8844 case 0xac:
8845 case 0xad:
8846 case 0xae:
8847 case 0xaf:
8848 case 0xb0:
8849 case 0xb1:
8850 case 0xb2:
8851 case 0xb3:
8852 case 0xb4:
8853 case 0xb5:
8854 case 0xb6:
8855 case 0xb7:
8856 {
8857 basic_json result = value_t::object;
8858 const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
8859 for (size_t i = 0; i < len; ++i)
8860 {
8861 cbor_expect_string(v, idx);
8862 std::string key = from_cbor_internal(v, idx);
8863 result[key] = from_cbor_internal(v, idx);
8864 }
8865 return result;
8866 }
8867
8868 case 0xb8: // map (one-byte uint8_t for n follows)
8869 {
8870 basic_json result = value_t::object;
8871 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
8872 idx += 1; // skip 1 size byte
8873 for (size_t i = 0; i < len; ++i)
8874 {
8875 cbor_expect_string(v, idx);
8876 std::string key = from_cbor_internal(v, idx);
8877 result[key] = from_cbor_internal(v, idx);
8878 }
8879 return result;
8880 }
8881
8882 case 0xb9: // map (two-byte uint16_t for n follow)
8883 {
8884 basic_json result = value_t::object;
8885 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
8886 idx += 2; // skip 2 size bytes
8887 for (size_t i = 0; i < len; ++i)
8888 {
8889 cbor_expect_string(v, idx);
8890 std::string key = from_cbor_internal(v, idx);
8891 result[key] = from_cbor_internal(v, idx);
8892 }
8893 return result;
8894 }
8895
8896 case 0xba: // map (four-byte uint32_t for n follow)
8897 {
8898 basic_json result = value_t::object;
8899 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
8900 idx += 4; // skip 4 size bytes
8901 for (size_t i = 0; i < len; ++i)
8902 {
8903 cbor_expect_string(v, idx);
8904 std::string key = from_cbor_internal(v, idx);
8905 result[key] = from_cbor_internal(v, idx);
8906 }
8907 return result;
8908 }
8909
8910 case 0xbb: // map (eight-byte uint64_t for n follow)
8911 {
8912 basic_json result = value_t::object;
8913 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
8914 idx += 8; // skip 8 size bytes
8915 for (size_t i = 0; i < len; ++i)
8916 {
8917 cbor_expect_string(v, idx);
8918 std::string key = from_cbor_internal(v, idx);
8919 result[key] = from_cbor_internal(v, idx);
8920 }
8921 return result;
8922 }
8923
8924 case 0xbf: // map (indefinite length)
8925 {
8926 basic_json result = value_t::object;
8927 while (static_cast<void>(check_length(v.size(), 1, idx)), v[idx] != 0xff)
8928 {
8929 cbor_expect_string(v, idx);
8930 std::string key = from_cbor_internal(v, idx);
8931 result[key] = from_cbor_internal(v, idx);
8932 }
8933 // skip break byte (0xFF)
8934 idx += 1;
8935 return result;
8936 }
8937
8938 case 0xf4: // false
8939 {
8940 return false;
8941 }
8942
8943 case 0xf5: // true
8944 {
8945 return true;
8946 }
8947
8948 case 0xf6: // null
8949 {
8950 return value_t::null;
8951 }
8952
8953 case 0xf9: // Half-Precision Float (two-byte IEEE 754)
8954 {
8955 idx += 2; // skip two content bytes
8956
8957 // code from RFC 7049, Appendix D, Figure 3:
8958 // As half-precision floating-point numbers were only added to
8959 // IEEE 754 in 2008, today's programming platforms often still
8960 // only have limited support for them. It is very easy to
8961 // include at least decoding support for them even without such
8962 // support. An example of a small decoder for half-precision
8963 // floating-point numbers in the C language is shown in Fig. 3.
8964 check_length(v.size(), 2, current_idx + 1);
8965 const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
8966 const int exp = (half >> 10) & 0x1f;
8967 const int mant = half & 0x3ff;
8968 double val;
8969 if (exp == 0)
8970 {
8971 val = std::ldexp(mant, -24);
8972 }
8973 else if (exp != 31)
8974 {
8975 val = std::ldexp(mant + 1024, exp - 25);
8976 }
8977 else
8978 {
8979 val = mant == 0
8980 ? std::numeric_limits<double>::infinity()
8981 : std::numeric_limits<double>::quiet_NaN();
8982 }
8983 return (half & 0x8000) != 0 ? -val : val;
8984 }
8985
8986 case 0xfa: // Single-Precision Float (four-byte IEEE 754)
8987 {
8988 // copy bytes in reverse order into the float variable
8989 float res;
8990 check_length(v.size(), sizeof(float), current_idx + 1);
8991 for (size_t byte = 0; byte < sizeof(float); ++byte)
8992 {
8993 reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
8994 }
8995 idx += sizeof(float); // skip content bytes
8996 return res;
8997 }
8998
8999 case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
9000 {
9001 // copy bytes in reverse order into the double variable
9002 double res;
9003 check_length(v.size(), sizeof(double), current_idx + 1);
9004 for (size_t byte = 0; byte < sizeof(double); ++byte)
9005 {
9006 reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
9007 }
9008 idx += sizeof(double); // skip content bytes
9009 return res;
9010 }
9011
9012 default: // anything else (0xFF is handled inside the other types)
9013 {
9014 std::stringstream ss;
9015 ss << std::hex << static_cast<int>(v[current_idx]);
9016 JSON_THROW(parse_error::create(112, current_idx + 1, "error reading CBOR; last byte: 0x" + ss.str()));
9017 }
9018 }
9019 }
9020
9021 public:
9096 static std::vector<uint8_t> to_msgpack(const basic_json& j)
9097 {
9098 std::vector<uint8_t> result;
9099 to_msgpack_internal(j, result);
9100 return result;
9101 }
9102
9170 static basic_json from_msgpack(const std::vector<uint8_t>& v,
9171 const size_t start_index = 0)
9172 {
9173 size_t i = start_index;
9174 return from_msgpack_internal(v, i);
9175 }
9176
9259 static std::vector<uint8_t> to_cbor(const basic_json& j)
9260 {
9261 std::vector<uint8_t> result;
9262 to_cbor_internal(j, result);
9263 return result;
9264 }
9265
9353 static basic_json from_cbor(const std::vector<uint8_t>& v,
9354 const size_t start_index = 0)
9355 {
9356 size_t i = start_index;
9357 return from_cbor_internal(v, i);
9358 }
9359
9361
9363 // convenience functions //
9365
9381 std::string type_name() const
9382 {
9383 {
9384 switch (m_type)
9385 {
9386 case value_t::null:
9387 return "null";
9388 case value_t::object:
9389 return "object";
9390 case value_t::array:
9391 return "array";
9392 case value_t::string:
9393 return "string";
9394 case value_t::boolean:
9395 return "boolean";
9396 case value_t::discarded:
9397 return "discarded";
9398 default:
9399 return "number";
9400 }
9401 }
9402 }
9403
9404
9405 private:
9407 // member variables //
9409
9411 value_t m_type = value_t::null;
9412
9414 json_value m_value = {};
9415
9416
9417 private:
9419 // iterators //
9421
9431 class primitive_iterator_t
9432 {
9433 public:
9434
9435 difference_type get_value() const noexcept
9436 {
9437 return m_it;
9438 }
9440 void set_begin() noexcept
9441 {
9442 m_it = begin_value;
9443 }
9444
9446 void set_end() noexcept
9447 {
9448 m_it = end_value;
9449 }
9450
9452 constexpr bool is_begin() const noexcept
9453 {
9454 return (m_it == begin_value);
9455 }
9456
9458 constexpr bool is_end() const noexcept
9459 {
9460 return (m_it == end_value);
9461 }
9462
9463 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9464 {
9465 return lhs.m_it == rhs.m_it;
9466 }
9467
9468 friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9469 {
9470 return !(lhs == rhs);
9471 }
9472
9473 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9474 {
9475 return lhs.m_it < rhs.m_it;
9476 }
9477
9478 friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9479 {
9480 return lhs.m_it <= rhs.m_it;
9481 }
9482
9483 friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9484 {
9485 return lhs.m_it > rhs.m_it;
9486 }
9487
9488 friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9489 {
9490 return lhs.m_it >= rhs.m_it;
9491 }
9492
9493 primitive_iterator_t operator+(difference_type i)
9494 {
9495 auto result = *this;
9496 result += i;
9497 return result;
9498 }
9499
9500 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9501 {
9502 return lhs.m_it - rhs.m_it;
9503 }
9504
9505 friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
9506 {
9507 return os << it.m_it;
9508 }
9509
9510 primitive_iterator_t& operator++()
9511 {
9512 ++m_it;
9513 return *this;
9514 }
9515
9516 primitive_iterator_t operator++(int)
9517 {
9518 auto result = *this;
9519 m_it++;
9520 return result;
9521 }
9522
9523 primitive_iterator_t& operator--()
9524 {
9525 --m_it;
9526 return *this;
9527 }
9528
9529 primitive_iterator_t operator--(int)
9530 {
9531 auto result = *this;
9532 m_it--;
9533 return result;
9534 }
9535
9536 primitive_iterator_t& operator+=(difference_type n)
9537 {
9538 m_it += n;
9539 return *this;
9540 }
9541
9542 primitive_iterator_t& operator-=(difference_type n)
9543 {
9544 m_it -= n;
9545 return *this;
9546 }
9547
9548 private:
9549 static constexpr difference_type begin_value = 0;
9550 static constexpr difference_type end_value = begin_value + 1;
9551
9553 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
9554 };
9555
9563 struct internal_iterator
9564 {
9566 typename object_t::iterator object_iterator;
9568 typename array_t::iterator array_iterator;
9570 primitive_iterator_t primitive_iterator;
9571
9573 internal_iterator() noexcept
9574 : object_iterator(), array_iterator(), primitive_iterator()
9575 {}
9576 };
9577
9579 template<typename IteratorType>
9580 class iteration_proxy
9581 {
9582 private:
9584 class iteration_proxy_internal
9585 {
9586 private:
9588 IteratorType anchor;
9590 size_t array_index = 0;
9591
9592 public:
9593 explicit iteration_proxy_internal(IteratorType it) noexcept
9594 : anchor(it)
9595 {}
9596
9598 iteration_proxy_internal& operator*()
9599 {
9600 return *this;
9601 }
9602
9604 iteration_proxy_internal& operator++()
9605 {
9606 ++anchor;
9607 ++array_index;
9608
9609 return *this;
9610 }
9611
9613 bool operator!= (const iteration_proxy_internal& o) const
9614 {
9615 return anchor != o.anchor;
9616 }
9617
9619 typename basic_json::string_t key() const
9620 {
9621 assert(anchor.m_object != nullptr);
9622
9623 switch (anchor.m_object->type())
9624 {
9625 // use integer array index as key
9626 case value_t::array:
9627 {
9628 return std::to_string(array_index);
9629 }
9630
9631 // use key from the object
9632 case value_t::object:
9633 {
9634 return anchor.key();
9635 }
9636
9637 // use an empty key for all primitive types
9638 default:
9639 {
9640 return "";
9641 }
9642 }
9643 }
9644
9646 typename IteratorType::reference value() const
9647 {
9648 return anchor.value();
9649 }
9650 };
9651
9653 typename IteratorType::reference container;
9654
9655 public:
9657 explicit iteration_proxy(typename IteratorType::reference cont)
9658 : container(cont)
9659 {}
9660
9662 iteration_proxy_internal begin() noexcept
9663 {
9664 return iteration_proxy_internal(container.begin());
9665 }
9666
9668 iteration_proxy_internal end() noexcept
9669 {
9670 return iteration_proxy_internal(container.end());
9671 }
9672 };
9673
9674 public:
9694 template<typename U>
9695 class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
9696 {
9698 friend class basic_json;
9699
9700 // make sure U is basic_json or const basic_json
9701 static_assert(std::is_same<U, basic_json>::value
9702 or std::is_same<U, const basic_json>::value,
9703 "iter_impl only accepts (const) basic_json");
9704
9705 public:
9707 using value_type = typename basic_json::value_type;
9709 using difference_type = typename basic_json::difference_type;
9711 using pointer = typename std::conditional<std::is_const<U>::value,
9712 typename basic_json::const_pointer,
9713 typename basic_json::pointer>::type;
9715 using reference = typename std::conditional<std::is_const<U>::value,
9716 typename basic_json::const_reference,
9717 typename basic_json::reference>::type;
9719 using iterator_category = std::bidirectional_iterator_tag;
9720
9722 iter_impl() = default;
9723
9730 explicit iter_impl(pointer object) noexcept
9731 : m_object(object)
9732 {
9733 assert(m_object != nullptr);
9734
9735 switch (m_object->m_type)
9736 {
9737 case basic_json::value_t::object:
9738 {
9739 m_it.object_iterator = typename object_t::iterator();
9740 break;
9741 }
9742
9743 case basic_json::value_t::array:
9744 {
9745 m_it.array_iterator = typename array_t::iterator();
9746 break;
9747 }
9748
9749 default:
9750 {
9751 m_it.primitive_iterator = primitive_iterator_t();
9752 break;
9753 }
9754 }
9755 }
9756
9757 /*
9758 Use operator `const_iterator` instead of `const_iterator(const iterator&
9759 other) noexcept` to avoid two class definitions for @ref iterator and
9760 @ref const_iterator.
9761
9762 This function is only called if this class is an @ref iterator. If this
9763 class is a @ref const_iterator this function is not called.
9764 */
9765 operator const_iterator() const
9766 {
9767 const_iterator ret;
9768
9769 if (m_object)
9770 {
9771 ret.m_object = m_object;
9772 ret.m_it = m_it;
9773 }
9774
9775 return ret;
9776 }
9777
9783 iter_impl(const iter_impl& other) noexcept
9784 : m_object(other.m_object), m_it(other.m_it)
9785 {}
9786
9792 iter_impl& operator=(iter_impl other) noexcept(
9793 std::is_nothrow_move_constructible<pointer>::value and
9794 std::is_nothrow_move_assignable<pointer>::value and
9795 std::is_nothrow_move_constructible<internal_iterator>::value and
9796 std::is_nothrow_move_assignable<internal_iterator>::value
9797 )
9798 {
9799 std::swap(m_object, other.m_object);
9800 std::swap(m_it, other.m_it);
9801 return *this;
9802 }
9803
9804 private:
9809 void set_begin() noexcept
9810 {
9811 assert(m_object != nullptr);
9812
9813 switch (m_object->m_type)
9814 {
9815 case basic_json::value_t::object:
9816 {
9817 m_it.object_iterator = m_object->m_value.object->begin();
9818 break;
9819 }
9820
9821 case basic_json::value_t::array:
9822 {
9823 m_it.array_iterator = m_object->m_value.array->begin();
9824 break;
9825 }
9826
9827 case basic_json::value_t::null:
9828 {
9829 // set to end so begin()==end() is true: null is empty
9830 m_it.primitive_iterator.set_end();
9831 break;
9832 }
9833
9834 default:
9835 {
9836 m_it.primitive_iterator.set_begin();
9837 break;
9838 }
9839 }
9840 }
9841
9846 void set_end() noexcept
9847 {
9848 assert(m_object != nullptr);
9849
9850 switch (m_object->m_type)
9851 {
9852 case basic_json::value_t::object:
9853 {
9854 m_it.object_iterator = m_object->m_value.object->end();
9855 break;
9856 }
9857
9858 case basic_json::value_t::array:
9859 {
9860 m_it.array_iterator = m_object->m_value.array->end();
9861 break;
9862 }
9863
9864 default:
9865 {
9866 m_it.primitive_iterator.set_end();
9867 break;
9868 }
9869 }
9870 }
9871
9872 public:
9877 reference operator*() const
9878 {
9879 assert(m_object != nullptr);
9880
9881 switch (m_object->m_type)
9882 {
9883 case basic_json::value_t::object:
9884 {
9885 assert(m_it.object_iterator != m_object->m_value.object->end());
9886 return m_it.object_iterator->second;
9887 }
9888
9889 case basic_json::value_t::array:
9890 {
9891 assert(m_it.array_iterator != m_object->m_value.array->end());
9892 return *m_it.array_iterator;
9893 }
9894
9895 case basic_json::value_t::null:
9896 {
9897 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9898 }
9899
9900 default:
9901 {
9902 if (m_it.primitive_iterator.is_begin())
9903 {
9904 return *m_object;
9905 }
9906
9907 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9908 }
9909 }
9910 }
9911
9916 pointer operator->() const
9917 {
9918 assert(m_object != nullptr);
9919
9920 switch (m_object->m_type)
9921 {
9922 case basic_json::value_t::object:
9923 {
9924 assert(m_it.object_iterator != m_object->m_value.object->end());
9925 return &(m_it.object_iterator->second);
9926 }
9927
9928 case basic_json::value_t::array:
9929 {
9930 assert(m_it.array_iterator != m_object->m_value.array->end());
9931 return &*m_it.array_iterator;
9932 }
9933
9934 default:
9935 {
9936 if (m_it.primitive_iterator.is_begin())
9937 {
9938 return m_object;
9939 }
9940
9941 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9942 }
9943 }
9944 }
9945
9950 iter_impl operator++(int)
9951 {
9952 auto result = *this;
9953 ++(*this);
9954 return result;
9955 }
9956
9961 iter_impl& operator++()
9962 {
9963 assert(m_object != nullptr);
9964
9965 switch (m_object->m_type)
9966 {
9967 case basic_json::value_t::object:
9968 {
9969 std::advance(m_it.object_iterator, 1);
9970 break;
9971 }
9972
9973 case basic_json::value_t::array:
9974 {
9975 std::advance(m_it.array_iterator, 1);
9976 break;
9977 }
9978
9979 default:
9980 {
9981 ++m_it.primitive_iterator;
9982 break;
9983 }
9984 }
9985
9986 return *this;
9987 }
9988
9993 iter_impl operator--(int)
9994 {
9995 auto result = *this;
9996 --(*this);
9997 return result;
9998 }
9999
10004 iter_impl& operator--()
10005 {
10006 assert(m_object != nullptr);
10007
10008 switch (m_object->m_type)
10009 {
10010 case basic_json::value_t::object:
10011 {
10012 std::advance(m_it.object_iterator, -1);
10013 break;
10014 }
10015
10016 case basic_json::value_t::array:
10017 {
10018 std::advance(m_it.array_iterator, -1);
10019 break;
10020 }
10021
10022 default:
10023 {
10024 --m_it.primitive_iterator;
10025 break;
10026 }
10027 }
10028
10029 return *this;
10030 }
10031
10036 bool operator==(const iter_impl& other) const
10037 {
10038 // if objects are not the same, the comparison is undefined
10039 if (m_object != other.m_object)
10040 {
10041 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
10042 }
10043
10044 assert(m_object != nullptr);
10045
10046 switch (m_object->m_type)
10047 {
10048 case basic_json::value_t::object:
10049 {
10050 return (m_it.object_iterator == other.m_it.object_iterator);
10051 }
10052
10053 case basic_json::value_t::array:
10054 {
10055 return (m_it.array_iterator == other.m_it.array_iterator);
10056 }
10057
10058 default:
10059 {
10060 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
10061 }
10062 }
10063 }
10064
10069 bool operator!=(const iter_impl& other) const
10070 {
10071 return not operator==(other);
10072 }
10073
10078 bool operator<(const iter_impl& other) const
10079 {
10080 // if objects are not the same, the comparison is undefined
10081 if (m_object != other.m_object)
10082 {
10083 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
10084 }
10085
10086 assert(m_object != nullptr);
10087
10088 switch (m_object->m_type)
10089 {
10090 case basic_json::value_t::object:
10091 {
10092 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
10093 }
10094
10095 case basic_json::value_t::array:
10096 {
10097 return (m_it.array_iterator < other.m_it.array_iterator);
10098 }
10099
10100 default:
10101 {
10102 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
10103 }
10104 }
10105 }
10106
10111 bool operator<=(const iter_impl& other) const
10112 {
10113 return not other.operator < (*this);
10114 }
10115
10120 bool operator>(const iter_impl& other) const
10121 {
10122 return not operator<=(other);
10123 }
10124
10129 bool operator>=(const iter_impl& other) const
10130 {
10131 return not operator<(other);
10132 }
10133
10138 iter_impl& operator+=(difference_type i)
10139 {
10140 assert(m_object != nullptr);
10141
10142 switch (m_object->m_type)
10143 {
10144 case basic_json::value_t::object:
10145 {
10146 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
10147 }
10148
10149 case basic_json::value_t::array:
10150 {
10151 std::advance(m_it.array_iterator, i);
10152 break;
10153 }
10154
10155 default:
10156 {
10157 m_it.primitive_iterator += i;
10158 break;
10159 }
10160 }
10161
10162 return *this;
10163 }
10164
10169 iter_impl& operator-=(difference_type i)
10170 {
10171 return operator+=(-i);
10172 }
10173
10178 iter_impl operator+(difference_type i)
10179 {
10180 auto result = *this;
10181 result += i;
10182 return result;
10183 }
10184
10189 iter_impl operator-(difference_type i)
10190 {
10191 auto result = *this;
10192 result -= i;
10193 return result;
10194 }
10195
10200 difference_type operator-(const iter_impl& other) const
10201 {
10202 assert(m_object != nullptr);
10203
10204 switch (m_object->m_type)
10205 {
10206 case basic_json::value_t::object:
10207 {
10208 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
10209 }
10210
10211 case basic_json::value_t::array:
10212 {
10213 return m_it.array_iterator - other.m_it.array_iterator;
10214 }
10215
10216 default:
10217 {
10218 return m_it.primitive_iterator - other.m_it.primitive_iterator;
10219 }
10220 }
10221 }
10222
10227 reference operator[](difference_type n) const
10228 {
10229 assert(m_object != nullptr);
10230
10231 switch (m_object->m_type)
10232 {
10233 case basic_json::value_t::object:
10234 {
10235 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
10236 }
10237
10238 case basic_json::value_t::array:
10239 {
10240 return *std::next(m_it.array_iterator, n);
10241 }
10242
10243 case basic_json::value_t::null:
10244 {
10245 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
10246 }
10247
10248 default:
10249 {
10250 if (m_it.primitive_iterator.get_value() == -n)
10251 {
10252 return *m_object;
10253 }
10254
10255 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
10256 }
10257 }
10258 }
10259
10264 typename object_t::key_type key() const
10265 {
10266 assert(m_object != nullptr);
10267
10268 if (m_object->is_object())
10269 {
10270 return m_it.object_iterator->first;
10271 }
10272
10273 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
10274 }
10275
10280 reference value() const
10281 {
10282 return operator*();
10283 }
10284
10285 private:
10287 pointer m_object = nullptr;
10289 internal_iterator m_it = internal_iterator();
10290 };
10291
10309 template<typename Base>
10310 class json_reverse_iterator : public std::reverse_iterator<Base>
10311 {
10312 public:
10314 using base_iterator = std::reverse_iterator<Base>;
10316 using reference = typename Base::reference;
10317
10319 json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
10320 : base_iterator(it)
10321 {}
10322
10324 json_reverse_iterator(const base_iterator& it) noexcept
10325 : base_iterator(it)
10326 {}
10327
10329 json_reverse_iterator operator++(int)
10330 {
10331 return base_iterator::operator++(1);
10332 }
10333
10335 json_reverse_iterator& operator++()
10336 {
10337 base_iterator::operator++();
10338 return *this;
10339 }
10340
10342 json_reverse_iterator operator--(int)
10343 {
10344 return base_iterator::operator--(1);
10345 }
10346
10348 json_reverse_iterator& operator--()
10349 {
10350 base_iterator::operator--();
10351 return *this;
10352 }
10353
10355 json_reverse_iterator& operator+=(difference_type i)
10356 {
10357 base_iterator::operator+=(i);
10358 return *this;
10359 }
10360
10362 json_reverse_iterator operator+(difference_type i) const
10363 {
10364 auto result = *this;
10365 result += i;
10366 return result;
10367 }
10368
10370 json_reverse_iterator operator-(difference_type i) const
10371 {
10372 auto result = *this;
10373 result -= i;
10374 return result;
10375 }
10376
10378 difference_type operator-(const json_reverse_iterator& other) const
10379 {
10380 return this->base() - other.base();
10381 }
10382
10384 reference operator[](difference_type n) const
10385 {
10386 return *(this->operator+(n));
10387 }
10388
10390 typename object_t::key_type key() const
10391 {
10392 auto it = --this->base();
10393 return it.key();
10394 }
10395
10397 reference value() const
10398 {
10399 auto it = --this->base();
10400 return it.operator * ();
10401 }
10402 };
10403
10404
10405 private:
10407 // lexer and parser //
10409
10417 class lexer
10418 {
10419 public:
10421 enum class token_type
10422 {
10423 uninitialized,
10424 literal_true,
10425 literal_false,
10426 literal_null,
10427 value_string,
10428 value_unsigned,
10429 value_integer,
10430 value_float,
10431 begin_array,
10432 begin_object,
10433 end_array,
10434 end_object,
10435 name_separator,
10436 value_separator,
10437 parse_error,
10438 end_of_input
10439 };
10440
10442 using lexer_char_t = unsigned char;
10443
10445 lexer(const lexer_char_t* buff, const size_t len) noexcept
10446 : m_content(buff)
10447 {
10448 assert(m_content != nullptr);
10449 m_start = m_cursor = m_content;
10450 m_limit = m_content + len;
10451 }
10452
10457 explicit lexer(std::istream& s)
10458 : m_stream(&s), m_line_buffer()
10459 {
10460 // immediately abort if stream is erroneous
10461 if (s.fail())
10462 {
10463 JSON_THROW(parse_error::create(111, 0, "bad input stream"));
10464 }
10465
10466 // fill buffer
10467 fill_line_buffer();
10468
10469 // skip UTF-8 byte-order mark
10470 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
10471 {
10472 m_line_buffer[0] = ' ';
10473 m_line_buffer[1] = ' ';
10474 m_line_buffer[2] = ' ';
10475 }
10476 }
10477
10478 // switch off unwanted functions (due to pointer members)
10479 lexer() = delete;
10480 lexer(const lexer&) = delete;
10481 lexer operator=(const lexer&) = delete;
10482
10506 string_t to_unicode(const std::size_t codepoint1,
10507 const std::size_t codepoint2 = 0) const
10508 {
10509 // calculate the code point from the given code points
10510 std::size_t codepoint = codepoint1;
10511
10512 // check if codepoint1 is a high surrogate
10513 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
10514 {
10515 // check if codepoint2 is a low surrogate
10516 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
10517 {
10518 codepoint =
10519 // high surrogate occupies the most significant 22 bits
10520 (codepoint1 << 10)
10521 // low surrogate occupies the least significant 15 bits
10522 + codepoint2
10523 // there is still the 0xD800, 0xDC00 and 0x10000 noise
10524 // in the result so we have to subtract with:
10525 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
10526 - 0x35FDC00;
10527 }
10528 else
10529 {
10530 JSON_THROW(parse_error::create(102, get_position(), "missing or wrong low surrogate"));
10531 }
10532 }
10533
10534 string_t result;
10535
10536 if (codepoint < 0x80)
10537 {
10538 // 1-byte characters: 0xxxxxxx (ASCII)
10539 result.append(1, static_cast<typename string_t::value_type>(codepoint));
10540 }
10541 else if (codepoint <= 0x7ff)
10542 {
10543 // 2-byte characters: 110xxxxx 10xxxxxx
10544 result.append(1, static_cast<typename string_t::value_type>(0xC0 | (codepoint >> 6)));
10545 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
10546 }
10547 else if (codepoint <= 0xffff)
10548 {
10549 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
10550 result.append(1, static_cast<typename string_t::value_type>(0xE0 | (codepoint >> 12)));
10551 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
10552 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
10553 }
10554 else if (codepoint <= 0x10ffff)
10555 {
10556 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
10557 result.append(1, static_cast<typename string_t::value_type>(0xF0 | (codepoint >> 18)));
10558 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
10559 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
10560 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
10561 }
10562 else
10563 {
10564 JSON_THROW(parse_error::create(103, get_position(), "code points above 0x10FFFF are invalid"));
10565 }
10566
10567 return result;
10568 }
10569
10571 static std::string token_type_name(const token_type t)
10572 {
10573 switch (t)
10574 {
10575 case token_type::uninitialized:
10576 return "<uninitialized>";
10577 case token_type::literal_true:
10578 return "true literal";
10579 case token_type::literal_false:
10580 return "false literal";
10581 case token_type::literal_null:
10582 return "null literal";
10583 case token_type::value_string:
10584 return "string literal";
10585 case lexer::token_type::value_unsigned:
10586 case lexer::token_type::value_integer:
10587 case lexer::token_type::value_float:
10588 return "number literal";
10589 case token_type::begin_array:
10590 return "'['";
10591 case token_type::begin_object:
10592 return "'{'";
10593 case token_type::end_array:
10594 return "']'";
10595 case token_type::end_object:
10596 return "'}'";
10597 case token_type::name_separator:
10598 return "':'";
10599 case token_type::value_separator:
10600 return "','";
10601 case token_type::parse_error:
10602 return "<parse error>";
10603 case token_type::end_of_input:
10604 return "end of input";
10605 default:
10606 {
10607 // catch non-enum values
10608 return "unknown token"; // LCOV_EXCL_LINE
10609 }
10610 }
10611 }
10612
10633 token_type scan()
10634 {
10635 while (true)
10636 {
10637 // pointer for backtracking information
10638 m_marker = nullptr;
10639
10640 // remember the begin of the token
10641 m_start = m_cursor;
10642 assert(m_start != nullptr);
10643
10644
10645 {
10646 lexer_char_t yych;
10647 unsigned int yyaccept = 0;
10648 static const unsigned char yybm[] =
10649 {
10650 0, 0, 0, 0, 0, 0, 0, 0,
10651 0, 32, 32, 0, 0, 32, 0, 0,
10652 0, 0, 0, 0, 0, 0, 0, 0,
10653 0, 0, 0, 0, 0, 0, 0, 0,
10654 160, 128, 0, 128, 128, 128, 128, 128,
10655 128, 128, 128, 128, 128, 128, 128, 128,
10656 192, 192, 192, 192, 192, 192, 192, 192,
10657 192, 192, 128, 128, 128, 128, 128, 128,
10658 128, 128, 128, 128, 128, 128, 128, 128,
10659 128, 128, 128, 128, 128, 128, 128, 128,
10660 128, 128, 128, 128, 128, 128, 128, 128,
10661 128, 128, 128, 128, 0, 128, 128, 128,
10662 128, 128, 128, 128, 128, 128, 128, 128,
10663 128, 128, 128, 128, 128, 128, 128, 128,
10664 128, 128, 128, 128, 128, 128, 128, 128,
10665 128, 128, 128, 128, 128, 128, 128, 128,
10666 0, 0, 0, 0, 0, 0, 0, 0,
10667 0, 0, 0, 0, 0, 0, 0, 0,
10668 0, 0, 0, 0, 0, 0, 0, 0,
10669 0, 0, 0, 0, 0, 0, 0, 0,
10670 0, 0, 0, 0, 0, 0, 0, 0,
10671 0, 0, 0, 0, 0, 0, 0, 0,
10672 0, 0, 0, 0, 0, 0, 0, 0,
10673 0, 0, 0, 0, 0, 0, 0, 0,
10674 0, 0, 0, 0, 0, 0, 0, 0,
10675 0, 0, 0, 0, 0, 0, 0, 0,
10676 0, 0, 0, 0, 0, 0, 0, 0,
10677 0, 0, 0, 0, 0, 0, 0, 0,
10678 0, 0, 0, 0, 0, 0, 0, 0,
10679 0, 0, 0, 0, 0, 0, 0, 0,
10680 0, 0, 0, 0, 0, 0, 0, 0,
10681 0, 0, 0, 0, 0, 0, 0, 0,
10682 };
10683 if ((m_limit - m_cursor) < 5)
10684 {
10685 fill_line_buffer(5); // LCOV_EXCL_LINE
10686 }
10687 yych = *m_cursor;
10688 if (yybm[0 + yych] & 32)
10689 {
10690 goto basic_json_parser_6;
10691 }
10692 if (yych <= '[')
10693 {
10694 if (yych <= '-')
10695 {
10696 if (yych <= '"')
10697 {
10698 if (yych <= 0x00)
10699 {
10700 goto basic_json_parser_2;
10701 }
10702 if (yych <= '!')
10703 {
10704 goto basic_json_parser_4;
10705 }
10706 goto basic_json_parser_9;
10707 }
10708 else
10709 {
10710 if (yych <= '+')
10711 {
10712 goto basic_json_parser_4;
10713 }
10714 if (yych <= ',')
10715 {
10716 goto basic_json_parser_10;
10717 }
10718 goto basic_json_parser_12;
10719 }
10720 }
10721 else
10722 {
10723 if (yych <= '9')
10724 {
10725 if (yych <= '/')
10726 {
10727 goto basic_json_parser_4;
10728 }
10729 if (yych <= '0')
10730 {
10731 goto basic_json_parser_13;
10732 }
10733 goto basic_json_parser_15;
10734 }
10735 else
10736 {
10737 if (yych <= ':')
10738 {
10739 goto basic_json_parser_17;
10740 }
10741 if (yych <= 'Z')
10742 {
10743 goto basic_json_parser_4;
10744 }
10745 goto basic_json_parser_19;
10746 }
10747 }
10748 }
10749 else
10750 {
10751 if (yych <= 'n')
10752 {
10753 if (yych <= 'e')
10754 {
10755 if (yych == ']')
10756 {
10757 goto basic_json_parser_21;
10758 }
10759 goto basic_json_parser_4;
10760 }
10761 else
10762 {
10763 if (yych <= 'f')
10764 {
10765 goto basic_json_parser_23;
10766 }
10767 if (yych <= 'm')
10768 {
10769 goto basic_json_parser_4;
10770 }
10771 goto basic_json_parser_24;
10772 }
10773 }
10774 else
10775 {
10776 if (yych <= 'z')
10777 {
10778 if (yych == 't')
10779 {
10780 goto basic_json_parser_25;
10781 }
10782 goto basic_json_parser_4;
10783 }
10784 else
10785 {
10786 if (yych <= '{')
10787 {
10788 goto basic_json_parser_26;
10789 }
10790 if (yych == '}')
10791 {
10792 goto basic_json_parser_28;
10793 }
10794 goto basic_json_parser_4;
10795 }
10796 }
10797 }
10798 basic_json_parser_2:
10799 ++m_cursor;
10800 {
10801 last_token_type = token_type::end_of_input;
10802 break;
10803 }
10804 basic_json_parser_4:
10805 ++m_cursor;
10806 basic_json_parser_5:
10807 {
10808 last_token_type = token_type::parse_error;
10809 break;
10810 }
10811 basic_json_parser_6:
10812 ++m_cursor;
10813 if (m_limit <= m_cursor)
10814 {
10815 fill_line_buffer(1); // LCOV_EXCL_LINE
10816 }
10817 yych = *m_cursor;
10818 if (yybm[0 + yych] & 32)
10819 {
10820 goto basic_json_parser_6;
10821 }
10822 {
10823 position += static_cast<size_t>((m_cursor - m_start));
10824 continue;
10825 }
10826 basic_json_parser_9:
10827 yyaccept = 0;
10828 yych = *(m_marker = ++m_cursor);
10829 if (yych <= 0x1F)
10830 {
10831 goto basic_json_parser_5;
10832 }
10833 if (yych <= 0x7F)
10834 {
10835 goto basic_json_parser_31;
10836 }
10837 if (yych <= 0xC1)
10838 {
10839 goto basic_json_parser_5;
10840 }
10841 if (yych <= 0xF4)
10842 {
10843 goto basic_json_parser_31;
10844 }
10845 goto basic_json_parser_5;
10846 basic_json_parser_10:
10847 ++m_cursor;
10848 {
10849 last_token_type = token_type::value_separator;
10850 break;
10851 }
10852 basic_json_parser_12:
10853 yych = *++m_cursor;
10854 if (yych <= '/')
10855 {
10856 goto basic_json_parser_5;
10857 }
10858 if (yych <= '0')
10859 {
10860 goto basic_json_parser_43;
10861 }
10862 if (yych <= '9')
10863 {
10864 goto basic_json_parser_45;
10865 }
10866 goto basic_json_parser_5;
10867 basic_json_parser_13:
10868 yyaccept = 1;
10869 yych = *(m_marker = ++m_cursor);
10870 if (yych <= '9')
10871 {
10872 if (yych == '.')
10873 {
10874 goto basic_json_parser_47;
10875 }
10876 if (yych >= '0')
10877 {
10878 goto basic_json_parser_48;
10879 }
10880 }
10881 else
10882 {
10883 if (yych <= 'E')
10884 {
10885 if (yych >= 'E')
10886 {
10887 goto basic_json_parser_51;
10888 }
10889 }
10890 else
10891 {
10892 if (yych == 'e')
10893 {
10894 goto basic_json_parser_51;
10895 }
10896 }
10897 }
10898 basic_json_parser_14:
10899 {
10900 last_token_type = token_type::value_unsigned;
10901 break;
10902 }
10903 basic_json_parser_15:
10904 yyaccept = 1;
10905 m_marker = ++m_cursor;
10906 if ((m_limit - m_cursor) < 3)
10907 {
10908 fill_line_buffer(3); // LCOV_EXCL_LINE
10909 }
10910 yych = *m_cursor;
10911 if (yybm[0 + yych] & 64)
10912 {
10913 goto basic_json_parser_15;
10914 }
10915 if (yych <= 'D')
10916 {
10917 if (yych == '.')
10918 {
10919 goto basic_json_parser_47;
10920 }
10921 goto basic_json_parser_14;
10922 }
10923 else
10924 {
10925 if (yych <= 'E')
10926 {
10927 goto basic_json_parser_51;
10928 }
10929 if (yych == 'e')
10930 {
10931 goto basic_json_parser_51;
10932 }
10933 goto basic_json_parser_14;
10934 }
10935 basic_json_parser_17:
10936 ++m_cursor;
10937 {
10938 last_token_type = token_type::name_separator;
10939 break;
10940 }
10941 basic_json_parser_19:
10942 ++m_cursor;
10943 {
10944 last_token_type = token_type::begin_array;
10945 break;
10946 }
10947 basic_json_parser_21:
10948 ++m_cursor;
10949 {
10950 last_token_type = token_type::end_array;
10951 break;
10952 }
10953 basic_json_parser_23:
10954 yyaccept = 0;
10955 yych = *(m_marker = ++m_cursor);
10956 if (yych == 'a')
10957 {
10958 goto basic_json_parser_52;
10959 }
10960 goto basic_json_parser_5;
10961 basic_json_parser_24:
10962 yyaccept = 0;
10963 yych = *(m_marker = ++m_cursor);
10964 if (yych == 'u')
10965 {
10966 goto basic_json_parser_53;
10967 }
10968 goto basic_json_parser_5;
10969 basic_json_parser_25:
10970 yyaccept = 0;
10971 yych = *(m_marker = ++m_cursor);
10972 if (yych == 'r')
10973 {
10974 goto basic_json_parser_54;
10975 }
10976 goto basic_json_parser_5;
10977 basic_json_parser_26:
10978 ++m_cursor;
10979 {
10980 last_token_type = token_type::begin_object;
10981 break;
10982 }
10983 basic_json_parser_28:
10984 ++m_cursor;
10985 {
10986 last_token_type = token_type::end_object;
10987 break;
10988 }
10989 basic_json_parser_30:
10990 ++m_cursor;
10991 if (m_limit <= m_cursor)
10992 {
10993 fill_line_buffer(1); // LCOV_EXCL_LINE
10994 }
10995 yych = *m_cursor;
10996 basic_json_parser_31:
10997 if (yybm[0 + yych] & 128)
10998 {
10999 goto basic_json_parser_30;
11000 }
11001 if (yych <= 0xE0)
11002 {
11003 if (yych <= '\\')
11004 {
11005 if (yych <= 0x1F)
11006 {
11007 goto basic_json_parser_32;
11008 }
11009 if (yych <= '"')
11010 {
11011 goto basic_json_parser_33;
11012 }
11013 goto basic_json_parser_35;
11014 }
11015 else
11016 {
11017 if (yych <= 0xC1)
11018 {
11019 goto basic_json_parser_32;
11020 }
11021 if (yych <= 0xDF)
11022 {
11023 goto basic_json_parser_36;
11024 }
11025 goto basic_json_parser_37;
11026 }
11027 }
11028 else
11029 {
11030 if (yych <= 0xEF)
11031 {
11032 if (yych == 0xED)
11033 {
11034 goto basic_json_parser_39;
11035 }
11036 goto basic_json_parser_38;
11037 }
11038 else
11039 {
11040 if (yych <= 0xF0)
11041 {
11042 goto basic_json_parser_40;
11043 }
11044 if (yych <= 0xF3)
11045 {
11046 goto basic_json_parser_41;
11047 }
11048 if (yych <= 0xF4)
11049 {
11050 goto basic_json_parser_42;
11051 }
11052 }
11053 }
11054 basic_json_parser_32:
11055 m_cursor = m_marker;
11056 if (yyaccept <= 1)
11057 {
11058 if (yyaccept == 0)
11059 {
11060 goto basic_json_parser_5;
11061 }
11062 else
11063 {
11064 goto basic_json_parser_14;
11065 }
11066 }
11067 else
11068 {
11069 if (yyaccept == 2)
11070 {
11071 goto basic_json_parser_44;
11072 }
11073 else
11074 {
11075 goto basic_json_parser_58;
11076 }
11077 }
11078 basic_json_parser_33:
11079 ++m_cursor;
11080 {
11081 last_token_type = token_type::value_string;
11082 break;
11083 }
11084 basic_json_parser_35:
11085 ++m_cursor;
11086 if (m_limit <= m_cursor)
11087 {
11088 fill_line_buffer(1); // LCOV_EXCL_LINE
11089 }
11090 yych = *m_cursor;
11091 if (yych <= 'e')
11092 {
11093 if (yych <= '/')
11094 {
11095 if (yych == '"')
11096 {
11097 goto basic_json_parser_30;
11098 }
11099 if (yych <= '.')
11100 {
11101 goto basic_json_parser_32;
11102 }
11103 goto basic_json_parser_30;
11104 }
11105 else
11106 {
11107 if (yych <= '\\')
11108 {
11109 if (yych <= '[')
11110 {
11111 goto basic_json_parser_32;
11112 }
11113 goto basic_json_parser_30;
11114 }
11115 else
11116 {
11117 if (yych == 'b')
11118 {
11119 goto basic_json_parser_30;
11120 }
11121 goto basic_json_parser_32;
11122 }
11123 }
11124 }
11125 else
11126 {
11127 if (yych <= 'q')
11128 {
11129 if (yych <= 'f')
11130 {
11131 goto basic_json_parser_30;
11132 }
11133 if (yych == 'n')
11134 {
11135 goto basic_json_parser_30;
11136 }
11137 goto basic_json_parser_32;
11138 }
11139 else
11140 {
11141 if (yych <= 's')
11142 {
11143 if (yych <= 'r')
11144 {
11145 goto basic_json_parser_30;
11146 }
11147 goto basic_json_parser_32;
11148 }
11149 else
11150 {
11151 if (yych <= 't')
11152 {
11153 goto basic_json_parser_30;
11154 }
11155 if (yych <= 'u')
11156 {
11157 goto basic_json_parser_55;
11158 }
11159 goto basic_json_parser_32;
11160 }
11161 }
11162 }
11163 basic_json_parser_36:
11164 ++m_cursor;
11165 if (m_limit <= m_cursor)
11166 {
11167 fill_line_buffer(1); // LCOV_EXCL_LINE
11168 }
11169 yych = *m_cursor;
11170 if (yych <= 0x7F)
11171 {
11172 goto basic_json_parser_32;
11173 }
11174 if (yych <= 0xBF)
11175 {
11176 goto basic_json_parser_30;
11177 }
11178 goto basic_json_parser_32;
11179 basic_json_parser_37:
11180 ++m_cursor;
11181 if (m_limit <= m_cursor)
11182 {
11183 fill_line_buffer(1); // LCOV_EXCL_LINE
11184 }
11185 yych = *m_cursor;
11186 if (yych <= 0x9F)
11187 {
11188 goto basic_json_parser_32;
11189 }
11190 if (yych <= 0xBF)
11191 {
11192 goto basic_json_parser_36;
11193 }
11194 goto basic_json_parser_32;
11195 basic_json_parser_38:
11196 ++m_cursor;
11197 if (m_limit <= m_cursor)
11198 {
11199 fill_line_buffer(1); // LCOV_EXCL_LINE
11200 }
11201 yych = *m_cursor;
11202 if (yych <= 0x7F)
11203 {
11204 goto basic_json_parser_32;
11205 }
11206 if (yych <= 0xBF)
11207 {
11208 goto basic_json_parser_36;
11209 }
11210 goto basic_json_parser_32;
11211 basic_json_parser_39:
11212 ++m_cursor;
11213 if (m_limit <= m_cursor)
11214 {
11215 fill_line_buffer(1); // LCOV_EXCL_LINE
11216 }
11217 yych = *m_cursor;
11218 if (yych <= 0x7F)
11219 {
11220 goto basic_json_parser_32;
11221 }
11222 if (yych <= 0x9F)
11223 {
11224 goto basic_json_parser_36;
11225 }
11226 goto basic_json_parser_32;
11227 basic_json_parser_40:
11228 ++m_cursor;
11229 if (m_limit <= m_cursor)
11230 {
11231 fill_line_buffer(1); // LCOV_EXCL_LINE
11232 }
11233 yych = *m_cursor;
11234 if (yych <= 0x8F)
11235 {
11236 goto basic_json_parser_32;
11237 }
11238 if (yych <= 0xBF)
11239 {
11240 goto basic_json_parser_38;
11241 }
11242 goto basic_json_parser_32;
11243 basic_json_parser_41:
11244 ++m_cursor;
11245 if (m_limit <= m_cursor)
11246 {
11247 fill_line_buffer(1); // LCOV_EXCL_LINE
11248 }
11249 yych = *m_cursor;
11250 if (yych <= 0x7F)
11251 {
11252 goto basic_json_parser_32;
11253 }
11254 if (yych <= 0xBF)
11255 {
11256 goto basic_json_parser_38;
11257 }
11258 goto basic_json_parser_32;
11259 basic_json_parser_42:
11260 ++m_cursor;
11261 if (m_limit <= m_cursor)
11262 {
11263 fill_line_buffer(1); // LCOV_EXCL_LINE
11264 }
11265 yych = *m_cursor;
11266 if (yych <= 0x7F)
11267 {
11268 goto basic_json_parser_32;
11269 }
11270 if (yych <= 0x8F)
11271 {
11272 goto basic_json_parser_38;
11273 }
11274 goto basic_json_parser_32;
11275 basic_json_parser_43:
11276 yyaccept = 2;
11277 yych = *(m_marker = ++m_cursor);
11278 if (yych <= '9')
11279 {
11280 if (yych == '.')
11281 {
11282 goto basic_json_parser_47;
11283 }
11284 if (yych >= '0')
11285 {
11286 goto basic_json_parser_48;
11287 }
11288 }
11289 else
11290 {
11291 if (yych <= 'E')
11292 {
11293 if (yych >= 'E')
11294 {
11295 goto basic_json_parser_51;
11296 }
11297 }
11298 else
11299 {
11300 if (yych == 'e')
11301 {
11302 goto basic_json_parser_51;
11303 }
11304 }
11305 }
11306 basic_json_parser_44:
11307 {
11308 last_token_type = token_type::value_integer;
11309 break;
11310 }
11311 basic_json_parser_45:
11312 yyaccept = 2;
11313 m_marker = ++m_cursor;
11314 if ((m_limit - m_cursor) < 3)
11315 {
11316 fill_line_buffer(3); // LCOV_EXCL_LINE
11317 }
11318 yych = *m_cursor;
11319 if (yych <= '9')
11320 {
11321 if (yych == '.')
11322 {
11323 goto basic_json_parser_47;
11324 }
11325 if (yych <= '/')
11326 {
11327 goto basic_json_parser_44;
11328 }
11329 goto basic_json_parser_45;
11330 }
11331 else
11332 {
11333 if (yych <= 'E')
11334 {
11335 if (yych <= 'D')
11336 {
11337 goto basic_json_parser_44;
11338 }
11339 goto basic_json_parser_51;
11340 }
11341 else
11342 {
11343 if (yych == 'e')
11344 {
11345 goto basic_json_parser_51;
11346 }
11347 goto basic_json_parser_44;
11348 }
11349 }
11350 basic_json_parser_47:
11351 yych = *++m_cursor;
11352 if (yych <= '/')
11353 {
11354 goto basic_json_parser_32;
11355 }
11356 if (yych <= '9')
11357 {
11358 goto basic_json_parser_56;
11359 }
11360 goto basic_json_parser_32;
11361 basic_json_parser_48:
11362 ++m_cursor;
11363 if (m_limit <= m_cursor)
11364 {
11365 fill_line_buffer(1); // LCOV_EXCL_LINE
11366 }
11367 yych = *m_cursor;
11368 if (yych <= '/')
11369 {
11370 goto basic_json_parser_50;
11371 }
11372 if (yych <= '9')
11373 {
11374 goto basic_json_parser_48;
11375 }
11376 basic_json_parser_50:
11377 {
11378 last_token_type = token_type::parse_error;
11379 break;
11380 }
11381 basic_json_parser_51:
11382 yych = *++m_cursor;
11383 if (yych <= ',')
11384 {
11385 if (yych == '+')
11386 {
11387 goto basic_json_parser_59;
11388 }
11389 goto basic_json_parser_32;
11390 }
11391 else
11392 {
11393 if (yych <= '-')
11394 {
11395 goto basic_json_parser_59;
11396 }
11397 if (yych <= '/')
11398 {
11399 goto basic_json_parser_32;
11400 }
11401 if (yych <= '9')
11402 {
11403 goto basic_json_parser_60;
11404 }
11405 goto basic_json_parser_32;
11406 }
11407 basic_json_parser_52:
11408 yych = *++m_cursor;
11409 if (yych == 'l')
11410 {
11411 goto basic_json_parser_62;
11412 }
11413 goto basic_json_parser_32;
11414 basic_json_parser_53:
11415 yych = *++m_cursor;
11416 if (yych == 'l')
11417 {
11418 goto basic_json_parser_63;
11419 }
11420 goto basic_json_parser_32;
11421 basic_json_parser_54:
11422 yych = *++m_cursor;
11423 if (yych == 'u')
11424 {
11425 goto basic_json_parser_64;
11426 }
11427 goto basic_json_parser_32;
11428 basic_json_parser_55:
11429 ++m_cursor;
11430 if (m_limit <= m_cursor)
11431 {
11432 fill_line_buffer(1); // LCOV_EXCL_LINE
11433 }
11434 yych = *m_cursor;
11435 if (yych <= '@')
11436 {
11437 if (yych <= '/')
11438 {
11439 goto basic_json_parser_32;
11440 }
11441 if (yych <= '9')
11442 {
11443 goto basic_json_parser_65;
11444 }
11445 goto basic_json_parser_32;
11446 }
11447 else
11448 {
11449 if (yych <= 'F')
11450 {
11451 goto basic_json_parser_65;
11452 }
11453 if (yych <= '`')
11454 {
11455 goto basic_json_parser_32;
11456 }
11457 if (yych <= 'f')
11458 {
11459 goto basic_json_parser_65;
11460 }
11461 goto basic_json_parser_32;
11462 }
11463 basic_json_parser_56:
11464 yyaccept = 3;
11465 m_marker = ++m_cursor;
11466 if ((m_limit - m_cursor) < 3)
11467 {
11468 fill_line_buffer(3); // LCOV_EXCL_LINE
11469 }
11470 yych = *m_cursor;
11471 if (yych <= 'D')
11472 {
11473 if (yych <= '/')
11474 {
11475 goto basic_json_parser_58;
11476 }
11477 if (yych <= '9')
11478 {
11479 goto basic_json_parser_56;
11480 }
11481 }
11482 else
11483 {
11484 if (yych <= 'E')
11485 {
11486 goto basic_json_parser_51;
11487 }
11488 if (yych == 'e')
11489 {
11490 goto basic_json_parser_51;
11491 }
11492 }
11493 basic_json_parser_58:
11494 {
11495 last_token_type = token_type::value_float;
11496 break;
11497 }
11498 basic_json_parser_59:
11499 yych = *++m_cursor;
11500 if (yych <= '/')
11501 {
11502 goto basic_json_parser_32;
11503 }
11504 if (yych >= ':')
11505 {
11506 goto basic_json_parser_32;
11507 }
11508 basic_json_parser_60:
11509 ++m_cursor;
11510 if (m_limit <= m_cursor)
11511 {
11512 fill_line_buffer(1); // LCOV_EXCL_LINE
11513 }
11514 yych = *m_cursor;
11515 if (yych <= '/')
11516 {
11517 goto basic_json_parser_58;
11518 }
11519 if (yych <= '9')
11520 {
11521 goto basic_json_parser_60;
11522 }
11523 goto basic_json_parser_58;
11524 basic_json_parser_62:
11525 yych = *++m_cursor;
11526 if (yych == 's')
11527 {
11528 goto basic_json_parser_66;
11529 }
11530 goto basic_json_parser_32;
11531 basic_json_parser_63:
11532 yych = *++m_cursor;
11533 if (yych == 'l')
11534 {
11535 goto basic_json_parser_67;
11536 }
11537 goto basic_json_parser_32;
11538 basic_json_parser_64:
11539 yych = *++m_cursor;
11540 if (yych == 'e')
11541 {
11542 goto basic_json_parser_69;
11543 }
11544 goto basic_json_parser_32;
11545 basic_json_parser_65:
11546 ++m_cursor;
11547 if (m_limit <= m_cursor)
11548 {
11549 fill_line_buffer(1); // LCOV_EXCL_LINE
11550 }
11551 yych = *m_cursor;
11552 if (yych <= '@')
11553 {
11554 if (yych <= '/')
11555 {
11556 goto basic_json_parser_32;
11557 }
11558 if (yych <= '9')
11559 {
11560 goto basic_json_parser_71;
11561 }
11562 goto basic_json_parser_32;
11563 }
11564 else
11565 {
11566 if (yych <= 'F')
11567 {
11568 goto basic_json_parser_71;
11569 }
11570 if (yych <= '`')
11571 {
11572 goto basic_json_parser_32;
11573 }
11574 if (yych <= 'f')
11575 {
11576 goto basic_json_parser_71;
11577 }
11578 goto basic_json_parser_32;
11579 }
11580 basic_json_parser_66:
11581 yych = *++m_cursor;
11582 if (yych == 'e')
11583 {
11584 goto basic_json_parser_72;
11585 }
11586 goto basic_json_parser_32;
11587 basic_json_parser_67:
11588 ++m_cursor;
11589 {
11590 last_token_type = token_type::literal_null;
11591 break;
11592 }
11593 basic_json_parser_69:
11594 ++m_cursor;
11595 {
11596 last_token_type = token_type::literal_true;
11597 break;
11598 }
11599 basic_json_parser_71:
11600 ++m_cursor;
11601 if (m_limit <= m_cursor)
11602 {
11603 fill_line_buffer(1); // LCOV_EXCL_LINE
11604 }
11605 yych = *m_cursor;
11606 if (yych <= '@')
11607 {
11608 if (yych <= '/')
11609 {
11610 goto basic_json_parser_32;
11611 }
11612 if (yych <= '9')
11613 {
11614 goto basic_json_parser_74;
11615 }
11616 goto basic_json_parser_32;
11617 }
11618 else
11619 {
11620 if (yych <= 'F')
11621 {
11622 goto basic_json_parser_74;
11623 }
11624 if (yych <= '`')
11625 {
11626 goto basic_json_parser_32;
11627 }
11628 if (yych <= 'f')
11629 {
11630 goto basic_json_parser_74;
11631 }
11632 goto basic_json_parser_32;
11633 }
11634 basic_json_parser_72:
11635 ++m_cursor;
11636 {
11637 last_token_type = token_type::literal_false;
11638 break;
11639 }
11640 basic_json_parser_74:
11641 ++m_cursor;
11642 if (m_limit <= m_cursor)
11643 {
11644 fill_line_buffer(1); // LCOV_EXCL_LINE
11645 }
11646 yych = *m_cursor;
11647 if (yych <= '@')
11648 {
11649 if (yych <= '/')
11650 {
11651 goto basic_json_parser_32;
11652 }
11653 if (yych <= '9')
11654 {
11655 goto basic_json_parser_30;
11656 }
11657 goto basic_json_parser_32;
11658 }
11659 else
11660 {
11661 if (yych <= 'F')
11662 {
11663 goto basic_json_parser_30;
11664 }
11665 if (yych <= '`')
11666 {
11667 goto basic_json_parser_32;
11668 }
11669 if (yych <= 'f')
11670 {
11671 goto basic_json_parser_30;
11672 }
11673 goto basic_json_parser_32;
11674 }
11675 }
11676
11677 }
11678
11679 position += static_cast<size_t>((m_cursor - m_start));
11680 return last_token_type;
11681 }
11682
11711 void fill_line_buffer(size_t n = 0)
11712 {
11713 // if line buffer is used, m_content points to its data
11714 assert(m_line_buffer.empty()
11715 or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
11716
11717 // if line buffer is used, m_limit is set past the end of its data
11718 assert(m_line_buffer.empty()
11719 or m_limit == m_content + m_line_buffer.size());
11720
11721 // pointer relationships
11722 assert(m_content <= m_start);
11723 assert(m_start <= m_cursor);
11724 assert(m_cursor <= m_limit);
11725 assert(m_marker == nullptr or m_marker <= m_limit);
11726
11727 // number of processed characters (p)
11728 const auto num_processed_chars = static_cast<size_t>(m_start - m_content);
11729 // offset for m_marker wrt. to m_start
11730 const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
11731 // number of unprocessed characters (u)
11732 const auto offset_cursor = m_cursor - m_start;
11733
11734 // no stream is used or end of file is reached
11735 if (m_stream == nullptr or m_stream->eof())
11736 {
11737 // m_start may or may not be pointing into m_line_buffer at
11738 // this point. We trust the standard library to do the right
11739 // thing. See http://stackoverflow.com/q/28142011/266378
11740 m_line_buffer.assign(m_start, m_limit);
11741
11742 // append n characters to make sure that there is sufficient
11743 // space between m_cursor and m_limit
11744 m_line_buffer.append(1, '\x00');
11745 if (n > 0)
11746 {
11747 m_line_buffer.append(n - 1, '\x01');
11748 }
11749 }
11750 else
11751 {
11752 // delete processed characters from line buffer
11753 m_line_buffer.erase(0, num_processed_chars);
11754 // read next line from input stream
11755 m_line_buffer_tmp.clear();
11756
11757 // check if stream is still good
11758 if (m_stream->fail())
11759 {
11760 JSON_THROW(parse_error::create(111, 0, "bad input stream"));
11761 }
11762
11763 std::getline(*m_stream, m_line_buffer_tmp, '\n');
11764
11765 // add line with newline symbol to the line buffer
11766 m_line_buffer += m_line_buffer_tmp;
11767 m_line_buffer.push_back('\n');
11768 }
11769
11770 // set pointers
11771 m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
11772 assert(m_content != nullptr);
11773 m_start = m_content;
11774 m_marker = m_start + offset_marker;
11775 m_cursor = m_start + offset_cursor;
11776 m_limit = m_start + m_line_buffer.size();
11777 }
11778
11780 string_t get_token_string() const
11781 {
11782 assert(m_start != nullptr);
11783 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
11784 static_cast<size_t>(m_cursor - m_start));
11785 }
11786
11845 string_t get_string() const
11846 {
11847 assert(m_cursor - m_start >= 2);
11848
11849 string_t result;
11850 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
11851
11852 // iterate the result between the quotes
11853 for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
11854 {
11855 // find next escape character
11856 auto e = std::find(i, m_cursor - 1, '\\');
11857 if (e != i)
11858 {
11859 // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
11860 for (auto k = i; k < e; k++)
11861 {
11862 result.push_back(static_cast<typename string_t::value_type>(*k));
11863 }
11864 i = e - 1; // -1 because of ++i
11865 }
11866 else
11867 {
11868 // processing escaped character
11869 // read next character
11870 ++i;
11871
11872 switch (*i)
11873 {
11874 // the default escapes
11875 case 't':
11876 {
11877 result += "\t";
11878 break;
11879 }
11880 case 'b':
11881 {
11882 result += "\b";
11883 break;
11884 }
11885 case 'f':
11886 {
11887 result += "\f";
11888 break;
11889 }
11890 case 'n':
11891 {
11892 result += "\n";
11893 break;
11894 }
11895 case 'r':
11896 {
11897 result += "\r";
11898 break;
11899 }
11900 case '\\':
11901 {
11902 result += "\\";
11903 break;
11904 }
11905 case '/':
11906 {
11907 result += "/";
11908 break;
11909 }
11910 case '"':
11911 {
11912 result += "\"";
11913 break;
11914 }
11915
11916 // unicode
11917 case 'u':
11918 {
11919 // get code xxxx from uxxxx
11920 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
11921 4).c_str(), nullptr, 16);
11922
11923 // check if codepoint is a high surrogate
11924 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
11925 {
11926 // make sure there is a subsequent unicode
11927 if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
11928 {
11929 JSON_THROW(parse_error::create(102, get_position(), "missing low surrogate"));
11930 }
11931
11932 // get code yyyy from uxxxx\uyyyy
11933 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
11934 (i + 7), 4).c_str(), nullptr, 16);
11935 result += to_unicode(codepoint, codepoint2);
11936 // skip the next 10 characters (xxxx\uyyyy)
11937 i += 10;
11938 }
11939 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
11940 {
11941 // we found a lone low surrogate
11942 JSON_THROW(parse_error::create(102, get_position(), "missing high surrogate"));
11943 }
11944 else
11945 {
11946 // add unicode character(s)
11947 result += to_unicode(codepoint);
11948 // skip the next four characters (xxxx)
11949 i += 4;
11950 }
11951 break;
11952 }
11953 }
11954 }
11955 }
11956
11957 return result;
11958 }
11959
11960
11970 struct strtonum
11971 {
11972 public:
11973 strtonum(const char* start, const char* end)
11974 : m_start(start), m_end(end)
11975 {}
11976
11983 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
11984 bool to(T& val) const
11985 {
11986 return parse(val, std::is_integral<T>());
11987 }
11988
11989 private:
11990 const char* const m_start = nullptr;
11991 const char* const m_end = nullptr;
11992
11993 // floating-point conversion
11994
11995 // overloaded wrappers for strtod/strtof/strtold
11996 // that will be called from parse<floating_point_t>
11997 static void strtof(float& f, const char* str, char** endptr)
11998 {
11999 f = std::strtof(str, endptr);
12000 }
12001
12002 static void strtof(double& f, const char* str, char** endptr)
12003 {
12004 f = std::strtod(str, endptr);
12005 }
12006
12007 static void strtof(long double& f, const char* str, char** endptr)
12008 {
12009 f = std::strtold(str, endptr);
12010 }
12011
12012 template<typename T>
12013 bool parse(T& value, /*is_integral=*/std::false_type) const
12014 {
12015 // replace decimal separator with locale-specific version,
12016 // when necessary; data will point to either the original
12017 // string, or buf, or tempstr containing the fixed string.
12018 std::string tempstr;
12019 std::array<char, 64> buf;
12020 const size_t len = static_cast<size_t>(m_end - m_start);
12021
12022 // lexer will reject empty numbers
12023 assert(len > 0);
12024
12025 // since dealing with strtod family of functions, we're
12026 // getting the decimal point char from the C locale facilities
12027 // instead of C++'s numpunct facet of the current std::locale
12028 const auto loc = localeconv();
12029 assert(loc != nullptr);
12030 const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];
12031
12032 const char* data = m_start;
12033
12034 if (decimal_point_char != '.')
12035 {
12036 const size_t ds_pos = static_cast<size_t>(std::find(m_start, m_end, '.') - m_start);
12037
12038 if (ds_pos != len)
12039 {
12040 // copy the data into the local buffer or tempstr, if
12041 // buffer is too small; replace decimal separator, and
12042 // update data to point to the modified bytes
12043 if ((len + 1) < buf.size())
12044 {
12045 std::copy(m_start, m_end, buf.begin());
12046 buf[len] = 0;
12047 buf[ds_pos] = decimal_point_char;
12048 data = buf.data();
12049 }
12050 else
12051 {
12052 tempstr.assign(m_start, m_end);
12053 tempstr[ds_pos] = decimal_point_char;
12054 data = tempstr.c_str();
12055 }
12056 }
12057 }
12058
12059 char* endptr = nullptr;
12060 value = 0;
12061 // this calls appropriate overload depending on T
12062 strtof(value, data, &endptr);
12063
12064 // parsing was successful iff strtof parsed exactly the number
12065 // of characters determined by the lexer (len)
12066 const bool ok = (endptr == (data + len));
12067
12068 if (ok and (value == static_cast<T>(0.0)) and (*data == '-'))
12069 {
12070 // some implementations forget to negate the zero
12071 value = -0.0;
12072 }
12073
12074 return ok;
12075 }
12076
12077 // integral conversion
12078
12079 signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const
12080 {
12081 return std::strtoll(m_start, endptr, 10);
12082 }
12083
12084 unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const
12085 {
12086 return std::strtoull(m_start, endptr, 10);
12087 }
12088
12089 template<typename T>
12090 bool parse(T& value, /*is_integral=*/std::true_type) const
12091 {
12092 char* endptr = nullptr;
12093 errno = 0; // these are thread-local
12094 const auto x = parse_integral(&endptr, std::is_signed<T>());
12095
12096 // called right overload?
12097 static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(), "");
12098
12099 value = static_cast<T>(x);
12100
12101 return (x == static_cast<decltype(x)>(value)) // x fits into destination T
12102 and (x < 0) == (value < 0) // preserved sign
12103 //and ((x != 0) or is_integral()) // strto[u]ll did nto fail
12104 and (errno == 0) // strto[u]ll did not overflow
12105 and (m_start < m_end) // token was not empty
12106 and (endptr == m_end); // parsed entire token exactly
12107 }
12108 };
12109
12129 bool get_number(basic_json& result, const token_type token) const
12130 {
12131 assert(m_start != nullptr);
12132 assert(m_start < m_cursor);
12133 assert((token == token_type::value_unsigned) or
12134 (token == token_type::value_integer) or
12135 (token == token_type::value_float));
12136
12137 strtonum num_converter(reinterpret_cast<const char*>(m_start),
12138 reinterpret_cast<const char*>(m_cursor));
12139
12140 switch (token)
12141 {
12142 case lexer::token_type::value_unsigned:
12143 {
12144 number_unsigned_t val;
12145 if (num_converter.to(val))
12146 {
12147 // parsing successful
12148 result.m_type = value_t::number_unsigned;
12149 result.m_value = val;
12150 return true;
12151 }
12152 break;
12153 }
12154
12155 case lexer::token_type::value_integer:
12156 {
12157 number_integer_t val;
12158 if (num_converter.to(val))
12159 {
12160 // parsing successful
12161 result.m_type = value_t::number_integer;
12162 result.m_value = val;
12163 return true;
12164 }
12165 break;
12166 }
12167
12168 default:
12169 {
12170 break;
12171 }
12172 }
12173
12174 // parse float (either explicitly or because a previous conversion
12175 // failed)
12176 number_float_t val;
12177 if (num_converter.to(val))
12178 {
12179 // parsing successful
12180 result.m_type = value_t::number_float;
12181 result.m_value = val;
12182
12183 // throw in case of infinity or NAN
12184 if (not std::isfinite(result.m_value.number_float))
12185 {
12186 JSON_THROW(out_of_range::create(406, "number overflow parsing '" + get_token_string() + "'"));
12187 }
12188
12189 return true;
12190 }
12191
12192 // couldn't parse number in any format
12193 return false;
12194 }
12195
12196 constexpr size_t get_position() const
12197 {
12198 return position;
12199 }
12200
12201 private:
12203 std::istream* m_stream = nullptr;
12205 string_t m_line_buffer {};
12207 string_t m_line_buffer_tmp {};
12209 const lexer_char_t* m_content = nullptr;
12211 const lexer_char_t* m_start = nullptr;
12213 const lexer_char_t* m_marker = nullptr;
12215 const lexer_char_t* m_cursor = nullptr;
12217 const lexer_char_t* m_limit = nullptr;
12219 token_type last_token_type = token_type::end_of_input;
12221 size_t position = 0;
12222 };
12223
12229 class parser
12230 {
12231 public:
12233 parser(const char* buff, const parser_callback_t cb = nullptr)
12234 : callback(cb),
12235 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
12236 {}
12237
12242 parser(std::istream& is, const parser_callback_t cb = nullptr)
12243 : callback(cb), m_lexer(is)
12244 {}
12245
12247 template<class IteratorType, typename std::enable_if<
12248 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
12249 , int>::type
12250 = 0>
12251 parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
12252 : callback(cb),
12253 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
12254 static_cast<size_t>(std::distance(first, last)))
12255 {}
12256
12263 basic_json parse()
12264 {
12265 // read first token
12266 get_token();
12267
12268 basic_json result = parse_internal(true);
12269 result.assert_invariant();
12270
12271 expect(lexer::token_type::end_of_input);
12272
12273 // return parser result and replace it with null in case the
12274 // top-level value was discarded by the callback function
12275 return result.is_discarded() ? basic_json() : std::move(result);
12276 }
12277
12278 private:
12285 basic_json parse_internal(bool keep)
12286 {
12287 auto result = basic_json(value_t::discarded);
12288
12289 switch (last_token)
12290 {
12291 case lexer::token_type::begin_object:
12292 {
12293 if (keep and (not callback
12294 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
12295 {
12296 // explicitly set result to object to cope with {}
12297 result.m_type = value_t::object;
12298 result.m_value = value_t::object;
12299 }
12300
12301 // read next token
12302 get_token();
12303
12304 // closing } -> we are done
12305 if (last_token == lexer::token_type::end_object)
12306 {
12307 get_token();
12308 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
12309 {
12310 result = basic_json(value_t::discarded);
12311 }
12312 return result;
12313 }
12314
12315 // no comma is expected here
12316 unexpect(lexer::token_type::value_separator);
12317
12318 // otherwise: parse key-value pairs
12319 do
12320 {
12321 // ugly, but could be fixed with loop reorganization
12322 if (last_token == lexer::token_type::value_separator)
12323 {
12324 get_token();
12325 }
12326
12327 // store key
12328 expect(lexer::token_type::value_string);
12329 const auto key = m_lexer.get_string();
12330
12331 bool keep_tag = false;
12332 if (keep)
12333 {
12334 if (callback)
12335 {
12336 basic_json k(key);
12337 keep_tag = callback(depth, parse_event_t::key, k);
12338 }
12339 else
12340 {
12341 keep_tag = true;
12342 }
12343 }
12344
12345 // parse separator (:)
12346 get_token();
12347 expect(lexer::token_type::name_separator);
12348
12349 // parse and add value
12350 get_token();
12351 auto value = parse_internal(keep);
12352 if (keep and keep_tag and not value.is_discarded())
12353 {
12354 result[key] = std::move(value);
12355 }
12356 }
12357 while (last_token == lexer::token_type::value_separator);
12358
12359 // closing }
12360 expect(lexer::token_type::end_object);
12361 get_token();
12362 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
12363 {
12364 result = basic_json(value_t::discarded);
12365 }
12366
12367 return result;
12368 }
12369
12370 case lexer::token_type::begin_array:
12371 {
12372 if (keep and (not callback
12373 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
12374 {
12375 // explicitly set result to object to cope with []
12376 result.m_type = value_t::array;
12377 result.m_value = value_t::array;
12378 }
12379
12380 // read next token
12381 get_token();
12382
12383 // closing ] -> we are done
12384 if (last_token == lexer::token_type::end_array)
12385 {
12386 get_token();
12387 if (callback and not callback(--depth, parse_event_t::array_end, result))
12388 {
12389 result = basic_json(value_t::discarded);
12390 }
12391 return result;
12392 }
12393
12394 // no comma is expected here
12395 unexpect(lexer::token_type::value_separator);
12396
12397 // otherwise: parse values
12398 do
12399 {
12400 // ugly, but could be fixed with loop reorganization
12401 if (last_token == lexer::token_type::value_separator)
12402 {
12403 get_token();
12404 }
12405
12406 // parse value
12407 auto value = parse_internal(keep);
12408 if (keep and not value.is_discarded())
12409 {
12410 result.push_back(std::move(value));
12411 }
12412 }
12413 while (last_token == lexer::token_type::value_separator);
12414
12415 // closing ]
12416 expect(lexer::token_type::end_array);
12417 get_token();
12418 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
12419 {
12420 result = basic_json(value_t::discarded);
12421 }
12422
12423 return result;
12424 }
12425
12426 case lexer::token_type::literal_null:
12427 {
12428 get_token();
12429 result.m_type = value_t::null;
12430 break;
12431 }
12432
12433 case lexer::token_type::value_string:
12434 {
12435 const auto s = m_lexer.get_string();
12436 get_token();
12437 result = basic_json(s);
12438 break;
12439 }
12440
12441 case lexer::token_type::literal_true:
12442 {
12443 get_token();
12444 result.m_type = value_t::boolean;
12445 result.m_value = true;
12446 break;
12447 }
12448
12449 case lexer::token_type::literal_false:
12450 {
12451 get_token();
12452 result.m_type = value_t::boolean;
12453 result.m_value = false;
12454 break;
12455 }
12456
12457 case lexer::token_type::value_unsigned:
12458 case lexer::token_type::value_integer:
12459 case lexer::token_type::value_float:
12460 {
12461 m_lexer.get_number(result, last_token);
12462 get_token();
12463 break;
12464 }
12465
12466 default:
12467 {
12468 // the last token was unexpected
12469 unexpect(last_token);
12470 }
12471 }
12472
12473 if (keep and callback and not callback(depth, parse_event_t::value, result))
12474 {
12475 result = basic_json(value_t::discarded);
12476 }
12477 return result;
12478 }
12479
12481 typename lexer::token_type get_token()
12482 {
12483 last_token = m_lexer.scan();
12484 return last_token;
12485 }
12486
12490 void expect(typename lexer::token_type t) const
12491 {
12492 if (t != last_token)
12493 {
12494 std::string error_msg = "parse error - unexpected ";
12495 error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
12496 "'") :
12497 lexer::token_type_name(last_token));
12498 error_msg += "; expected " + lexer::token_type_name(t);
12499 JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
12500 }
12501 }
12502
12506 void unexpect(typename lexer::token_type t) const
12507 {
12508 if (t == last_token)
12509 {
12510 std::string error_msg = "parse error - unexpected ";
12511 error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
12512 "'") :
12513 lexer::token_type_name(last_token));
12514 JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
12515 }
12516 }
12517
12518 private:
12520 int depth = 0;
12522 const parser_callback_t callback = nullptr;
12524 typename lexer::token_type last_token = lexer::token_type::uninitialized;
12526 lexer m_lexer;
12527 };
12528
12529 public:
12541 class json_pointer
12542 {
12544 friend class basic_json;
12545
12546 public:
12569 explicit json_pointer(const std::string& s = "")
12570 : reference_tokens(split(s))
12571 {}
12572
12588 std::string to_string() const noexcept
12589 {
12590 return std::accumulate(reference_tokens.begin(),
12591 reference_tokens.end(), std::string{},
12592 [](const std::string & a, const std::string & b)
12593 {
12594 return a + "/" + escape(b);
12595 });
12596 }
12597
12599 operator std::string() const
12600 {
12601 return to_string();
12602 }
12603
12604 private:
12609 std::string pop_back()
12610 {
12611 if (is_root())
12612 {
12613 JSON_THROW(out_of_range::create(405, "JSON pointer has no parent"));
12614 }
12615
12616 auto last = reference_tokens.back();
12617 reference_tokens.pop_back();
12618 return last;
12619 }
12620
12622 bool is_root() const
12623 {
12624 return reference_tokens.empty();
12625 }
12626
12627 json_pointer top() const
12628 {
12629 if (is_root())
12630 {
12631 JSON_THROW(out_of_range::create(405, "JSON pointer has no parent"));
12632 }
12633
12634 json_pointer result = *this;
12635 result.reference_tokens = {reference_tokens[0]};
12636 return result;
12637 }
12638
12647 reference get_and_create(reference j) const
12648 {
12649 pointer result = &j;
12650
12651 // in case no reference tokens exist, return a reference to the
12652 // JSON value j which will be overwritten by a primitive value
12653 for (const auto& reference_token : reference_tokens)
12654 {
12655 switch (result->m_type)
12656 {
12657 case value_t::null:
12658 {
12659 if (reference_token == "0")
12660 {
12661 // start a new array if reference token is 0
12662 result = &result->operator[](0);
12663 }
12664 else
12665 {
12666 // start a new object otherwise
12667 result = &result->operator[](reference_token);
12668 }
12669 break;
12670 }
12671
12672 case value_t::object:
12673 {
12674 // create an entry in the object
12675 result = &result->operator[](reference_token);
12676 break;
12677 }
12678
12679 case value_t::array:
12680 {
12681 // create an entry in the array
12682 JSON_TRY
12683 {
12684 result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
12685 }
12686 JSON_CATCH (std::invalid_argument&)
12687 {
12688 JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12689 }
12690 break;
12691 }
12692
12693 /*
12694 The following code is only reached if there exists a
12695 reference token _and_ the current value is primitive. In
12696 this case, we have an error situation, because primitive
12697 values may only occur as single value; that is, with an
12698 empty list of reference tokens.
12699 */
12700 default:
12701 {
12702 JSON_THROW(type_error::create(313, "invalid value to unflatten"));
12703 }
12704 }
12705 }
12706
12707 return *result;
12708 }
12709
12729 reference get_unchecked(pointer ptr) const
12730 {
12731 for (const auto& reference_token : reference_tokens)
12732 {
12733 // convert null values to arrays or objects before continuing
12734 if (ptr->m_type == value_t::null)
12735 {
12736 // check if reference token is a number
12737 const bool nums = std::all_of(reference_token.begin(),
12738 reference_token.end(),
12739 [](const char x)
12740 {
12741 return (x >= '0' and x <= '9');
12742 });
12743
12744 // change value to array for numbers or "-" or to object
12745 // otherwise
12746 if (nums or reference_token == "-")
12747 {
12748 *ptr = value_t::array;
12749 }
12750 else
12751 {
12752 *ptr = value_t::object;
12753 }
12754 }
12755
12756 switch (ptr->m_type)
12757 {
12758 case value_t::object:
12759 {
12760 // use unchecked object access
12761 ptr = &ptr->operator[](reference_token);
12762 break;
12763 }
12764
12765 case value_t::array:
12766 {
12767 // error condition (cf. RFC 6901, Sect. 4)
12768 if (reference_token.size() > 1 and reference_token[0] == '0')
12769 {
12770 JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
12771 }
12772
12773 if (reference_token == "-")
12774 {
12775 // explicitly treat "-" as index beyond the end
12776 ptr = &ptr->operator[](ptr->m_value.array->size());
12777 }
12778 else
12779 {
12780 // convert array index to number; unchecked access
12781 JSON_TRY
12782 {
12783 ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
12784 }
12785 JSON_CATCH (std::invalid_argument&)
12786 {
12787 JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12788 }
12789 }
12790 break;
12791 }
12792
12793 default:
12794 {
12795 JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12796 }
12797 }
12798 }
12799
12800 return *ptr;
12801 }
12802
12809 reference get_checked(pointer ptr) const
12810 {
12811 for (const auto& reference_token : reference_tokens)
12812 {
12813 switch (ptr->m_type)
12814 {
12815 case value_t::object:
12816 {
12817 // note: at performs range check
12818 ptr = &ptr->at(reference_token);
12819 break;
12820 }
12821
12822 case value_t::array:
12823 {
12824 if (reference_token == "-")
12825 {
12826 // "-" always fails the range check
12827 JSON_THROW(out_of_range::create(402, "array index '-' (" +
12828 std::to_string(ptr->m_value.array->size()) +
12829 ") is out of range"));
12830 }
12831
12832 // error condition (cf. RFC 6901, Sect. 4)
12833 if (reference_token.size() > 1 and reference_token[0] == '0')
12834 {
12835 JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
12836 }
12837
12838 // note: at performs range check
12839 JSON_TRY
12840 {
12841 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
12842 }
12843 JSON_CATCH (std::invalid_argument&)
12844 {
12845 JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12846 }
12847 break;
12848 }
12849
12850 default:
12851 {
12852 JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12853 }
12854 }
12855 }
12856
12857 return *ptr;
12858 }
12859
12873 const_reference get_unchecked(const_pointer ptr) const
12874 {
12875 for (const auto& reference_token : reference_tokens)
12876 {
12877 switch (ptr->m_type)
12878 {
12879 case value_t::object:
12880 {
12881 // use unchecked object access
12882 ptr = &ptr->operator[](reference_token);
12883 break;
12884 }
12885
12886 case value_t::array:
12887 {
12888 if (reference_token == "-")
12889 {
12890 // "-" cannot be used for const access
12891 JSON_THROW(out_of_range::create(402, "array index '-' (" +
12892 std::to_string(ptr->m_value.array->size()) +
12893 ") is out of range"));
12894 }
12895
12896 // error condition (cf. RFC 6901, Sect. 4)
12897 if (reference_token.size() > 1 and reference_token[0] == '0')
12898 {
12899 JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
12900 }
12901
12902 // use unchecked array access
12903 JSON_TRY
12904 {
12905 ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
12906 }
12907 JSON_CATCH (std::invalid_argument&)
12908 {
12909 JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12910 }
12911 break;
12912 }
12913
12914 default:
12915 {
12916 JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12917 }
12918 }
12919 }
12920
12921 return *ptr;
12922 }
12923
12930 const_reference get_checked(const_pointer ptr) const
12931 {
12932 for (const auto& reference_token : reference_tokens)
12933 {
12934 switch (ptr->m_type)
12935 {
12936 case value_t::object:
12937 {
12938 // note: at performs range check
12939 ptr = &ptr->at(reference_token);
12940 break;
12941 }
12942
12943 case value_t::array:
12944 {
12945 if (reference_token == "-")
12946 {
12947 // "-" always fails the range check
12948 JSON_THROW(out_of_range::create(402, "array index '-' (" +
12949 std::to_string(ptr->m_value.array->size()) +
12950 ") is out of range"));
12951 }
12952
12953 // error condition (cf. RFC 6901, Sect. 4)
12954 if (reference_token.size() > 1 and reference_token[0] == '0')
12955 {
12956 JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
12957 }
12958
12959 // note: at performs range check
12960 JSON_TRY
12961 {
12962 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
12963 }
12964 JSON_CATCH (std::invalid_argument&)
12965 {
12966 JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12967 }
12968 break;
12969 }
12970
12971 default:
12972 {
12973 JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12974 }
12975 }
12976 }
12977
12978 return *ptr;
12979 }
12980
12990 static std::vector<std::string> split(const std::string& reference_string)
12991 {
12992 std::vector<std::string> result;
12993
12994 // special case: empty reference string -> no reference tokens
12995 if (reference_string.empty())
12996 {
12997 return result;
12998 }
12999
13000 // check if nonempty reference string begins with slash
13001 if (reference_string[0] != '/')
13002 {
13003 JSON_THROW(parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'"));
13004 }
13005
13006 // extract the reference tokens:
13007 // - slash: position of the last read slash (or end of string)
13008 // - start: position after the previous slash
13009 for (
13010 // search for the first slash after the first character
13011 size_t slash = reference_string.find_first_of('/', 1),
13012 // set the beginning of the first reference token
13013 start = 1;
13014 // we can stop if start == string::npos+1 = 0
13015 start != 0;
13016 // set the beginning of the next reference token
13017 // (will eventually be 0 if slash == std::string::npos)
13018 start = slash + 1,
13019 // find next slash
13020 slash = reference_string.find_first_of('/', start))
13021 {
13022 // use the text between the beginning of the reference token
13023 // (start) and the last slash (slash).
13024 auto reference_token = reference_string.substr(start, slash - start);
13025
13026 // check reference tokens are properly escaped
13027 for (size_t pos = reference_token.find_first_of('~');
13028 pos != std::string::npos;
13029 pos = reference_token.find_first_of('~', pos + 1))
13030 {
13031 assert(reference_token[pos] == '~');
13032
13033 // ~ must be followed by 0 or 1
13034 if (pos == reference_token.size() - 1 or
13035 (reference_token[pos + 1] != '0' and
13036 reference_token[pos + 1] != '1'))
13037 {
13038 JSON_THROW(parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
13039 }
13040 }
13041
13042 // finally, store the reference token
13043 unescape(reference_token);
13044 result.push_back(reference_token);
13045 }
13046
13047 return result;
13048 }
13049
13063 static void replace_substring(std::string& s,
13064 const std::string& f,
13065 const std::string& t)
13066 {
13067 assert(not f.empty());
13068
13069 for (
13070 size_t pos = s.find(f); // find first occurrence of f
13071 pos != std::string::npos; // make sure f was found
13072 s.replace(pos, f.size(), t), // replace with t
13073 pos = s.find(f, pos + t.size()) // find next occurrence of f
13074 );
13075 }
13076
13078 static std::string escape(std::string s)
13079 {
13080 // escape "~"" to "~0" and "/" to "~1"
13081 replace_substring(s, "~", "~0");
13082 replace_substring(s, "/", "~1");
13083 return s;
13084 }
13085
13087 static void unescape(std::string& s)
13088 {
13089 // first transform any occurrence of the sequence '~1' to '/'
13090 replace_substring(s, "~1", "/");
13091 // then transform any occurrence of the sequence '~0' to '~'
13092 replace_substring(s, "~0", "~");
13093 }
13094
13102 static void flatten(const std::string& reference_string,
13103 const basic_json& value,
13104 basic_json& result)
13105 {
13106 switch (value.m_type)
13107 {
13108 case value_t::array:
13109 {
13110 if (value.m_value.array->empty())
13111 {
13112 // flatten empty array as null
13113 result[reference_string] = nullptr;
13114 }
13115 else
13116 {
13117 // iterate array and use index as reference string
13118 for (size_t i = 0; i < value.m_value.array->size(); ++i)
13119 {
13120 flatten(reference_string + "/" + std::to_string(i),
13121 value.m_value.array->operator[](i), result);
13122 }
13123 }
13124 break;
13125 }
13126
13127 case value_t::object:
13128 {
13129 if (value.m_value.object->empty())
13130 {
13131 // flatten empty object as null
13132 result[reference_string] = nullptr;
13133 }
13134 else
13135 {
13136 // iterate object and use keys as reference string
13137 for (const auto& element : *value.m_value.object)
13138 {
13139 flatten(reference_string + "/" + escape(element.first),
13140 element.second, result);
13141 }
13142 }
13143 break;
13144 }
13145
13146 default:
13147 {
13148 // add primitive value with its reference string
13149 result[reference_string] = value;
13150 break;
13151 }
13152 }
13153 }
13154
13165 static basic_json unflatten(const basic_json& value)
13166 {
13167 if (not value.is_object())
13168 {
13169 JSON_THROW(type_error::create(314, "only objects can be unflattened"));
13170 }
13171
13172 basic_json result;
13173
13174 // iterate the JSON object values
13175 for (const auto& element : *value.m_value.object)
13176 {
13177 if (not element.second.is_primitive())
13178 {
13179 JSON_THROW(type_error::create(315, "values in object must be primitive"));
13180 }
13181
13182 // assign value to reference pointed to by JSON pointer; Note
13183 // that if the JSON pointer is "" (i.e., points to the whole
13184 // value), function get_and_create returns a reference to
13185 // result itself. An assignment will then create a primitive
13186 // value.
13187 json_pointer(element.first).get_and_create(result) = element.second;
13188 }
13189
13190 return result;
13191 }
13192
13193 friend bool operator==(json_pointer const& lhs,
13194 json_pointer const& rhs) noexcept
13195 {
13196 return lhs.reference_tokens == rhs.reference_tokens;
13197 }
13198
13199 friend bool operator!=(json_pointer const& lhs,
13200 json_pointer const& rhs) noexcept
13201 {
13202 return !(lhs == rhs);
13203 }
13204
13206 std::vector<std::string> reference_tokens {};
13207 };
13208
13210 // JSON Pointer support //
13212
13215
13249 reference operator[](const json_pointer& ptr)
13250 {
13251 return ptr.get_unchecked(this);
13252 }
13253
13277 const_reference operator[](const json_pointer& ptr) const
13278 {
13279 return ptr.get_unchecked(this);
13280 }
13281
13317 reference at(const json_pointer& ptr)
13318 {
13319 return ptr.get_checked(this);
13320 }
13321
13357 const_reference at(const json_pointer& ptr) const
13358 {
13359 return ptr.get_checked(this);
13360 }
13361
13384 basic_json flatten() const
13385 {
13386 basic_json result(value_t::object);
13387 json_pointer::flatten("", *this, result);
13388 return result;
13389 }
13390
13421 basic_json unflatten() const
13422 {
13423 return json_pointer::unflatten(*this);
13424 }
13425
13427
13429 // JSON Patch functions //
13431
13434
13482 basic_json patch(const basic_json& json_patch) const
13483 {
13484 // make a working copy to apply the patch to
13485 basic_json result = *this;
13486
13487 // the valid JSON Patch operations
13488 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
13489
13490 const auto get_op = [](const std::string & op)
13491 {
13492 if (op == "add")
13493 {
13494 return patch_operations::add;
13495 }
13496 if (op == "remove")
13497 {
13498 return patch_operations::remove;
13499 }
13500 if (op == "replace")
13501 {
13502 return patch_operations::replace;
13503 }
13504 if (op == "move")
13505 {
13506 return patch_operations::move;
13507 }
13508 if (op == "copy")
13509 {
13510 return patch_operations::copy;
13511 }
13512 if (op == "test")
13513 {
13514 return patch_operations::test;
13515 }
13516
13517 return patch_operations::invalid;
13518 };
13519
13520 // wrapper for "add" operation; add value at ptr
13521 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
13522 {
13523 // adding to the root of the target document means replacing it
13524 if (ptr.is_root())
13525 {
13526 result = val;
13527 }
13528 else
13529 {
13530 // make sure the top element of the pointer exists
13531 json_pointer top_pointer = ptr.top();
13532 if (top_pointer != ptr)
13533 {
13534 result.at(top_pointer);
13535 }
13536
13537 // get reference to parent of JSON pointer ptr
13538 const auto last_path = ptr.pop_back();
13539 basic_json& parent = result[ptr];
13540
13541 switch (parent.m_type)
13542 {
13543 case value_t::null:
13544 case value_t::object:
13545 {
13546 // use operator[] to add value
13547 parent[last_path] = val;
13548 break;
13549 }
13550
13551 case value_t::array:
13552 {
13553 if (last_path == "-")
13554 {
13555 // special case: append to back
13556 parent.push_back(val);
13557 }
13558 else
13559 {
13560 const auto idx = std::stoi(last_path);
13561 if (static_cast<size_type>(idx) > parent.size())
13562 {
13563 // avoid undefined behavior
13564 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
13565 }
13566 else
13567 {
13568 // default case: insert add offset
13569 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
13570 }
13571 }
13572 break;
13573 }
13574
13575 default:
13576 {
13577 // if there exists a parent it cannot be primitive
13578 assert(false); // LCOV_EXCL_LINE
13579 }
13580 }
13581 }
13582 };
13583
13584 // wrapper for "remove" operation; remove value at ptr
13585 const auto operation_remove = [&result](json_pointer & ptr)
13586 {
13587 // get reference to parent of JSON pointer ptr
13588 const auto last_path = ptr.pop_back();
13589 basic_json& parent = result.at(ptr);
13590
13591 // remove child
13592 if (parent.is_object())
13593 {
13594 // perform range check
13595 auto it = parent.find(last_path);
13596 if (it != parent.end())
13597 {
13598 parent.erase(it);
13599 }
13600 else
13601 {
13602 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
13603 }
13604 }
13605 else if (parent.is_array())
13606 {
13607 // note erase performs range check
13608 parent.erase(static_cast<size_type>(std::stoi(last_path)));
13609 }
13610 };
13611
13612 // type check: top level value must be an array
13613 if (not json_patch.is_array())
13614 {
13615 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
13616 }
13617
13618 // iterate and apply the operations
13619 for (const auto& val : json_patch)
13620 {
13621 // wrapper to get a value for an operation
13622 const auto get_value = [&val](const std::string & op,
13623 const std::string & member,
13624 bool string_type) -> basic_json&
13625 {
13626 // find value
13627 auto it = val.m_value.object->find(member);
13628
13629 // context-sensitive error message
13630 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
13631
13632 // check if desired value is present
13633 if (it == val.m_value.object->end())
13634 {
13635 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
13636 }
13637
13638 // check if result is of type string
13639 if (string_type and not it->second.is_string())
13640 {
13641 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
13642 }
13643
13644 // no error: return value
13645 return it->second;
13646 };
13647
13648 // type check: every element of the array must be an object
13649 if (not val.is_object())
13650 {
13651 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
13652 }
13653
13654 // collect mandatory members
13655 const std::string op = get_value("op", "op", true);
13656 const std::string path = get_value(op, "path", true);
13657 json_pointer ptr(path);
13658
13659 switch (get_op(op))
13660 {
13661 case patch_operations::add:
13662 {
13663 operation_add(ptr, get_value("add", "value", false));
13664 break;
13665 }
13666
13667 case patch_operations::remove:
13668 {
13669 operation_remove(ptr);
13670 break;
13671 }
13672
13673 case patch_operations::replace:
13674 {
13675 // the "path" location must exist - use at()
13676 result.at(ptr) = get_value("replace", "value", false);
13677 break;
13678 }
13679
13680 case patch_operations::move:
13681 {
13682 const std::string from_path = get_value("move", "from", true);
13683 json_pointer from_ptr(from_path);
13684
13685 // the "from" location must exist - use at()
13686 basic_json v = result.at(from_ptr);
13687
13688 // The move operation is functionally identical to a
13689 // "remove" operation on the "from" location, followed
13690 // immediately by an "add" operation at the target
13691 // location with the value that was just removed.
13692 operation_remove(from_ptr);
13693 operation_add(ptr, v);
13694 break;
13695 }
13696
13697 case patch_operations::copy:
13698 {
13699 const std::string from_path = get_value("copy", "from", true);;
13700 const json_pointer from_ptr(from_path);
13701
13702 // the "from" location must exist - use at()
13703 result[ptr] = result.at(from_ptr);
13704 break;
13705 }
13706
13707 case patch_operations::test:
13708 {
13709 bool success = false;
13710 JSON_TRY
13711 {
13712 // check if "value" matches the one at "path"
13713 // the "path" location must exist - use at()
13714 success = (result.at(ptr) == get_value("test", "value", false));
13715 }
13716 JSON_CATCH (out_of_range&)
13717 {
13718 // ignore out of range errors: success remains false
13719 }
13720
13721 // throw an exception if test fails
13722 if (not success)
13723 {
13724 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
13725 }
13726
13727 break;
13728 }
13729
13730 case patch_operations::invalid:
13731 {
13732 // op must be "add", "remove", "replace", "move", "copy", or
13733 // "test"
13734 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
13735 }
13736 }
13737 }
13738
13739 return result;
13740 }
13741
13774 static basic_json diff(const basic_json& source,
13775 const basic_json& target,
13776 const std::string& path = "")
13777 {
13778 // the patch
13779 basic_json result(value_t::array);
13780
13781 // if the values are the same, return empty patch
13782 if (source == target)
13783 {
13784 return result;
13785 }
13786
13787 if (source.type() != target.type())
13788 {
13789 // different types: replace value
13790 result.push_back(
13791 {
13792 {"op", "replace"},
13793 {"path", path},
13794 {"value", target}
13795 });
13796 }
13797 else
13798 {
13799 switch (source.type())
13800 {
13801 case value_t::array:
13802 {
13803 // first pass: traverse common elements
13804 size_t i = 0;
13805 while (i < source.size() and i < target.size())
13806 {
13807 // recursive call to compare array values at index i
13808 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
13809 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
13810 ++i;
13811 }
13812
13813 // i now reached the end of at least one array
13814 // in a second pass, traverse the remaining elements
13815
13816 // remove my remaining elements
13817 const auto end_index = static_cast<difference_type>(result.size());
13818 while (i < source.size())
13819 {
13820 // add operations in reverse order to avoid invalid
13821 // indices
13822 result.insert(result.begin() + end_index, object(
13823 {
13824 {"op", "remove"},
13825 {"path", path + "/" + std::to_string(i)}
13826 }));
13827 ++i;
13828 }
13829
13830 // add other remaining elements
13831 while (i < target.size())
13832 {
13833 result.push_back(
13834 {
13835 {"op", "add"},
13836 {"path", path + "/" + std::to_string(i)},
13837 {"value", target[i]}
13838 });
13839 ++i;
13840 }
13841
13842 break;
13843 }
13844
13845 case value_t::object:
13846 {
13847 // first pass: traverse this object's elements
13848 for (auto it = source.begin(); it != source.end(); ++it)
13849 {
13850 // escape the key name to be used in a JSON patch
13851 const auto key = json_pointer::escape(it.key());
13852
13853 if (target.find(it.key()) != target.end())
13854 {
13855 // recursive call to compare object values at key it
13856 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
13857 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
13858 }
13859 else
13860 {
13861 // found a key that is not in o -> remove it
13862 result.push_back(object(
13863 {
13864 {"op", "remove"},
13865 {"path", path + "/" + key}
13866 }));
13867 }
13868 }
13869
13870 // second pass: traverse other object's elements
13871 for (auto it = target.begin(); it != target.end(); ++it)
13872 {
13873 if (source.find(it.key()) == source.end())
13874 {
13875 // found a key that is not in this -> add it
13876 const auto key = json_pointer::escape(it.key());
13877 result.push_back(
13878 {
13879 {"op", "add"},
13880 {"path", path + "/" + key},
13881 {"value", it.value()}
13882 });
13883 }
13884 }
13885
13886 break;
13887 }
13888
13889 default:
13890 {
13891 // both primitive type: replace value
13892 result.push_back(
13893 {
13894 {"op", "replace"},
13895 {"path", path},
13896 {"value", target}
13897 });
13898 break;
13899 }
13900 }
13901 }
13902
13903 return result;
13904 }
13905
13907 };
13908
13910 // presets //
13912
13921 using json = basic_json<>;
13922 } // namespace nlohmann
13923
13924
13926 // nonmember support //
13928
13929 // specialization of std::swap, and std::hash
13930 namespace std
13931 {
13937 template<>
13938 inline void swap(nlohmann::json& j1,
13939 nlohmann::json& j2) noexcept(
13940 is_nothrow_move_constructible<nlohmann::json>::value and
13941 is_nothrow_move_assignable<nlohmann::json>::value
13942 )
13943 {
13944 j1.swap(j2);
13945 }
13946
13948 template<>
13949 struct hash<nlohmann::json>
13950 {
13956 std::size_t operator()(const nlohmann::json& j) const
13957 {
13958 // a naive hashing via the string representation
13959 const auto& h = hash<nlohmann::json::string_t>();
13960 return h(j.dump());
13961 }
13962 };
13963
13965 template <>
13966 struct less<::nlohmann::detail::value_t>
13967 {
13972 bool operator()(nlohmann::detail::value_t lhs,
13973 nlohmann::detail::value_t rhs) const noexcept
13974 {
13975 return nlohmann::detail::operator<(lhs, rhs);
13976 }
13977 };
13978
13979 } // namespace std
13980
13994 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
13995 {
13996 return nlohmann::json::parse(s, s + n);
13997 }
13998
14012 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
14013 {
14014 return nlohmann::json::json_pointer(std::string(s, n));
14015 }
14016
14017 // restore GCC/clang diagnostic settings
14018 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
14019 #pragma GCC diagnostic pop
14020 #endif
14021 #if defined(__clang__)
14022 #pragma GCC diagnostic pop
14023 #endif
14024
14025 // clean up
14026 #undef JSON_CATCH
14027 #undef JSON_THROW
14028 #undef JSON_TRY
14029 #undef JSON_DEPRECATED
14030
14031 #endif
nlohmann::basic_json::pointer
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:1357
nlohmann::basic_json::json_serializer
JSONSerializer< T, SFINAE > json_serializer
Definition: json.hpp:1304
nlohmann::basic_json::number_float_t
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:1889
nlohmann::basic_json::boolean_t
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:1678
nlohmann::basic_json::json_reverse_iterator::base_iterator
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:10322
nlohmann::basic_json::begin
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4941
nlohmann::basic_json::end
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:5012
nlohmann::basic_json::type
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2923
nlohmann::basic_json::basic_json
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:2208
nlohmann::basic_json::object
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:2476
nlohmann::basic_json::basic_json
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:2552
nlohmann::basic_json::get_ref
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3679
nlohmann::basic_json
a class to store JSON values
Definition: json.hpp:1288
nlohmann::basic_json::iter_impl::pointer
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:9721
nlohmann::basic_json::get_allocator
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:1376
nlohmann::adl_serializer
default JSONSerializer template argument
Definition: json.hpp:1160
nlohmann::basic_json::json_reverse_iterator::operator-
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:10378
nlohmann::basic_json::find
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4852
nlohmann::basic_json::is_structured
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2980
nlohmann::basic_json::object_t
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
Definition: json.hpp:1553
nlohmann::basic_json::parse
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:7289
nlohmann::basic_json::iter_impl::reference
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:9725
nlohmann::basic_json::~basic_json
~basic_json()
destructor
Definition: json.hpp:2816
nlohmann::basic_json::operator=
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:2783
std
STL namespace.
nlohmann::basic_json::other_error
detail::other_error other_error
exception indicating other errors
Definition: json.hpp:1326
nlohmann::basic_json::iter_impl::iterator_category
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:9727
nlohmann::basic_json::basic_json
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:2352
nlohmann::basic_json::at
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3780
nlohmann::basic_json::is_number
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:3054
nlohmann::basic_json::const_reference
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:1346
nlohmann::basic_json::is_primitive
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2953
nlohmann::basic_json::front
reference front()
access the first element
Definition: json.hpp:4461
nlohmann::basic_json::size_type
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:1351
nlohmann::basic_json::get_ref
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3692
nlohmann::basic_json::iterator_wrapper
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:5206
nlohmann::adl_serializer::from_json
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:1172
nlohmann::basic_json::number_integer_t
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:1750
nlohmann::basic_json::is_array
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:3183
nlohmann::basic_json::number_unsigned_t
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:1821
nlohmann::basic_json::size
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:5334
nlohmann::basic_json::lexer::strtonum
parse string into a built-in arithmetic type as if the current locale is POSIX.
Definition: json.hpp:11978
nlohmann::basic_json::out_of_range
detail::out_of_range out_of_range
exception indicating access out of the defined range
Definition: json.hpp:1324
nlohmann::basic_json::meta
static basic_json meta()
returns version information on the library
Definition: json.hpp:1404
nlohmann::basic_json::basic_json
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:2500
nlohmann::anonymous_namespace{json.hpp}::from_json
constexpr const auto & from_json
Definition: json.hpp:1148
nlohmann::basic_json::is_boolean
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:3024
nlohmann::basic_json::type_error
detail::type_error type_error
exception indicating executing a member function with a wrong type
Definition: json.hpp:1322
nlohmann::basic_json::get_ptr
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:3602
nlohmann
namespace for Niels Lohmann
Definition: json.hpp:106
nlohmann::basic_json::is_number_integer
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:3083
nlohmann::basic_json::basic_json
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:2184
nlohmann::basic_json::is_object
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:3161
nlohmann::basic_json::is_number_float
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:3139
nlohmann::basic_json::json_pointer
JSON Pointer.
Definition: json.hpp:12549
nlohmann::basic_json::rbegin
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:5082
nlohmann::basic_json::parse_error
detail::parse_error parse_error
exception indicating a parse error
Definition: json.hpp:1318
nlohmann::adl_serializer::to_json
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:1188
nlohmann::basic_json::parser_callback_t
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:2148
nlohmann::basic_json::is_string
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:3205
nlohmann::anonymous_namespace{json.hpp}::to_json
constexpr const auto & to_json
Definition: json.hpp:1147
nlohmann::basic_json::array_t
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:1599
nlohmann::basic_json::dump
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2888
nlohmann::basic_json::difference_type
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:1349
nlohmann::basic_json::allocator_type
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:1354
nlohmann::basic_json::basic_json
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:2274
nlohmann::basic_json::is_null
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:3002
nlohmann::basic_json::const_pointer
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:1359
nlohmann::basic_json::string_t
StringType string_t
a type for a string
Definition: json.hpp:1652
nlohmann::basic_json::array
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:2435
nlohmann::basic_json::basic_json
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2746
nlohmann::basic_json::is_number_unsigned
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:3111
nlohmann::basic_json::iter_impl::difference_type
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:9717
nlohmann::basic_json::get_ptr
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3630
nlohmann::basic_json::json_reverse_iterator::reference
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:10324
nlohmann::basic_json::json_reverse_iterator
a template for a reverse iterator class
Definition: json.hpp:1301
nlohmann::basic_json::push_back
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:5529
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5811
nlohmann::basic_json::value_type
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:1341
nlohmann::basic_json::exception
detail::exception exception
general exception of the basic_json class
Definition: json.hpp:1316
nlohmann::basic_json::swap
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:6055
nlohmann::basic_json::basic_json
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:2669
nlohmann::basic_json::invalid_iterator
detail::invalid_iterator invalid_iterator
exception indicating errors with iterators
Definition: json.hpp:1320
nlohmann::basic_json::erase
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:4572
nlohmann::basic_json::iter_impl
a template for a random access iterator for the basic_json class
Definition: json.hpp:1300
nlohmann::basic_json::is_discarded
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:3232
nlohmann::basic_json::parse_event_t
parse_event_t
JSON callback events.
Definition: json.hpp:2078
nlohmann::basic_json::rend
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:5119