CellModules
json.hpp
Go to the documentation of this file.
1/*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 3.6.1
5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8SPDX-License-Identifier: MIT
9Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28*/
29
30#ifndef INCLUDE_NLOHMANN_JSON_HPP_
31#define INCLUDE_NLOHMANN_JSON_HPP_
32
33#define NLOHMANN_JSON_VERSION_MAJOR 3
34#define NLOHMANN_JSON_VERSION_MINOR 6
35#define NLOHMANN_JSON_VERSION_PATCH 1
36
37#include <algorithm> // all_of, find, for_each
38#include <cassert> // assert
39#include <ciso646> // and, not, or
40#include <cstddef> // nullptr_t, ptrdiff_t, size_t
41#include <functional> // hash, less
42#include <initializer_list> // initializer_list
43#include <iosfwd> // istream, ostream
44#include <iterator> // random_access_iterator_tag
45#include <memory> // unique_ptr
46#include <numeric> // accumulate
47#include <string> // string, stoi, to_string
48#include <utility> // declval, forward, move, pair, swap
49#include <vector> // vector
50
51// #include <nlohmann/adl_serializer.hpp>
52
53
54#include <utility>
55
56// #include <nlohmann/detail/conversions/from_json.hpp>
57
58
59#include <algorithm> // transform
60#include <array> // array
61#include <ciso646> // and, not
62#include <forward_list> // forward_list
63#include <iterator> // inserter, front_inserter, end
64#include <map> // map
65#include <string> // string
66#include <tuple> // tuple, make_tuple
67#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
68#include <unordered_map> // unordered_map
69#include <utility> // pair, declval
70#include <valarray> // valarray
71
72// #include <nlohmann/detail/exceptions.hpp>
73
74
75#include <exception> // exception
76#include <stdexcept> // runtime_error
77#include <string> // to_string
78
79// #include <nlohmann/detail/input/position_t.hpp>
80
81
82#include <cstddef> // size_t
83
84namespace nlohmann
85{
86 namespace detail
87 {
90 {
92 std::size_t chars_read_total = 0;
94 std::size_t chars_read_current_line = 0;
96 std::size_t lines_read = 0;
97
99 constexpr operator size_t() const
100 {
101 return chars_read_total;
102 }
103 };
104
105 } // namespace detail
106} // namespace nlohmann
107
108
109namespace nlohmann
110{
111 namespace detail
112 {
114// exceptions //
116
145 class exception : public std::exception
146 {
147 public:
149 const char* what() const noexcept override
150 {
151 return m.what();
152 }
153
155 const int id;
156
157 protected:
158 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
159
160 static std::string name(const std::string& ename, int id_)
161 {
162 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
163 }
164
165 private:
167 std::runtime_error m;
168 };
169
214 class parse_error : public exception
215 {
216 public:
226 static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
227 {
228 std::string w = exception::name("parse_error", id_) + "parse error" +
229 position_string(pos) + ": " + what_arg;
230 return parse_error(id_, pos.chars_read_total, w.c_str());
231 }
232
233 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
234 {
235 std::string w = exception::name("parse_error", id_) + "parse error" +
236 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
237 ": " + what_arg;
238 return parse_error(id_, byte_, w.c_str());
239 }
240
250 const std::size_t byte;
251
252 private:
253 parse_error(int id_, std::size_t byte_, const char* what_arg)
254 : exception(id_, what_arg), byte(byte_) {}
255
256 static std::string position_string(const position_t& pos)
257 {
258 return " at line " + std::to_string(pos.lines_read + 1) +
259 ", column " + std::to_string(pos.chars_read_current_line);
260 }
261 };
262
301 {
302 public:
303 static invalid_iterator create(int id_, const std::string& what_arg)
304 {
305 std::string w = exception::name("invalid_iterator", id_) + what_arg;
306 return invalid_iterator(id_, w.c_str());
307 }
308
309 private:
310 invalid_iterator(int id_, const char* what_arg)
311 : exception(id_, what_arg) {}
312 };
313
353 class type_error : public exception
354 {
355 public:
356 static type_error create(int id_, const std::string& what_arg)
357 {
358 std::string w = exception::name("type_error", id_) + what_arg;
359 return type_error(id_, w.c_str());
360 }
361
362 private:
363 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
364 };
365
399 class out_of_range : public exception
400 {
401 public:
402 static out_of_range create(int id_, const std::string& what_arg)
403 {
404 std::string w = exception::name("out_of_range", id_) + what_arg;
405 return out_of_range(id_, w.c_str());
406 }
407
408 private:
409 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
410 };
411
436 class other_error : public exception
437 {
438 public:
439 static other_error create(int id_, const std::string& what_arg)
440 {
441 std::string w = exception::name("other_error", id_) + what_arg;
442 return other_error(id_, w.c_str());
443 }
444
445 private:
446 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
447 };
448 } // namespace detail
449} // namespace nlohmann
450
451// #include <nlohmann/detail/macro_scope.hpp>
452
453
454#include <utility> // pair
455
456// This file contains all internal macro definitions
457// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
458
459// exclude unsupported compilers
460#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
461#if defined(__clang__)
462#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
463 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
464 #endif
465#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
466#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
467#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
468#endif
469#endif
470#endif
471
472// disable float-equal warnings on GCC/clang
473#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
474#pragma GCC diagnostic push
475#pragma GCC diagnostic ignored "-Wfloat-equal"
476#endif
477
478// disable documentation warnings on clang
479#if defined(__clang__)
480#pragma GCC diagnostic push
481 #pragma GCC diagnostic ignored "-Wdocumentation"
482#endif
483
484// allow for portable deprecation warnings
485#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
486#define JSON_DEPRECATED __attribute__((deprecated))
487#elif defined(_MSC_VER)
488#define JSON_DEPRECATED __declspec(deprecated)
489#else
490 #define JSON_DEPRECATED
491#endif
492
493// allow for portable nodiscard warnings
494#if defined(__has_cpp_attribute)
495#if __has_cpp_attribute(nodiscard)
496 #define JSON_NODISCARD [[nodiscard]]
497 #elif __has_cpp_attribute(gnu::warn_unused_result)
498 #define JSON_NODISCARD [[gnu::warn_unused_result]]
499 #else
500 #define JSON_NODISCARD
501 #endif
502#else
503#define JSON_NODISCARD
504#endif
505
506// allow to disable exceptions
507#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
508#define JSON_THROW(exception) throw exception
509#define JSON_TRY try
510#define JSON_CATCH(exception) catch(exception)
511#define JSON_INTERNAL_CATCH(exception) catch(exception)
512#else
513#include <cstdlib>
514 #define JSON_THROW(exception) std::abort()
515 #define JSON_TRY if(true)
516 #define JSON_CATCH(exception) if(false)
517 #define JSON_INTERNAL_CATCH(exception) if(false)
518#endif
519
520// override exception macros
521#if defined(JSON_THROW_USER)
522#undef JSON_THROW
523 #define JSON_THROW JSON_THROW_USER
524#endif
525#if defined(JSON_TRY_USER)
526#undef JSON_TRY
527 #define JSON_TRY JSON_TRY_USER
528#endif
529#if defined(JSON_CATCH_USER)
530#undef JSON_CATCH
531 #define JSON_CATCH JSON_CATCH_USER
532 #undef JSON_INTERNAL_CATCH
533 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
534#endif
535#if defined(JSON_INTERNAL_CATCH_USER)
536#undef JSON_INTERNAL_CATCH
537 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
538#endif
539
540// manual branch prediction
541#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
542#define JSON_LIKELY(x) __builtin_expect(x, 1)
543#define JSON_UNLIKELY(x) __builtin_expect(x, 0)
544#else
545#define JSON_LIKELY(x) x
546 #define JSON_UNLIKELY(x) x
547#endif
548
549// C++ language standard detection
550#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
551#define JSON_HAS_CPP_17
552#define JSON_HAS_CPP_14
553#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
554#define JSON_HAS_CPP_14
555#endif
556
562#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
563 template<typename BasicJsonType> \
564 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
565 { \
566 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
567 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
568 auto it = std::find_if(std::begin(m), std::end(m), \
569 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
570 { \
571 return ej_pair.first == e; \
572 }); \
573 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
574 } \
575 template<typename BasicJsonType> \
576 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
577 { \
578 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
579 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
580 auto it = std::find_if(std::begin(m), std::end(m), \
581 [j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
582 { \
583 return ej_pair.second == j; \
584 }); \
585 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
586 }
587
588// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
589// may be removed in the future once the class is split.
590
591#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
592 template<template<typename, typename, typename...> class ObjectType, \
593 template<typename, typename...> class ArrayType, \
594 class StringType, class BooleanType, class NumberIntegerType, \
595 class NumberUnsignedType, class NumberFloatType, \
596 template<typename> class AllocatorType, \
597 template<typename, typename = void> class JSONSerializer>
598
599#define NLOHMANN_BASIC_JSON_TPL \
600 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
601 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
602 AllocatorType, JSONSerializer>
603
604// #include <nlohmann/detail/meta/cpp_future.hpp>
605
606
607#include <ciso646> // not
608#include <cstddef> // size_t
609#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
610
611namespace nlohmann
612{
613 namespace detail
614 {
615// alias templates to reduce boilerplate
616 template<bool B, typename T = void>
617 using enable_if_t = typename std::enable_if<B, T>::type;
618
619 template<typename T>
620 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
621
622// implementation of C++14 index_sequence and affiliates
623// source: https://stackoverflow.com/a/32223343
624 template<std::size_t... Ints>
626 {
628 using value_type = std::size_t;
629 static constexpr std::size_t size() noexcept
630 {
631 return sizeof...(Ints);
632 }
633 };
634
635 template<class Sequence1, class Sequence2>
637
638 template<std::size_t... I1, std::size_t... I2>
640 : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
641
642 template<std::size_t N>
644 : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
645 typename make_index_sequence < N - N / 2 >::type > {};
646
647 template<> struct make_index_sequence<0> : index_sequence<> {};
648 template<> struct make_index_sequence<1> : index_sequence<0> {};
649
650 template<typename... Ts>
652
653// dispatch utility (taken from ranges-v3)
654 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
655 template<> struct priority_tag<0> {};
656
657// taken from ranges-v3
658 template<typename T>
660 {
661 static constexpr T value{};
662 };
663
664 template<typename T>
665 constexpr T static_const<T>::value;
666 } // namespace detail
667} // namespace nlohmann
668
669// #include <nlohmann/detail/meta/type_traits.hpp>
670
671
672#include <ciso646> // not
673#include <limits> // numeric_limits
674#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
675#include <utility> // declval
676
677// #include <nlohmann/detail/iterators/iterator_traits.hpp>
678
679
680#include <iterator> // random_access_iterator_tag
681
682// #include <nlohmann/detail/meta/void_t.hpp>
683
684
685namespace nlohmann
686{
687 namespace detail
688 {
689 template <typename ...Ts> struct make_void
690 {
691 using type = void;
692 };
693 template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
694 } // namespace detail
695} // namespace nlohmann
696
697// #include <nlohmann/detail/meta/cpp_future.hpp>
698
699
700namespace nlohmann
701{
702 namespace detail
703 {
704 template <typename It, typename = void>
705 struct iterator_types {};
706
707 template <typename It>
709 It,
710 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
711 typename It::reference, typename It::iterator_category >>
712 {
713 using difference_type = typename It::difference_type;
714 using value_type = typename It::value_type;
715 using pointer = typename It::pointer;
716 using reference = typename It::reference;
717 using iterator_category = typename It::iterator_category;
718 };
719
720// This is required as some compilers implement std::iterator_traits in a way that
721// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
722 template <typename T, typename = void>
724 {
725 };
726
727 template <typename T>
728 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
729 : iterator_types<T>
730 {
731 };
732
733 template <typename T>
735 {
736 using iterator_category = std::random_access_iterator_tag;
737 using value_type = T;
738 using difference_type = ptrdiff_t;
739 using pointer = T*;
740 using reference = T&;
741 };
742 } // namespace detail
743} // namespace nlohmann
744
745// #include <nlohmann/detail/macro_scope.hpp>
746
747// #include <nlohmann/detail/meta/cpp_future.hpp>
748
749// #include <nlohmann/detail/meta/detected.hpp>
750
751
752#include <type_traits>
753
754// #include <nlohmann/detail/meta/void_t.hpp>
755
756
757// http://en.cppreference.com/w/cpp/experimental/is_detected
758namespace nlohmann
759{
760 namespace detail
761 {
762 struct nonesuch
763 {
764 nonesuch() = delete;
765 ~nonesuch() = delete;
766 nonesuch(nonesuch const&) = delete;
767 nonesuch(nonesuch const&&) = delete;
768 void operator=(nonesuch const&) = delete;
769 void operator=(nonesuch&&) = delete;
770 };
771
772 template <class Default,
773 class AlwaysVoid,
774 template <class...> class Op,
775 class... Args>
776 struct detector
777 {
778 using value_t = std::false_type;
779 using type = Default;
780 };
781
782 template <class Default, template <class...> class Op, class... Args>
783 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
784 {
785 using value_t = std::true_type;
786 using type = Op<Args...>;
787 };
788
789 template <template <class...> class Op, class... Args>
790 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
791
792 template <template <class...> class Op, class... Args>
793 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
794
795 template <class Default, template <class...> class Op, class... Args>
796 using detected_or = detector<Default, void, Op, Args...>;
797
798 template <class Default, template <class...> class Op, class... Args>
799 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
800
801 template <class Expected, template <class...> class Op, class... Args>
802 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
803
804 template <class To, template <class...> class Op, class... Args>
806 std::is_convertible<detected_t<Op, Args...>, To>;
807 } // namespace detail
808} // namespace nlohmann
809
810// #include <nlohmann/json_fwd.hpp>
811#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
812#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
813
814#include <cstdint> // int64_t, uint64_t
815#include <map> // map
816#include <memory> // allocator
817#include <string> // string
818#include <vector> // vector
819
825namespace nlohmann
826{
834 template<typename T = void, typename SFINAE = void>
835 struct adl_serializer;
836
837 template<template<typename U, typename V, typename... Args> class ObjectType =
838 std::map,
839 template<typename U, typename... Args> class ArrayType = std::vector,
840 class StringType = std::string, class BooleanType = bool,
841 class NumberIntegerType = std::int64_t,
842 class NumberUnsignedType = std::uint64_t,
843 class NumberFloatType = double,
844 template<typename U> class AllocatorType = std::allocator,
845 template<typename T, typename SFINAE = void> class JSONSerializer =
846 adl_serializer>
847 class basic_json;
848
860 template<typename BasicJsonType>
861 class json_pointer;
862
872} // namespace nlohmann
873
874#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
875
876
877namespace nlohmann
878{
887 namespace detail
888 {
890// helpers //
892
893// Note to maintainers:
894//
895// Every trait in this file expects a non CV-qualified type.
896// The only exceptions are in the 'aliases for detected' section
897// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
898//
899// In this case, T has to be properly CV-qualified to constraint the function arguments
900// (e.g. to_json(BasicJsonType&, const T&))
901
902 template<typename> struct is_basic_json : std::false_type {};
903
905 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
906
908// aliases for detected //
910
911 template <typename T>
912 using mapped_type_t = typename T::mapped_type;
913
914 template <typename T>
915 using key_type_t = typename T::key_type;
916
917 template <typename T>
918 using value_type_t = typename T::value_type;
919
920 template <typename T>
921 using difference_type_t = typename T::difference_type;
922
923 template <typename T>
924 using pointer_t = typename T::pointer;
925
926 template <typename T>
927 using reference_t = typename T::reference;
928
929 template <typename T>
930 using iterator_category_t = typename T::iterator_category;
931
932 template <typename T>
933 using iterator_t = typename T::iterator;
934
935 template <typename T, typename... Args>
936 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
937
938 template <typename T, typename... Args>
939 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
940
941 template <typename T, typename U>
942 using get_template_function = decltype(std::declval<T>().template get<U>());
943
944// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
945 template <typename BasicJsonType, typename T, typename = void>
946 struct has_from_json : std::false_type {};
947
948 template <typename BasicJsonType, typename T>
949 struct has_from_json<BasicJsonType, T,
950 enable_if_t<not is_basic_json<T>::value>>
951 {
952 using serializer = typename BasicJsonType::template json_serializer<T, void>;
953
954 static constexpr bool value =
956 const BasicJsonType&, T&>::value;
957 };
958
959// This trait checks if JSONSerializer<T>::from_json(json const&) exists
960// this overload is used for non-default-constructible user-defined-types
961 template <typename BasicJsonType, typename T, typename = void>
962 struct has_non_default_from_json : std::false_type {};
963
964 template<typename BasicJsonType, typename T>
965 struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
966 {
967 using serializer = typename BasicJsonType::template json_serializer<T, void>;
968
969 static constexpr bool value =
971 const BasicJsonType&>::value;
972 };
973
974// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
975// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
976 template <typename BasicJsonType, typename T, typename = void>
977 struct has_to_json : std::false_type {};
978
979 template <typename BasicJsonType, typename T>
980 struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
981 {
982 using serializer = typename BasicJsonType::template json_serializer<T, void>;
983
984 static constexpr bool value =
985 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
986 T>::value;
987 };
988
989
991// is_ functions //
993
994 template <typename T, typename = void>
995 struct is_iterator_traits : std::false_type {};
996
997 template <typename T>
999 {
1000 private:
1002
1003 public:
1004 static constexpr auto value =
1010 };
1011
1012// source: https://stackoverflow.com/a/37193089/4116453
1013
1014 template <typename T, typename = void>
1015 struct is_complete_type : std::false_type {};
1016
1017 template <typename T>
1018 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
1019
1020 template <typename BasicJsonType, typename CompatibleObjectType,
1021 typename = void>
1022 struct is_compatible_object_type_impl : std::false_type {};
1023
1024 template <typename BasicJsonType, typename CompatibleObjectType>
1026 BasicJsonType, CompatibleObjectType,
1027 enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
1028 is_detected<key_type_t, CompatibleObjectType>::value >>
1029 {
1030
1031 using object_t = typename BasicJsonType::object_t;
1032
1033 // macOS's is_constructible does not play well with nonesuch...
1034 static constexpr bool value =
1035 std::is_constructible<typename object_t::key_type,
1036 typename CompatibleObjectType::key_type>::value and
1037 std::is_constructible<typename object_t::mapped_type,
1038 typename CompatibleObjectType::mapped_type>::value;
1039 };
1040
1041 template <typename BasicJsonType, typename CompatibleObjectType>
1043 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
1044
1045 template <typename BasicJsonType, typename ConstructibleObjectType,
1046 typename = void>
1047 struct is_constructible_object_type_impl : std::false_type {};
1048
1049 template <typename BasicJsonType, typename ConstructibleObjectType>
1051 BasicJsonType, ConstructibleObjectType,
1052 enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
1053 is_detected<key_type_t, ConstructibleObjectType>::value >>
1054 {
1055 using object_t = typename BasicJsonType::object_t;
1056
1057 static constexpr bool value =
1058 (std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and
1059 std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or
1062 };
1063
1064 template <typename BasicJsonType, typename ConstructibleObjectType>
1066 : is_constructible_object_type_impl<BasicJsonType,
1067 ConstructibleObjectType> {};
1068
1069 template <typename BasicJsonType, typename CompatibleStringType,
1070 typename = void>
1071 struct is_compatible_string_type_impl : std::false_type {};
1072
1073 template <typename BasicJsonType, typename CompatibleStringType>
1075 BasicJsonType, CompatibleStringType,
1076 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
1077 value_type_t, CompatibleStringType>::value >>
1078 {
1079 static constexpr auto value =
1080 std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
1081 };
1082
1083 template <typename BasicJsonType, typename ConstructibleStringType>
1085 : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
1086
1087 template <typename BasicJsonType, typename ConstructibleStringType,
1088 typename = void>
1089 struct is_constructible_string_type_impl : std::false_type {};
1090
1091 template <typename BasicJsonType, typename ConstructibleStringType>
1093 BasicJsonType, ConstructibleStringType,
1094 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
1095 value_type_t, ConstructibleStringType>::value >>
1096 {
1097 static constexpr auto value =
1098 std::is_constructible<ConstructibleStringType,
1099 typename BasicJsonType::string_t>::value;
1100 };
1101
1102 template <typename BasicJsonType, typename ConstructibleStringType>
1104 : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
1105
1106 template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
1107 struct is_compatible_array_type_impl : std::false_type {};
1108
1109 template <typename BasicJsonType, typename CompatibleArrayType>
1111 BasicJsonType, CompatibleArrayType,
1112 enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
1113 is_detected<iterator_t, CompatibleArrayType>::value and
1114 // This is needed because json_reverse_iterator has a ::iterator type...
1115 // Therefore it is detected as a CompatibleArrayType.
1116 // The real fix would be to have an Iterable concept.
1118 iterator_traits<CompatibleArrayType>>::value >>
1119 {
1120 static constexpr bool value =
1121 std::is_constructible<BasicJsonType,
1122 typename CompatibleArrayType::value_type>::value;
1123 };
1124
1125 template <typename BasicJsonType, typename CompatibleArrayType>
1127 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
1128
1129 template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
1130 struct is_constructible_array_type_impl : std::false_type {};
1131
1132 template <typename BasicJsonType, typename ConstructibleArrayType>
1134 BasicJsonType, ConstructibleArrayType,
1135 enable_if_t<std::is_same<ConstructibleArrayType,
1136 typename BasicJsonType::value_type>::value >>
1137 : std::true_type {};
1138
1139 template <typename BasicJsonType, typename ConstructibleArrayType>
1141 BasicJsonType, ConstructibleArrayType,
1142 enable_if_t<not std::is_same<ConstructibleArrayType,
1143 typename BasicJsonType::value_type>::value and
1144 is_detected<value_type_t, ConstructibleArrayType>::value and
1145 is_detected<iterator_t, ConstructibleArrayType>::value and
1147 detected_t<value_type_t, ConstructibleArrayType>>::value >>
1148 {
1149 static constexpr bool value =
1150 // This is needed because json_reverse_iterator has a ::iterator type,
1151 // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
1152 // Therefore it is detected as a ConstructibleArrayType.
1153 // The real fix would be to have an Iterable concept.
1154 not is_iterator_traits <
1156
1157 (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
1158 has_from_json<BasicJsonType,
1159 typename ConstructibleArrayType::value_type>::value or
1161 BasicJsonType, typename ConstructibleArrayType::value_type >::value);
1162 };
1163
1164 template <typename BasicJsonType, typename ConstructibleArrayType>
1166 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
1167
1168 template <typename RealIntegerType, typename CompatibleNumberIntegerType,
1169 typename = void>
1170 struct is_compatible_integer_type_impl : std::false_type {};
1171
1172 template <typename RealIntegerType, typename CompatibleNumberIntegerType>
1174 RealIntegerType, CompatibleNumberIntegerType,
1175 enable_if_t<std::is_integral<RealIntegerType>::value and
1176 std::is_integral<CompatibleNumberIntegerType>::value and
1177 not std::is_same<bool, CompatibleNumberIntegerType>::value >>
1178 {
1179 // is there an assert somewhere on overflows?
1180 using RealLimits = std::numeric_limits<RealIntegerType>;
1181 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
1182
1183 static constexpr auto value =
1184 std::is_constructible<RealIntegerType,
1185 CompatibleNumberIntegerType>::value and
1186 CompatibleLimits::is_integer and
1187 RealLimits::is_signed == CompatibleLimits::is_signed;
1188 };
1189
1190 template <typename RealIntegerType, typename CompatibleNumberIntegerType>
1192 : is_compatible_integer_type_impl<RealIntegerType,
1193 CompatibleNumberIntegerType> {};
1194
1195 template <typename BasicJsonType, typename CompatibleType, typename = void>
1196 struct is_compatible_type_impl: std::false_type {};
1197
1198 template <typename BasicJsonType, typename CompatibleType>
1200 BasicJsonType, CompatibleType,
1201 enable_if_t<is_complete_type<CompatibleType>::value >>
1202 {
1203 static constexpr bool value =
1205 };
1206
1207 template <typename BasicJsonType, typename CompatibleType>
1209 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
1210 } // namespace detail
1211} // namespace nlohmann
1212
1213// #include <nlohmann/detail/value_t.hpp>
1214
1215
1216#include <array> // array
1217#include <ciso646> // and
1218#include <cstddef> // size_t
1219#include <cstdint> // uint8_t
1220#include <string> // string
1221
1222namespace nlohmann
1223{
1224 namespace detail
1225 {
1227// JSON type enumeration //
1229
1254 enum class value_t : std::uint8_t
1255 {
1256 null,
1257 object,
1258 array,
1259 string,
1260 boolean,
1263 number_float,
1264 discarded
1265 };
1266
1277 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
1278 {
1279 static constexpr std::array<std::uint8_t, 8> order = {{
1280 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
1281 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
1282 }
1283 };
1284
1285 const auto l_index = static_cast<std::size_t>(lhs);
1286 const auto r_index = static_cast<std::size_t>(rhs);
1287 return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
1288 }
1289 } // namespace detail
1290} // namespace nlohmann
1291
1292
1293namespace nlohmann
1294{
1295 namespace detail
1296 {
1297 template<typename BasicJsonType>
1298 void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1299 {
1300 if (JSON_UNLIKELY(not j.is_null()))
1301 {
1302 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1303 }
1304 n = nullptr;
1305 }
1306
1307// overloads for basic_json template parameters
1308 template<typename BasicJsonType, typename ArithmeticType,
1309 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1310 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1311 int> = 0>
1312 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
1313 {
1314 switch (static_cast<value_t>(j))
1315 {
1317 {
1318 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1319 break;
1320 }
1322 {
1323 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1324 break;
1325 }
1327 {
1328 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1329 break;
1330 }
1331
1332 default:
1333 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1334 }
1335 }
1336
1337 template<typename BasicJsonType>
1338 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
1339 {
1340 if (JSON_UNLIKELY(not j.is_boolean()))
1341 {
1342 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
1343 }
1344 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
1345 }
1346
1347 template<typename BasicJsonType>
1348 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
1349 {
1350 if (JSON_UNLIKELY(not j.is_string()))
1351 {
1352 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1353 }
1354 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1355 }
1356
1357 template <
1358 typename BasicJsonType, typename ConstructibleStringType,
1359 enable_if_t <
1360 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
1361 not std::is_same<typename BasicJsonType::string_t,
1362 ConstructibleStringType>::value,
1363 int > = 0 >
1364 void from_json(const BasicJsonType& j, ConstructibleStringType& s)
1365 {
1366 if (JSON_UNLIKELY(not j.is_string()))
1367 {
1368 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1369 }
1370
1371 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1372 }
1373
1374 template<typename BasicJsonType>
1375 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
1376 {
1377 get_arithmetic_value(j, val);
1378 }
1379
1380 template<typename BasicJsonType>
1381 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1382 {
1383 get_arithmetic_value(j, val);
1384 }
1385
1386 template<typename BasicJsonType>
1387 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1388 {
1389 get_arithmetic_value(j, val);
1390 }
1391
1392 template<typename BasicJsonType, typename EnumType,
1393 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1394 void from_json(const BasicJsonType& j, EnumType& e)
1395 {
1396 typename std::underlying_type<EnumType>::type val;
1397 get_arithmetic_value(j, val);
1398 e = static_cast<EnumType>(val);
1399 }
1400
1401// forward_list doesn't have an insert method
1402 template<typename BasicJsonType, typename T, typename Allocator,
1403 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1404 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1405 {
1406 if (JSON_UNLIKELY(not j.is_array()))
1407 {
1408 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1409 }
1410 std::transform(j.rbegin(), j.rend(),
1411 std::front_inserter(l), [](const BasicJsonType & i)
1412 {
1413 return i.template get<T>();
1414 });
1415 }
1416
1417// valarray doesn't have an insert method
1418 template<typename BasicJsonType, typename T,
1419 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1420 void from_json(const BasicJsonType& j, std::valarray<T>& l)
1421 {
1422 if (JSON_UNLIKELY(not j.is_array()))
1423 {
1424 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1425 }
1426 l.resize(j.size());
1427 std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1428 }
1429
1430 template<typename BasicJsonType>
1431 void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1432 {
1433 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1434 }
1435
1436 template <typename BasicJsonType, typename T, std::size_t N>
1437 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1438 priority_tag<2> /*unused*/)
1439 -> decltype(j.template get<T>(), void())
1440 {
1441 for (std::size_t i = 0; i < N; ++i)
1442 {
1443 arr[i] = j.at(i).template get<T>();
1444 }
1445 }
1446
1447 template<typename BasicJsonType, typename ConstructibleArrayType>
1448 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
1449 -> decltype(
1450 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
1451 j.template get<typename ConstructibleArrayType::value_type>(),
1452 void())
1453 {
1454 using std::end;
1455
1456 arr.reserve(j.size());
1457 std::transform(j.begin(), j.end(),
1458 std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1459 {
1460 // get<BasicJsonType>() returns *this, this won't call a from_json
1461 // method when value_type is BasicJsonType
1462 return i.template get<typename ConstructibleArrayType::value_type>();
1463 });
1464 }
1465
1466 template <typename BasicJsonType, typename ConstructibleArrayType>
1467 void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
1468 priority_tag<0> /*unused*/)
1469 {
1470 using std::end;
1471
1472 std::transform(
1473 j.begin(), j.end(), std::inserter(arr, end(arr)),
1474 [](const BasicJsonType & i)
1475 {
1476 // get<BasicJsonType>() returns *this, this won't call a from_json
1477 // method when value_type is BasicJsonType
1478 return i.template get<typename ConstructibleArrayType::value_type>();
1479 });
1480 }
1481
1482 template <typename BasicJsonType, typename ConstructibleArrayType,
1483 enable_if_t <
1484 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
1485 not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
1486 not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
1487 not is_basic_json<ConstructibleArrayType>::value,
1488 int > = 0 >
1489
1490 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
1491 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1492 j.template get<typename ConstructibleArrayType::value_type>(),
1493 void())
1494 {
1495 if (JSON_UNLIKELY(not j.is_array()))
1496 {
1497 JSON_THROW(type_error::create(302, "type must be array, but is " +
1498 std::string(j.type_name())));
1499 }
1500
1501 from_json_array_impl(j, arr, priority_tag<3> {});
1502 }
1503
1504 template<typename BasicJsonType, typename ConstructibleObjectType,
1505 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
1506 void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
1507 {
1508 if (JSON_UNLIKELY(not j.is_object()))
1509 {
1510 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1511 }
1512
1513 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1514 using value_type = typename ConstructibleObjectType::value_type;
1515 std::transform(
1516 inner_object->begin(), inner_object->end(),
1517 std::inserter(obj, obj.begin()),
1518 [](typename BasicJsonType::object_t::value_type const & p)
1519 {
1520 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
1521 });
1522 }
1523
1524// overload for arithmetic types, not chosen for basic_json template arguments
1525// (BooleanType, etc..); note: Is it really necessary to provide explicit
1526// overloads for boolean_t etc. in case of a custom BooleanType which is not
1527// an arithmetic type?
1528 template<typename BasicJsonType, typename ArithmeticType,
1529 enable_if_t <
1530 std::is_arithmetic<ArithmeticType>::value and
1531 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1532 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1533 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1534 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1535 int> = 0>
1536 void from_json(const BasicJsonType& j, ArithmeticType& val)
1537 {
1538 switch (static_cast<value_t>(j))
1539 {
1541 {
1542 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1543 break;
1544 }
1546 {
1547 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1548 break;
1549 }
1551 {
1552 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1553 break;
1554 }
1555 case value_t::boolean:
1556 {
1557 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1558 break;
1559 }
1560
1561 default:
1562 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1563 }
1564 }
1565
1566 template<typename BasicJsonType, typename A1, typename A2>
1567 void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1568 {
1569 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1570 }
1571
1572 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1573 void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
1574 {
1575 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1576 }
1577
1578 template<typename BasicJsonType, typename... Args>
1579 void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1580 {
1582 }
1583
1584 template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1585 typename = enable_if_t<not std::is_constructible<
1586 typename BasicJsonType::string_t, Key>::value>>
1587 void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1588 {
1589 if (JSON_UNLIKELY(not j.is_array()))
1590 {
1591 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1592 }
1593 for (const auto& p : j)
1594 {
1595 if (JSON_UNLIKELY(not p.is_array()))
1596 {
1597 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1598 }
1599 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1600 }
1601 }
1602
1603 template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1604 typename = enable_if_t<not std::is_constructible<
1605 typename BasicJsonType::string_t, Key>::value>>
1606 void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1607 {
1608 if (JSON_UNLIKELY(not j.is_array()))
1609 {
1610 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1611 }
1612 for (const auto& p : j)
1613 {
1614 if (JSON_UNLIKELY(not p.is_array()))
1615 {
1616 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1617 }
1618 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1619 }
1620 }
1621
1623 {
1624 template<typename BasicJsonType, typename T>
1625 auto operator()(const BasicJsonType& j, T& val) const
1626 noexcept(noexcept(from_json(j, val)))
1627 -> decltype(from_json(j, val), void())
1628 {
1629 return from_json(j, val);
1630 }
1631 };
1632 } // namespace detail
1633
1637 namespace
1638 {
1640 } // namespace
1641} // namespace nlohmann
1642
1643// #include <nlohmann/detail/conversions/to_json.hpp>
1644
1645
1646#include <algorithm> // copy
1647#include <ciso646> // or, and, not
1648#include <iterator> // begin, end
1649#include <string> // string
1650#include <tuple> // tuple, get
1651#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1652#include <utility> // move, forward, declval, pair
1653#include <valarray> // valarray
1654#include <vector> // vector
1655
1656// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1657
1658
1659#include <cstddef> // size_t
1660#include <iterator> // input_iterator_tag
1661#include <string> // string, to_string
1662#include <tuple> // tuple_size, get, tuple_element
1663
1664// #include <nlohmann/detail/meta/type_traits.hpp>
1665
1666// #include <nlohmann/detail/value_t.hpp>
1667
1668
1669namespace nlohmann
1670{
1671 namespace detail
1672 {
1673 template <typename IteratorType> class iteration_proxy_value
1674 {
1675 public:
1676 using difference_type = std::ptrdiff_t;
1680 using iterator_category = std::input_iterator_tag;
1681
1682 private:
1684 IteratorType anchor;
1686 std::size_t array_index = 0;
1688 mutable std::size_t array_index_last = 0;
1690 mutable std::string array_index_str = "0";
1692 const std::string empty_str = "";
1693
1694 public:
1695 explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
1696
1699 {
1700 return *this;
1701 }
1702
1705 {
1706 ++anchor;
1707 ++array_index;
1708
1709 return *this;
1710 }
1711
1714 {
1715 return anchor == o.anchor;
1716 }
1717
1720 {
1721 return anchor != o.anchor;
1722 }
1723
1725 const std::string& key() const
1726 {
1727 assert(anchor.m_object != nullptr);
1728
1729 switch (anchor.m_object->type())
1730 {
1731 // use integer array index as key
1732 case value_t::array:
1733 {
1735 {
1736 array_index_str = std::to_string(array_index);
1738 }
1739 return array_index_str;
1740 }
1741
1742 // use key from the object
1743 case value_t::object:
1744 return anchor.key();
1745
1746 // use an empty key for all primitive types
1747 default:
1748 return empty_str;
1749 }
1750 }
1751
1753 typename IteratorType::reference value() const
1754 {
1755 return anchor.value();
1756 }
1757 };
1758
1760 template<typename IteratorType> class iteration_proxy
1761 {
1762 private:
1764 typename IteratorType::reference container;
1765
1766 public:
1768 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1769 : container(cont) {}
1770
1773 {
1775 }
1776
1779 {
1781 }
1782 };
1783// Structured Bindings Support
1784// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1785// And see https://github.com/nlohmann/json/pull/1391
1786 template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
1788 {
1789 return i.key();
1790 }
1791// Structured Bindings Support
1792// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1793// And see https://github.com/nlohmann/json/pull/1391
1794 template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
1795 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
1796 {
1797 return i.value();
1798 }
1799 } // namespace detail
1800} // namespace nlohmann
1801
1802// The Addition to the STD Namespace is required to add
1803// Structured Bindings Support to the iteration_proxy_value class
1804// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1805// And see https://github.com/nlohmann/json/pull/1391
1806namespace std
1807{
1808#if defined(__clang__)
1809 // Fix: https://github.com/nlohmann/json/issues/1401
1810 #pragma clang diagnostic push
1811 #pragma clang diagnostic ignored "-Wmismatched-tags"
1812#endif
1813 template <typename IteratorType>
1814 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
1815 : public std::integral_constant<std::size_t, 2> {};
1816
1817 template <std::size_t N, typename IteratorType>
1818 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
1819 {
1820 public:
1821 using type = decltype(
1822 get<N>(std::declval <
1824 };
1825#if defined(__clang__)
1826#pragma clang diagnostic pop
1827#endif
1828} // namespace std
1829
1830// #include <nlohmann/detail/meta/cpp_future.hpp>
1831
1832// #include <nlohmann/detail/meta/type_traits.hpp>
1833
1834// #include <nlohmann/detail/value_t.hpp>
1835
1836
1837namespace nlohmann
1838{
1839 namespace detail
1840 {
1842// constructors //
1844
1845 template<value_t> struct external_constructor;
1846
1847 template<>
1849 {
1850 template<typename BasicJsonType>
1851 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1852 {
1853 j.m_type = value_t::boolean;
1854 j.m_value = b;
1855 j.assert_invariant();
1856 }
1857 };
1858
1859 template<>
1861 {
1862 template<typename BasicJsonType>
1863 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
1864 {
1865 j.m_type = value_t::string;
1866 j.m_value = s;
1867 j.assert_invariant();
1868 }
1869
1870 template<typename BasicJsonType>
1871 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1872 {
1873 j.m_type = value_t::string;
1874 j.m_value = std::move(s);
1875 j.assert_invariant();
1876 }
1877
1878 template<typename BasicJsonType, typename CompatibleStringType,
1880 int> = 0>
1881 static void construct(BasicJsonType& j, const CompatibleStringType& str)
1882 {
1883 j.m_type = value_t::string;
1884 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1885 j.assert_invariant();
1886 }
1887 };
1888
1889 template<>
1891 {
1892 template<typename BasicJsonType>
1893 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
1894 {
1895 j.m_type = value_t::number_float;
1896 j.m_value = val;
1897 j.assert_invariant();
1898 }
1899 };
1900
1901 template<>
1903 {
1904 template<typename BasicJsonType>
1905 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
1906 {
1907 j.m_type = value_t::number_unsigned;
1908 j.m_value = val;
1909 j.assert_invariant();
1910 }
1911 };
1912
1913 template<>
1915 {
1916 template<typename BasicJsonType>
1917 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
1918 {
1919 j.m_type = value_t::number_integer;
1920 j.m_value = val;
1921 j.assert_invariant();
1922 }
1923 };
1924
1925 template<>
1927 {
1928 template<typename BasicJsonType>
1929 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1930 {
1931 j.m_type = value_t::array;
1932 j.m_value = arr;
1933 j.assert_invariant();
1934 }
1935
1936 template<typename BasicJsonType>
1937 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1938 {
1939 j.m_type = value_t::array;
1940 j.m_value = std::move(arr);
1941 j.assert_invariant();
1942 }
1943
1944 template<typename BasicJsonType, typename CompatibleArrayType,
1946 int> = 0>
1947 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1948 {
1949 using std::begin;
1950 using std::end;
1951 j.m_type = value_t::array;
1952 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1953 j.assert_invariant();
1954 }
1955
1956 template<typename BasicJsonType>
1957 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1958 {
1959 j.m_type = value_t::array;
1960 j.m_value = value_t::array;
1961 j.m_value.array->reserve(arr.size());
1962 for (const bool x : arr)
1963 {
1964 j.m_value.array->push_back(x);
1965 }
1966 j.assert_invariant();
1967 }
1968
1969 template<typename BasicJsonType, typename T,
1971 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1972 {
1973 j.m_type = value_t::array;
1974 j.m_value = value_t::array;
1975 j.m_value.array->resize(arr.size());
1976 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1977 j.assert_invariant();
1978 }
1979 };
1980
1981 template<>
1983 {
1984 template<typename BasicJsonType>
1985 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1986 {
1987 j.m_type = value_t::object;
1988 j.m_value = obj;
1989 j.assert_invariant();
1990 }
1991
1992 template<typename BasicJsonType>
1993 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1994 {
1995 j.m_type = value_t::object;
1996 j.m_value = std::move(obj);
1997 j.assert_invariant();
1998 }
1999
2000 template<typename BasicJsonType, typename CompatibleObjectType,
2002 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
2003 {
2004 using std::begin;
2005 using std::end;
2006
2007 j.m_type = value_t::object;
2008 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
2009 j.assert_invariant();
2010 }
2011 };
2012
2014// to_json //
2016
2017 template<typename BasicJsonType, typename T,
2018 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
2019 void to_json(BasicJsonType& j, T b) noexcept
2020 {
2022 }
2023
2024 template<typename BasicJsonType, typename CompatibleString,
2025 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
2026 void to_json(BasicJsonType& j, const CompatibleString& s)
2027 {
2029 }
2030
2031 template<typename BasicJsonType>
2032 void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
2033 {
2035 }
2036
2037 template<typename BasicJsonType, typename FloatType,
2038 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
2039 void to_json(BasicJsonType& j, FloatType val) noexcept
2040 {
2041 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
2042 }
2043
2044 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
2045 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
2046 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
2047 {
2048 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
2049 }
2050
2051 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
2052 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
2053 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
2054 {
2055 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
2056 }
2057
2058 template<typename BasicJsonType, typename EnumType,
2059 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
2060 void to_json(BasicJsonType& j, EnumType e) noexcept
2061 {
2062 using underlying_type = typename std::underlying_type<EnumType>::type;
2063 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
2064 }
2065
2066 template<typename BasicJsonType>
2067 void to_json(BasicJsonType& j, const std::vector<bool>& e)
2068 {
2070 }
2071
2072 template <typename BasicJsonType, typename CompatibleArrayType,
2073 enable_if_t<is_compatible_array_type<BasicJsonType,
2074 CompatibleArrayType>::value and
2075 not is_compatible_object_type<
2076 BasicJsonType, CompatibleArrayType>::value and
2077 not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
2078 not is_basic_json<CompatibleArrayType>::value,
2079 int> = 0>
2080 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
2081 {
2083 }
2084
2085 template<typename BasicJsonType, typename T,
2086 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
2087 void to_json(BasicJsonType& j, const std::valarray<T>& arr)
2088 {
2090 }
2091
2092 template<typename BasicJsonType>
2093 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
2094 {
2096 }
2097
2098 template<typename BasicJsonType, typename CompatibleObjectType,
2099 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
2100 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
2101 {
2103 }
2104
2105 template<typename BasicJsonType>
2106 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
2107 {
2109 }
2110
2111 template <
2112 typename BasicJsonType, typename T, std::size_t N,
2113 enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
2114 const T(&)[N]>::value,
2115 int> = 0 >
2116 void to_json(BasicJsonType& j, const T(&arr)[N])
2117 {
2119 }
2120
2121 template<typename BasicJsonType, typename... Args>
2122 void to_json(BasicJsonType& j, const std::pair<Args...>& p)
2123 {
2124 j = { p.first, p.second };
2125 }
2126
2127// for https://github.com/nlohmann/json/pull/1134
2128 template < typename BasicJsonType, typename T,
2129 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
2130 void to_json(BasicJsonType& j, const T& b)
2131 {
2132 j = { {b.key(), b.value()} };
2133 }
2134
2135 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
2136 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
2137 {
2138 j = { std::get<Idx>(t)... };
2139 }
2140
2141 template<typename BasicJsonType, typename... Args>
2142 void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
2143 {
2145 }
2146
2148 {
2149 template<typename BasicJsonType, typename T>
2150 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
2151 -> decltype(to_json(j, std::forward<T>(val)), void())
2152 {
2153 return to_json(j, std::forward<T>(val));
2154 }
2155 };
2156 } // namespace detail
2157
2159 namespace
2160 {
2162 } // namespace
2163} // namespace nlohmann
2164
2165
2166namespace nlohmann
2167{
2168
2169 template<typename, typename>
2171 {
2181 template<typename BasicJsonType, typename ValueType>
2182 static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
2183 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
2184 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
2185 {
2186 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
2187 }
2188
2198 template <typename BasicJsonType, typename ValueType>
2199 static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
2200 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
2201 -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
2202 {
2203 ::nlohmann::to_json(j, std::forward<ValueType>(val));
2204 }
2205 };
2206
2207} // namespace nlohmann
2208
2209// #include <nlohmann/detail/conversions/from_json.hpp>
2210
2211// #include <nlohmann/detail/conversions/to_json.hpp>
2212
2213// #include <nlohmann/detail/exceptions.hpp>
2214
2215// #include <nlohmann/detail/input/binary_reader.hpp>
2216
2217
2218#include <algorithm> // generate_n
2219#include <array> // array
2220#include <cassert> // assert
2221#include <cmath> // ldexp
2222#include <cstddef> // size_t
2223#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
2224#include <cstdio> // snprintf
2225#include <cstring> // memcpy
2226#include <iterator> // back_inserter
2227#include <limits> // numeric_limits
2228#include <string> // char_traits, string
2229#include <utility> // make_pair, move
2230
2231// #include <nlohmann/detail/exceptions.hpp>
2232
2233// #include <nlohmann/detail/input/input_adapters.hpp>
2234
2235
2236#include <array> // array
2237#include <cassert> // assert
2238#include <cstddef> // size_t
2239#include <cstdio> //FILE *
2240#include <cstring> // strlen
2241#include <istream> // istream
2242#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
2243#include <memory> // shared_ptr, make_shared, addressof
2244#include <numeric> // accumulate
2245#include <string> // string, char_traits
2246#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
2247#include <utility> // pair, declval
2248
2249// #include <nlohmann/detail/iterators/iterator_traits.hpp>
2250
2251// #include <nlohmann/detail/macro_scope.hpp>
2252
2253
2254namespace nlohmann
2255{
2256 namespace detail
2257 {
2260
2262// input adapters //
2264
2277 {
2279 virtual std::char_traits<char>::int_type get_character() = 0;
2280 virtual ~input_adapter_protocol() = default;
2281 };
2282
2284 using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
2285
2291 {
2292 public:
2293 explicit file_input_adapter(std::FILE* f) noexcept
2294 : m_file(f)
2295 {}
2296
2297 // make class move-only
2302 ~file_input_adapter() override = default;
2303
2304 std::char_traits<char>::int_type get_character() noexcept override
2305 {
2306 return std::fgetc(m_file);
2307 }
2308
2309 private:
2311 std::FILE* m_file;
2312 };
2313
2314
2325 {
2326 public:
2328 {
2329 // clear stream flags; we use underlying streambuf I/O, do not
2330 // maintain ifstream flags, except eof
2331 is.clear(is.rdstate() & std::ios::eofbit);
2332 }
2333
2334 explicit input_stream_adapter(std::istream& i)
2335 : is(i), sb(*i.rdbuf())
2336 {}
2337
2338 // delete because of pointer members
2343
2344 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
2345 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
2346 // end up as the same value, eg. 0xFFFFFFFF.
2347 std::char_traits<char>::int_type get_character() override
2348 {
2349 auto res = sb.sbumpc();
2350 // set eof manually, as we don't use the istream interface.
2351 if (res == EOF)
2352 {
2353 is.clear(is.rdstate() | std::ios::eofbit);
2354 }
2355 return res;
2356 }
2357
2358 private:
2360 std::istream& is;
2361 std::streambuf& sb;
2362 };
2363
2366 {
2367 public:
2368 input_buffer_adapter(const char* b, const std::size_t l) noexcept
2369 : cursor(b), limit(b + l)
2370 {}
2371
2372 // delete because of pointer members
2377 ~input_buffer_adapter() override = default;
2378
2379 std::char_traits<char>::int_type get_character() noexcept override
2380 {
2381 if (JSON_LIKELY(cursor < limit))
2382 {
2383 return std::char_traits<char>::to_int_type(*(cursor++));
2384 }
2385
2386 return std::char_traits<char>::eof();
2387 }
2388
2389 private:
2391 const char* cursor;
2393 const char* const limit;
2394 };
2395
2396 template<typename WideStringType, size_t T>
2398 {
2399 // UTF-32
2400 static void fill_buffer(const WideStringType& str,
2401 size_t& current_wchar,
2402 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
2403 size_t& utf8_bytes_index,
2404 size_t& utf8_bytes_filled)
2405 {
2406 utf8_bytes_index = 0;
2407
2408 if (current_wchar == str.size())
2409 {
2410 utf8_bytes[0] = std::char_traits<char>::eof();
2411 utf8_bytes_filled = 1;
2412 }
2413 else
2414 {
2415 // get the current character
2416 const auto wc = static_cast<unsigned int>(str[current_wchar++]);
2417
2418 // UTF-32 to UTF-8 encoding
2419 if (wc < 0x80)
2420 {
2421 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2422 utf8_bytes_filled = 1;
2423 }
2424 else if (wc <= 0x7FF)
2425 {
2426 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
2427 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2428 utf8_bytes_filled = 2;
2429 }
2430 else if (wc <= 0xFFFF)
2431 {
2432 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
2433 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
2434 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2435 utf8_bytes_filled = 3;
2436 }
2437 else if (wc <= 0x10FFFF)
2438 {
2439 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
2440 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
2441 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
2442 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2443 utf8_bytes_filled = 4;
2444 }
2445 else
2446 {
2447 // unknown character
2448 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2449 utf8_bytes_filled = 1;
2450 }
2451 }
2452 }
2453 };
2454
2455 template<typename WideStringType>
2456 struct wide_string_input_helper<WideStringType, 2>
2457 {
2458 // UTF-16
2459 static void fill_buffer(const WideStringType& str,
2460 size_t& current_wchar,
2461 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
2462 size_t& utf8_bytes_index,
2463 size_t& utf8_bytes_filled)
2464 {
2465 utf8_bytes_index = 0;
2466
2467 if (current_wchar == str.size())
2468 {
2469 utf8_bytes[0] = std::char_traits<char>::eof();
2470 utf8_bytes_filled = 1;
2471 }
2472 else
2473 {
2474 // get the current character
2475 const auto wc = static_cast<unsigned int>(str[current_wchar++]);
2476
2477 // UTF-16 to UTF-8 encoding
2478 if (wc < 0x80)
2479 {
2480 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2481 utf8_bytes_filled = 1;
2482 }
2483 else if (wc <= 0x7FF)
2484 {
2485 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
2486 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2487 utf8_bytes_filled = 2;
2488 }
2489 else if (0xD800 > wc or wc >= 0xE000)
2490 {
2491 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
2492 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
2493 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2494 utf8_bytes_filled = 3;
2495 }
2496 else
2497 {
2498 if (current_wchar < str.size())
2499 {
2500 const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
2501 const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
2502 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
2503 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
2504 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
2505 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
2506 utf8_bytes_filled = 4;
2507 }
2508 else
2509 {
2510 // unknown character
2511 ++current_wchar;
2512 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2513 utf8_bytes_filled = 1;
2514 }
2515 }
2516 }
2517 }
2518 };
2519
2520 template<typename WideStringType>
2522 {
2523 public:
2524 explicit wide_string_input_adapter(const WideStringType& w) noexcept
2525 : str(w)
2526 {}
2527
2528 std::char_traits<char>::int_type get_character() noexcept override
2529 {
2530 // check if buffer needs to be filled
2532 {
2533 fill_buffer<sizeof(typename WideStringType::value_type)>();
2534
2535 assert(utf8_bytes_filled > 0);
2536 assert(utf8_bytes_index == 0);
2537 }
2538
2539 // use buffer
2540 assert(utf8_bytes_filled > 0);
2542 return utf8_bytes[utf8_bytes_index++];
2543 }
2544
2545 private:
2546 template<size_t T>
2548 {
2550 }
2551
2553 const WideStringType& str;
2554
2556 std::size_t current_wchar = 0;
2557
2559 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2560
2562 std::size_t utf8_bytes_index = 0;
2564 std::size_t utf8_bytes_filled = 0;
2565 };
2566
2568 {
2569 public:
2570 // native support
2571 input_adapter(std::FILE* file)
2572 : ia(std::make_shared<file_input_adapter>(file)) {}
2574 input_adapter(std::istream& i)
2575 : ia(std::make_shared<input_stream_adapter>(i)) {}
2576
2578 input_adapter(std::istream&& i)
2579 : ia(std::make_shared<input_stream_adapter>(i)) {}
2580
2581 input_adapter(const std::wstring& ws)
2582 : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2583
2584 input_adapter(const std::u16string& ws)
2585 : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2586
2587 input_adapter(const std::u32string& ws)
2588 : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2589
2591 template<typename CharT,
2592 typename std::enable_if<
2593 std::is_pointer<CharT>::value and
2594 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2595 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2596 int>::type = 0>
2597 input_adapter(CharT b, std::size_t l)
2598 : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2599
2600 // derived support
2601
2603 template<typename CharT,
2604 typename std::enable_if<
2605 std::is_pointer<CharT>::value and
2606 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2607 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2608 int>::type = 0>
2610 : input_adapter(reinterpret_cast<const char*>(b),
2611 std::strlen(reinterpret_cast<const char*>(b))) {}
2612
2614 template<class IteratorType,
2615 typename std::enable_if<
2616 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2617 int>::type = 0>
2618 input_adapter(IteratorType first, IteratorType last)
2619 {
2620#ifndef NDEBUG
2621 // assertion to check that the iterator range is indeed contiguous,
2622 // see http://stackoverflow.com/a/35008842/266378 for more discussion
2623 const auto is_contiguous = std::accumulate(
2624 first, last, std::pair<bool, int>(true, 0),
2625 [&first](std::pair<bool, int> res, decltype(*first) val)
2626 {
2627 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2628 return res;
2629 }).first;
2630 assert(is_contiguous);
2631#endif
2632
2633 // assertion to check that each element is 1 byte long
2634 static_assert(
2635 sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
2636 "each element in the iterator range must have the size of 1 byte");
2637
2638 const auto len = static_cast<size_t>(std::distance(first, last));
2639 if (JSON_LIKELY(len > 0))
2640 {
2641 // there is at least one element: use the address of first
2642 ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2643 }
2644 else
2645 {
2646 // the address of first cannot be used: use nullptr
2647 ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2648 }
2649 }
2650
2652 template<class T, std::size_t N>
2653 input_adapter(T (&array)[N])
2654 : input_adapter(std::begin(array), std::end(array)) {}
2655
2657 template<class ContiguousContainer, typename
2658 std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2659 std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2660 int>::type = 0>
2661 input_adapter(const ContiguousContainer& c)
2662 : input_adapter(std::begin(c), std::end(c)) {}
2663
2665 {
2666 return ia;
2667 }
2668
2669 private:
2672 };
2673 } // namespace detail
2674} // namespace nlohmann
2675
2676// #include <nlohmann/detail/input/json_sax.hpp>
2677
2678
2679#include <cassert> // assert
2680#include <cstddef>
2681#include <string> // string
2682#include <utility> // move
2683#include <vector> // vector
2684
2685// #include <nlohmann/detail/exceptions.hpp>
2686
2687// #include <nlohmann/detail/macro_scope.hpp>
2688
2689
2690namespace nlohmann
2691{
2692
2701 template<typename BasicJsonType>
2703 {
2705 using number_integer_t = typename BasicJsonType::number_integer_t;
2707 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2709 using number_float_t = typename BasicJsonType::number_float_t;
2711 using string_t = typename BasicJsonType::string_t;
2712
2717 virtual bool null() = 0;
2718
2724 virtual bool boolean(bool val) = 0;
2725
2731 virtual bool number_integer(number_integer_t val) = 0;
2732
2738 virtual bool number_unsigned(number_unsigned_t val) = 0;
2739
2746 virtual bool number_float(number_float_t val, const string_t& s) = 0;
2747
2754 virtual bool string(string_t& val) = 0;
2755
2762 virtual bool start_object(std::size_t elements) = 0;
2763
2770 virtual bool key(string_t& val) = 0;
2771
2776 virtual bool end_object() = 0;
2777
2784 virtual bool start_array(std::size_t elements) = 0;
2785
2790 virtual bool end_array() = 0;
2791
2799 virtual bool parse_error(std::size_t position,
2800 const std::string& last_token,
2801 const detail::exception& ex) = 0;
2802
2803 virtual ~json_sax() = default;
2804 };
2805
2806
2807 namespace detail
2808 {
2822 template<typename BasicJsonType>
2824 {
2825 public:
2826 using number_integer_t = typename BasicJsonType::number_integer_t;
2827 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2828 using number_float_t = typename BasicJsonType::number_float_t;
2829 using string_t = typename BasicJsonType::string_t;
2830
2836 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
2837 : root(r), allow_exceptions(allow_exceptions_)
2838 {}
2839
2840 // make class move-only
2846
2847 bool null()
2848 {
2849 handle_value(nullptr);
2850 return true;
2851 }
2852
2853 bool boolean(bool val)
2854 {
2855 handle_value(val);
2856 return true;
2857 }
2858
2860 {
2861 handle_value(val);
2862 return true;
2863 }
2864
2866 {
2867 handle_value(val);
2868 return true;
2869 }
2870
2871 bool number_float(number_float_t val, const string_t& /*unused*/)
2872 {
2873 handle_value(val);
2874 return true;
2875 }
2876
2877 bool string(string_t& val)
2878 {
2879 handle_value(val);
2880 return true;
2881 }
2882
2883 bool start_object(std::size_t len)
2884 {
2885 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
2886
2887 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
2888 {
2890 "excessive object size: " + std::to_string(len)));
2891 }
2892
2893 return true;
2894 }
2895
2896 bool key(string_t& val)
2897 {
2898 // add null at given key and store the reference for later
2899 object_element = &(ref_stack.back()->m_value.object->operator[](val));
2900 return true;
2901 }
2902
2904 {
2906 return true;
2907 }
2908
2909 bool start_array(std::size_t len)
2910 {
2911 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
2912
2913 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
2914 {
2916 "excessive array size: " + std::to_string(len)));
2917 }
2918
2919 return true;
2920 }
2921
2923 {
2925 return true;
2926 }
2927
2928 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
2929 const detail::exception& ex)
2930 {
2931 errored = true;
2932 if (allow_exceptions)
2933 {
2934 // determine the proper exception type from the id
2935 switch ((ex.id / 100) % 100)
2936 {
2937 case 1:
2938 JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
2939 case 4:
2940 JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
2941 // LCOV_EXCL_START
2942 case 2:
2943 JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
2944 case 3:
2945 JSON_THROW(*static_cast<const detail::type_error*>(&ex));
2946 case 5:
2947 JSON_THROW(*static_cast<const detail::other_error*>(&ex));
2948 default:
2949 assert(false);
2950 // LCOV_EXCL_STOP
2951 }
2952 }
2953 return false;
2954 }
2955
2956 constexpr bool is_errored() const
2957 {
2958 return errored;
2959 }
2960
2961 private:
2968 template<typename Value>
2969 BasicJsonType* handle_value(Value&& v)
2970 {
2971 if (ref_stack.empty())
2972 {
2973 root = BasicJsonType(std::forward<Value>(v));
2974 return &root;
2975 }
2976
2977 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
2978
2979 if (ref_stack.back()->is_array())
2980 {
2981 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
2982 return &(ref_stack.back()->m_value.array->back());
2983 }
2984
2985 assert(ref_stack.back()->is_object());
2986 assert(object_element);
2987 *object_element = BasicJsonType(std::forward<Value>(v));
2988 return object_element;
2989 }
2990
2992 BasicJsonType& root;
2996 BasicJsonType* object_element = nullptr;
2998 bool errored = false;
3000 const bool allow_exceptions = true;
3001 };
3002
3003 template<typename BasicJsonType>
3005 {
3006 public:
3007 using number_integer_t = typename BasicJsonType::number_integer_t;
3008 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3009 using number_float_t = typename BasicJsonType::number_float_t;
3010 using string_t = typename BasicJsonType::string_t;
3011 using parser_callback_t = typename BasicJsonType::parser_callback_t;
3012 using parse_event_t = typename BasicJsonType::parse_event_t;
3013
3015 const parser_callback_t cb,
3016 const bool allow_exceptions_ = true)
3017 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
3018 {
3019 keep_stack.push_back(true);
3020 }
3021
3022 // make class move-only
3028
3029 bool null()
3030 {
3031 handle_value(nullptr);
3032 return true;
3033 }
3034
3035 bool boolean(bool val)
3036 {
3037 handle_value(val);
3038 return true;
3039 }
3040
3042 {
3043 handle_value(val);
3044 return true;
3045 }
3046
3048 {
3049 handle_value(val);
3050 return true;
3051 }
3052
3053 bool number_float(number_float_t val, const string_t& /*unused*/)
3054 {
3055 handle_value(val);
3056 return true;
3057 }
3058
3059 bool string(string_t& val)
3060 {
3061 handle_value(val);
3062 return true;
3063 }
3064
3065 bool start_object(std::size_t len)
3066 {
3067 // check callback for object start
3068 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
3069 keep_stack.push_back(keep);
3070
3071 auto val = handle_value(BasicJsonType::value_t::object, true);
3072 ref_stack.push_back(val.second);
3073
3074 // check object limit
3075 if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3076 {
3077 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
3078 }
3079
3080 return true;
3081 }
3082
3083 bool key(string_t& val)
3084 {
3085 BasicJsonType k = BasicJsonType(val);
3086
3087 // check callback for key
3088 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
3090
3091 // add discarded value at given key and store the reference for later
3092 if (keep and ref_stack.back())
3093 {
3094 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
3095 }
3096
3097 return true;
3098 }
3099
3101 {
3102 if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
3103 {
3104 // discard object
3106 }
3107
3108 assert(not ref_stack.empty());
3109 assert(not keep_stack.empty());
3112
3113 if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
3114 {
3115 // remove discarded value
3116 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
3117 {
3118 if (it->is_discarded())
3119 {
3120 ref_stack.back()->erase(it);
3121 break;
3122 }
3123 }
3124 }
3125
3126 return true;
3127 }
3128
3129 bool start_array(std::size_t len)
3130 {
3131 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
3132 keep_stack.push_back(keep);
3133
3134 auto val = handle_value(BasicJsonType::value_t::array, true);
3135 ref_stack.push_back(val.second);
3136
3137 // check array limit
3138 if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3139 {
3140 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
3141 }
3142
3143 return true;
3144 }
3145
3147 {
3148 bool keep = true;
3149
3150 if (ref_stack.back())
3151 {
3152 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
3153 if (not keep)
3154 {
3155 // discard array
3157 }
3158 }
3159
3160 assert(not ref_stack.empty());
3161 assert(not keep_stack.empty());
3164
3165 // remove discarded value
3166 if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
3167 {
3168 ref_stack.back()->m_value.array->pop_back();
3169 }
3170
3171 return true;
3172 }
3173
3174 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
3175 const detail::exception& ex)
3176 {
3177 errored = true;
3178 if (allow_exceptions)
3179 {
3180 // determine the proper exception type from the id
3181 switch ((ex.id / 100) % 100)
3182 {
3183 case 1:
3184 JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
3185 case 4:
3186 JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
3187 // LCOV_EXCL_START
3188 case 2:
3189 JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
3190 case 3:
3191 JSON_THROW(*static_cast<const detail::type_error*>(&ex));
3192 case 5:
3193 JSON_THROW(*static_cast<const detail::other_error*>(&ex));
3194 default:
3195 assert(false);
3196 // LCOV_EXCL_STOP
3197 }
3198 }
3199 return false;
3200 }
3201
3202 constexpr bool is_errored() const
3203 {
3204 return errored;
3205 }
3206
3207 private:
3223 template<typename Value>
3224 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
3225 {
3226 assert(not keep_stack.empty());
3227
3228 // do not handle this value if we know it would be added to a discarded
3229 // container
3230 if (not keep_stack.back())
3231 {
3232 return {false, nullptr};
3233 }
3234
3235 // create value
3236 auto value = BasicJsonType(std::forward<Value>(v));
3237
3238 // check callback
3239 const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
3240
3241 // do not handle this value if we just learnt it shall be discarded
3242 if (not keep)
3243 {
3244 return {false, nullptr};
3245 }
3246
3247 if (ref_stack.empty())
3248 {
3249 root = std::move(value);
3250 return {true, &root};
3251 }
3252
3253 // skip this value if we already decided to skip the parent
3254 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
3255 if (not ref_stack.back())
3256 {
3257 return {false, nullptr};
3258 }
3259
3260 // we now only expect arrays and objects
3261 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
3262
3263 // array
3264 if (ref_stack.back()->is_array())
3265 {
3266 ref_stack.back()->m_value.array->push_back(std::move(value));
3267 return {true, &(ref_stack.back()->m_value.array->back())};
3268 }
3269
3270 // object
3271 assert(ref_stack.back()->is_object());
3272 // check if we should store an element for the current key
3273 assert(not key_keep_stack.empty());
3274 const bool store_element = key_keep_stack.back();
3276
3277 if (not store_element)
3278 {
3279 return {false, nullptr};
3280 }
3281
3282 assert(object_element);
3283 *object_element = std::move(value);
3284 return {true, object_element};
3285 }
3286
3288 BasicJsonType& root;
3296 BasicJsonType* object_element = nullptr;
3298 bool errored = false;
3302 const bool allow_exceptions = true;
3304 BasicJsonType discarded = BasicJsonType::value_t::discarded;
3305 };
3306
3307 template<typename BasicJsonType>
3309 {
3310 public:
3311 using number_integer_t = typename BasicJsonType::number_integer_t;
3312 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3313 using number_float_t = typename BasicJsonType::number_float_t;
3314 using string_t = typename BasicJsonType::string_t;
3315
3316 bool null()
3317 {
3318 return true;
3319 }
3320
3321 bool boolean(bool /*unused*/)
3322 {
3323 return true;
3324 }
3325
3327 {
3328 return true;
3329 }
3330
3332 {
3333 return true;
3334 }
3335
3336 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
3337 {
3338 return true;
3339 }
3340
3341 bool string(string_t& /*unused*/)
3342 {
3343 return true;
3344 }
3345
3346 bool start_object(std::size_t /*unused*/ = std::size_t(-1))
3347 {
3348 return true;
3349 }
3350
3351 bool key(string_t& /*unused*/)
3352 {
3353 return true;
3354 }
3355
3357 {
3358 return true;
3359 }
3360
3361 bool start_array(std::size_t /*unused*/ = std::size_t(-1))
3362 {
3363 return true;
3364 }
3365
3367 {
3368 return true;
3369 }
3370
3371 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
3372 {
3373 return false;
3374 }
3375 };
3376 } // namespace detail
3377
3378} // namespace nlohmann
3379
3380// #include <nlohmann/detail/macro_scope.hpp>
3381
3382// #include <nlohmann/detail/meta/is_sax.hpp>
3383
3384
3385#include <cstdint> // size_t
3386#include <utility> // declval
3387#include <string> // string
3388
3389// #include <nlohmann/detail/meta/detected.hpp>
3390
3391// #include <nlohmann/detail/meta/type_traits.hpp>
3392
3393
3394namespace nlohmann
3395{
3396 namespace detail
3397 {
3398 template <typename T>
3399 using null_function_t = decltype(std::declval<T&>().null());
3400
3401 template <typename T>
3403 decltype(std::declval<T&>().boolean(std::declval<bool>()));
3404
3405 template <typename T, typename Integer>
3407 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
3408
3409 template <typename T, typename Unsigned>
3411 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
3412
3413 template <typename T, typename Float, typename String>
3414 using number_float_function_t = decltype(std::declval<T&>().number_float(
3415 std::declval<Float>(), std::declval<const String&>()));
3416
3417 template <typename T, typename String>
3419 decltype(std::declval<T&>().string(std::declval<String&>()));
3420
3421 template <typename T>
3423 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
3424
3425 template <typename T, typename String>
3427 decltype(std::declval<T&>().key(std::declval<String&>()));
3428
3429 template <typename T>
3430 using end_object_function_t = decltype(std::declval<T&>().end_object());
3431
3432 template <typename T>
3434 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
3435
3436 template <typename T>
3437 using end_array_function_t = decltype(std::declval<T&>().end_array());
3438
3439 template <typename T, typename Exception>
3440 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
3441 std::declval<std::size_t>(), std::declval<const std::string&>(),
3442 std::declval<const Exception&>()));
3443
3444 template <typename SAX, typename BasicJsonType>
3445 struct is_sax
3446 {
3447 private:
3449 "BasicJsonType must be of type basic_json<...>");
3450
3451 using number_integer_t = typename BasicJsonType::number_integer_t;
3452 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3453 using number_float_t = typename BasicJsonType::number_float_t;
3454 using string_t = typename BasicJsonType::string_t;
3455 using exception_t = typename BasicJsonType::exception;
3456
3457 public:
3458 static constexpr bool value =
3466 string_t>::value &&
3474 };
3475
3476 template <typename SAX, typename BasicJsonType>
3478 {
3479 private:
3481 "BasicJsonType must be of type basic_json<...>");
3482
3483 using number_integer_t = typename BasicJsonType::number_integer_t;
3484 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3485 using number_float_t = typename BasicJsonType::number_float_t;
3486 using string_t = typename BasicJsonType::string_t;
3487 using exception_t = typename BasicJsonType::exception;
3488
3489 public:
3491 "Missing/invalid function: bool null()");
3493 "Missing/invalid function: bool boolean(bool)");
3495 "Missing/invalid function: bool boolean(bool)");
3496 static_assert(
3498 number_integer_t>::value,
3499 "Missing/invalid function: bool number_integer(number_integer_t)");
3500 static_assert(
3502 number_unsigned_t>::value,
3503 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
3504 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
3505 number_float_t, string_t>::value,
3506 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
3507 static_assert(
3509 "Missing/invalid function: bool string(string_t&)");
3511 "Missing/invalid function: bool start_object(std::size_t)");
3513 "Missing/invalid function: bool key(string_t&)");
3515 "Missing/invalid function: bool end_object()");
3517 "Missing/invalid function: bool start_array(std::size_t)");
3519 "Missing/invalid function: bool end_array()");
3520 static_assert(
3522 "Missing/invalid function: bool parse_error(std::size_t, const "
3523 "std::string&, const exception&)");
3524 };
3525 } // namespace detail
3526} // namespace nlohmann
3527
3528// #include <nlohmann/detail/value_t.hpp>
3529
3530
3531namespace nlohmann
3532{
3533 namespace detail
3534 {
3536// binary reader //
3538
3542 template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
3544 {
3545 using number_integer_t = typename BasicJsonType::number_integer_t;
3546 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3547 using number_float_t = typename BasicJsonType::number_float_t;
3548 using string_t = typename BasicJsonType::string_t;
3549 using json_sax_t = SAX;
3550
3551 public:
3557 explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
3558 {
3560 assert(ia);
3561 }
3562
3563 // make class move-only
3568 ~binary_reader() = default;
3569
3577 bool sax_parse(const input_format_t format,
3578 json_sax_t* sax_,
3579 const bool strict = true)
3580 {
3581 sax = sax_;
3582 bool result = false;
3583
3584 switch (format)
3585 {
3587 result = parse_bson_internal();
3588 break;
3589
3591 result = parse_cbor_internal();
3592 break;
3593
3595 result = parse_msgpack_internal();
3596 break;
3597
3599 result = parse_ubjson_internal();
3600 break;
3601
3602 default: // LCOV_EXCL_LINE
3603 assert(false); // LCOV_EXCL_LINE
3604 }
3605
3606 // strict mode: next byte must be EOF
3607 if (result and strict)
3608 {
3609 if (format == input_format_t::ubjson)
3610 {
3612 }
3613 else
3614 {
3615 get();
3616 }
3617
3618 if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
3619 {
3620 return sax->parse_error(chars_read, get_token_string(),
3621 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
3622 }
3623 }
3624
3625 return result;
3626 }
3627
3635 static constexpr bool little_endianess(int num = 1) noexcept
3636 {
3637 return *reinterpret_cast<char*>(&num) == 1;
3638 }
3639
3640 private:
3642 // BSON //
3644
3650 {
3651 std::int32_t document_size;
3652 get_number<std::int32_t, true>(input_format_t::bson, document_size);
3653
3654 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
3655 {
3656 return false;
3657 }
3658
3659 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
3660 {
3661 return false;
3662 }
3663
3664 return sax->end_object();
3665 }
3666
3675 {
3676 auto out = std::back_inserter(result);
3677 while (true)
3678 {
3679 get();
3680 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
3681 {
3682 return false;
3683 }
3684 if (current == 0x00)
3685 {
3686 return true;
3687 }
3688 *out++ = static_cast<char>(current);
3689 }
3690
3691 return true;
3692 }
3693
3705 template<typename NumberType>
3706 bool get_bson_string(const NumberType len, string_t& result)
3707 {
3708 if (JSON_UNLIKELY(len < 1))
3709 {
3710 auto last_token = get_token_string();
3711 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
3712 }
3713
3714 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();
3715 }
3716
3727 bool parse_bson_element_internal(const int element_type,
3728 const std::size_t element_type_parse_position)
3729 {
3730 switch (element_type)
3731 {
3732 case 0x01: // double
3733 {
3734 double number;
3735 return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), "");
3736 }
3737
3738 case 0x02: // string
3739 {
3740 std::int32_t len;
3741 string_t value;
3742 return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);
3743 }
3744
3745 case 0x03: // object
3746 {
3747 return parse_bson_internal();
3748 }
3749
3750 case 0x04: // array
3751 {
3752 return parse_bson_array();
3753 }
3754
3755 case 0x08: // boolean
3756 {
3757 return sax->boolean(get() != 0);
3758 }
3759
3760 case 0x0A: // null
3761 {
3762 return sax->null();
3763 }
3764
3765 case 0x10: // int32
3766 {
3767 std::int32_t value;
3768 return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);
3769 }
3770
3771 case 0x12: // int64
3772 {
3773 std::int64_t value;
3774 return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);
3775 }
3776
3777 default: // anything else not supported (yet)
3778 {
3779 std::array<char, 3> cr{{}};
3780 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
3781 return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
3782 }
3783 }
3784 }
3785
3798 bool parse_bson_element_list(const bool is_array)
3799 {
3800 string_t key;
3801 while (int element_type = get())
3802 {
3803 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
3804 {
3805 return false;
3806 }
3807
3808 const std::size_t element_type_parse_position = chars_read;
3809 if (JSON_UNLIKELY(not get_bson_cstr(key)))
3810 {
3811 return false;
3812 }
3813
3814 if (not is_array and not sax->key(key))
3815 {
3816 return false;
3817 }
3818
3819 if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
3820 {
3821 return false;
3822 }
3823
3824 // get_bson_cstr only appends
3825 key.clear();
3826 }
3827
3828 return true;
3829 }
3830
3836 {
3837 std::int32_t document_size;
3838 get_number<std::int32_t, true>(input_format_t::bson, document_size);
3839
3840 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
3841 {
3842 return false;
3843 }
3844
3845 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
3846 {
3847 return false;
3848 }
3849
3850 return sax->end_array();
3851 }
3852
3854 // CBOR //
3856
3864 bool parse_cbor_internal(const bool get_char = true)
3865 {
3866 switch (get_char ? get() : current)
3867 {
3868 // EOF
3869 case std::char_traits<char>::eof():
3870 return unexpect_eof(input_format_t::cbor, "value");
3871
3872 // Integer 0x00..0x17 (0..23)
3873 case 0x00:
3874 case 0x01:
3875 case 0x02:
3876 case 0x03:
3877 case 0x04:
3878 case 0x05:
3879 case 0x06:
3880 case 0x07:
3881 case 0x08:
3882 case 0x09:
3883 case 0x0A:
3884 case 0x0B:
3885 case 0x0C:
3886 case 0x0D:
3887 case 0x0E:
3888 case 0x0F:
3889 case 0x10:
3890 case 0x11:
3891 case 0x12:
3892 case 0x13:
3893 case 0x14:
3894 case 0x15:
3895 case 0x16:
3896 case 0x17:
3897 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
3898
3899 case 0x18: // Unsigned integer (one-byte uint8_t follows)
3900 {
3901 std::uint8_t number;
3902 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3903 }
3904
3905 case 0x19: // Unsigned integer (two-byte uint16_t follows)
3906 {
3907 std::uint16_t number;
3908 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3909 }
3910
3911 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
3912 {
3913 std::uint32_t number;
3914 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3915 }
3916
3917 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
3918 {
3919 std::uint64_t number;
3920 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3921 }
3922
3923 // Negative integer -1-0x00..-1-0x17 (-1..-24)
3924 case 0x20:
3925 case 0x21:
3926 case 0x22:
3927 case 0x23:
3928 case 0x24:
3929 case 0x25:
3930 case 0x26:
3931 case 0x27:
3932 case 0x28:
3933 case 0x29:
3934 case 0x2A:
3935 case 0x2B:
3936 case 0x2C:
3937 case 0x2D:
3938 case 0x2E:
3939 case 0x2F:
3940 case 0x30:
3941 case 0x31:
3942 case 0x32:
3943 case 0x33:
3944 case 0x34:
3945 case 0x35:
3946 case 0x36:
3947 case 0x37:
3948 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
3949
3950 case 0x38: // Negative integer (one-byte uint8_t follows)
3951 {
3952 std::uint8_t number;
3953 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
3954 }
3955
3956 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
3957 {
3958 std::uint16_t number;
3959 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
3960 }
3961
3962 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
3963 {
3964 std::uint32_t number;
3965 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
3966 }
3967
3968 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
3969 {
3970 std::uint64_t number;
3971 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
3972 - static_cast<number_integer_t>(number));
3973 }
3974
3975 // UTF-8 string (0x00..0x17 bytes follow)
3976 case 0x60:
3977 case 0x61:
3978 case 0x62:
3979 case 0x63:
3980 case 0x64:
3981 case 0x65:
3982 case 0x66:
3983 case 0x67:
3984 case 0x68:
3985 case 0x69:
3986 case 0x6A:
3987 case 0x6B:
3988 case 0x6C:
3989 case 0x6D:
3990 case 0x6E:
3991 case 0x6F:
3992 case 0x70:
3993 case 0x71:
3994 case 0x72:
3995 case 0x73:
3996 case 0x74:
3997 case 0x75:
3998 case 0x76:
3999 case 0x77:
4000 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
4001 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
4002 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
4003 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
4004 case 0x7F: // UTF-8 string (indefinite length)
4005 {
4006 string_t s;
4007 return get_cbor_string(s) and sax->string(s);
4008 }
4009
4010 // array (0x00..0x17 data items follow)
4011 case 0x80:
4012 case 0x81:
4013 case 0x82:
4014 case 0x83:
4015 case 0x84:
4016 case 0x85:
4017 case 0x86:
4018 case 0x87:
4019 case 0x88:
4020 case 0x89:
4021 case 0x8A:
4022 case 0x8B:
4023 case 0x8C:
4024 case 0x8D:
4025 case 0x8E:
4026 case 0x8F:
4027 case 0x90:
4028 case 0x91:
4029 case 0x92:
4030 case 0x93:
4031 case 0x94:
4032 case 0x95:
4033 case 0x96:
4034 case 0x97:
4035 return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
4036
4037 case 0x98: // array (one-byte uint8_t for n follows)
4038 {
4039 std::uint8_t len;
4040 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4041 }
4042
4043 case 0x99: // array (two-byte uint16_t for n follow)
4044 {
4045 std::uint16_t len;
4046 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4047 }
4048
4049 case 0x9A: // array (four-byte uint32_t for n follow)
4050 {
4051 std::uint32_t len;
4052 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4053 }
4054
4055 case 0x9B: // array (eight-byte uint64_t for n follow)
4056 {
4057 std::uint64_t len;
4058 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4059 }
4060
4061 case 0x9F: // array (indefinite length)
4062 return get_cbor_array(std::size_t(-1));
4063
4064 // map (0x00..0x17 pairs of data items follow)
4065 case 0xA0:
4066 case 0xA1:
4067 case 0xA2:
4068 case 0xA3:
4069 case 0xA4:
4070 case 0xA5:
4071 case 0xA6:
4072 case 0xA7:
4073 case 0xA8:
4074 case 0xA9:
4075 case 0xAA:
4076 case 0xAB:
4077 case 0xAC:
4078 case 0xAD:
4079 case 0xAE:
4080 case 0xAF:
4081 case 0xB0:
4082 case 0xB1:
4083 case 0xB2:
4084 case 0xB3:
4085 case 0xB4:
4086 case 0xB5:
4087 case 0xB6:
4088 case 0xB7:
4089 return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
4090
4091 case 0xB8: // map (one-byte uint8_t for n follows)
4092 {
4093 std::uint8_t len;
4094 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4095 }
4096
4097 case 0xB9: // map (two-byte uint16_t for n follow)
4098 {
4099 std::uint16_t len;
4100 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4101 }
4102
4103 case 0xBA: // map (four-byte uint32_t for n follow)
4104 {
4105 std::uint32_t len;
4106 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4107 }
4108
4109 case 0xBB: // map (eight-byte uint64_t for n follow)
4110 {
4111 std::uint64_t len;
4112 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4113 }
4114
4115 case 0xBF: // map (indefinite length)
4116 return get_cbor_object(std::size_t(-1));
4117
4118 case 0xF4: // false
4119 return sax->boolean(false);
4120
4121 case 0xF5: // true
4122 return sax->boolean(true);
4123
4124 case 0xF6: // null
4125 return sax->null();
4126
4127 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
4128 {
4129 const int byte1_raw = get();
4131 {
4132 return false;
4133 }
4134 const int byte2_raw = get();
4136 {
4137 return false;
4138 }
4139
4140 const auto byte1 = static_cast<unsigned char>(byte1_raw);
4141 const auto byte2 = static_cast<unsigned char>(byte2_raw);
4142
4143 // code from RFC 7049, Appendix D, Figure 3:
4144 // As half-precision floating-point numbers were only added
4145 // to IEEE 754 in 2008, today's programming platforms often
4146 // still only have limited support for them. It is very
4147 // easy to include at least decoding support for them even
4148 // without such support. An example of a small decoder for
4149 // half-precision floating-point numbers in the C language
4150 // is shown in Fig. 3.
4151 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
4152 const double val = [&half]
4153 {
4154 const int exp = (half >> 10u) & 0x1Fu;
4155 const unsigned int mant = half & 0x3FFu;
4156 assert(0 <= exp and exp <= 32);
4157 assert(0 <= mant and mant <= 1024);
4158 switch (exp)
4159 {
4160 case 0:
4161 return std::ldexp(mant, -24);
4162 case 31:
4163 return (mant == 0)
4164 ? std::numeric_limits<double>::infinity()
4165 : std::numeric_limits<double>::quiet_NaN();
4166 default:
4167 return std::ldexp(mant + 1024, exp - 25);
4168 }
4169 }();
4170 return sax->number_float((half & 0x8000u) != 0
4171 ? static_cast<number_float_t>(-val)
4172 : static_cast<number_float_t>(val), "");
4173 }
4174
4175 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
4176 {
4177 float number;
4178 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
4179 }
4180
4181 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
4182 {
4183 double number;
4184 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
4185 }
4186
4187 default: // anything else (0xFF is handled inside the other types)
4188 {
4189 auto last_token = get_token_string();
4190 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
4191 }
4192 }
4193 }
4194
4207 {
4209 {
4210 return false;
4211 }
4212
4213 switch (current)
4214 {
4215 // UTF-8 string (0x00..0x17 bytes follow)
4216 case 0x60:
4217 case 0x61:
4218 case 0x62:
4219 case 0x63:
4220 case 0x64:
4221 case 0x65:
4222 case 0x66:
4223 case 0x67:
4224 case 0x68:
4225 case 0x69:
4226 case 0x6A:
4227 case 0x6B:
4228 case 0x6C:
4229 case 0x6D:
4230 case 0x6E:
4231 case 0x6F:
4232 case 0x70:
4233 case 0x71:
4234 case 0x72:
4235 case 0x73:
4236 case 0x74:
4237 case 0x75:
4238 case 0x76:
4239 case 0x77:
4240 {
4241 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
4242 }
4243
4244 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
4245 {
4246 std::uint8_t len;
4247 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4248 }
4249
4250 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
4251 {
4252 std::uint16_t len;
4253 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4254 }
4255
4256 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
4257 {
4258 std::uint32_t len;
4259 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4260 }
4261
4262 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
4263 {
4264 std::uint64_t len;
4265 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4266 }
4267
4268 case 0x7F: // UTF-8 string (indefinite length)
4269 {
4270 while (get() != 0xFF)
4271 {
4272 string_t chunk;
4273 if (not get_cbor_string(chunk))
4274 {
4275 return false;
4276 }
4277 result.append(chunk);
4278 }
4279 return true;
4280 }
4281
4282 default:
4283 {
4284 auto last_token = get_token_string();
4285 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
4286 }
4287 }
4288 }
4289
4295 bool get_cbor_array(const std::size_t len)
4296 {
4297 if (JSON_UNLIKELY(not sax->start_array(len)))
4298 {
4299 return false;
4300 }
4301
4302 if (len != std::size_t(-1))
4303 {
4304 for (std::size_t i = 0; i < len; ++i)
4305 {
4307 {
4308 return false;
4309 }
4310 }
4311 }
4312 else
4313 {
4314 while (get() != 0xFF)
4315 {
4316 if (JSON_UNLIKELY(not parse_cbor_internal(false)))
4317 {
4318 return false;
4319 }
4320 }
4321 }
4322
4323 return sax->end_array();
4324 }
4325
4331 bool get_cbor_object(const std::size_t len)
4332 {
4333 if (JSON_UNLIKELY(not sax->start_object(len)))
4334 {
4335 return false;
4336 }
4337
4338 string_t key;
4339 if (len != std::size_t(-1))
4340 {
4341 for (std::size_t i = 0; i < len; ++i)
4342 {
4343 get();
4344 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
4345 {
4346 return false;
4347 }
4348
4350 {
4351 return false;
4352 }
4353 key.clear();
4354 }
4355 }
4356 else
4357 {
4358 while (get() != 0xFF)
4359 {
4360 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
4361 {
4362 return false;
4363 }
4364
4366 {
4367 return false;
4368 }
4369 key.clear();
4370 }
4371 }
4372
4373 return sax->end_object();
4374 }
4375
4377 // MsgPack //
4379
4384 {
4385 switch (get())
4386 {
4387 // EOF
4388 case std::char_traits<char>::eof():
4389 return unexpect_eof(input_format_t::msgpack, "value");
4390
4391 // positive fixint
4392 case 0x00:
4393 case 0x01:
4394 case 0x02:
4395 case 0x03:
4396 case 0x04:
4397 case 0x05:
4398 case 0x06:
4399 case 0x07:
4400 case 0x08:
4401 case 0x09:
4402 case 0x0A:
4403 case 0x0B:
4404 case 0x0C:
4405 case 0x0D:
4406 case 0x0E:
4407 case 0x0F:
4408 case 0x10:
4409 case 0x11:
4410 case 0x12:
4411 case 0x13:
4412 case 0x14:
4413 case 0x15:
4414 case 0x16:
4415 case 0x17:
4416 case 0x18:
4417 case 0x19:
4418 case 0x1A:
4419 case 0x1B:
4420 case 0x1C:
4421 case 0x1D:
4422 case 0x1E:
4423 case 0x1F:
4424 case 0x20:
4425 case 0x21:
4426 case 0x22:
4427 case 0x23:
4428 case 0x24:
4429 case 0x25:
4430 case 0x26:
4431 case 0x27:
4432 case 0x28:
4433 case 0x29:
4434 case 0x2A:
4435 case 0x2B:
4436 case 0x2C:
4437 case 0x2D:
4438 case 0x2E:
4439 case 0x2F:
4440 case 0x30:
4441 case 0x31:
4442 case 0x32:
4443 case 0x33:
4444 case 0x34:
4445 case 0x35:
4446 case 0x36:
4447 case 0x37:
4448 case 0x38:
4449 case 0x39:
4450 case 0x3A:
4451 case 0x3B:
4452 case 0x3C:
4453 case 0x3D:
4454 case 0x3E:
4455 case 0x3F:
4456 case 0x40:
4457 case 0x41:
4458 case 0x42:
4459 case 0x43:
4460 case 0x44:
4461 case 0x45:
4462 case 0x46:
4463 case 0x47:
4464 case 0x48:
4465 case 0x49:
4466 case 0x4A:
4467 case 0x4B:
4468 case 0x4C:
4469 case 0x4D:
4470 case 0x4E:
4471 case 0x4F:
4472 case 0x50:
4473 case 0x51:
4474 case 0x52:
4475 case 0x53:
4476 case 0x54:
4477 case 0x55:
4478 case 0x56:
4479 case 0x57:
4480 case 0x58:
4481 case 0x59:
4482 case 0x5A:
4483 case 0x5B:
4484 case 0x5C:
4485 case 0x5D:
4486 case 0x5E:
4487 case 0x5F:
4488 case 0x60:
4489 case 0x61:
4490 case 0x62:
4491 case 0x63:
4492 case 0x64:
4493 case 0x65:
4494 case 0x66:
4495 case 0x67:
4496 case 0x68:
4497 case 0x69:
4498 case 0x6A:
4499 case 0x6B:
4500 case 0x6C:
4501 case 0x6D:
4502 case 0x6E:
4503 case 0x6F:
4504 case 0x70:
4505 case 0x71:
4506 case 0x72:
4507 case 0x73:
4508 case 0x74:
4509 case 0x75:
4510 case 0x76:
4511 case 0x77:
4512 case 0x78:
4513 case 0x79:
4514 case 0x7A:
4515 case 0x7B:
4516 case 0x7C:
4517 case 0x7D:
4518 case 0x7E:
4519 case 0x7F:
4520 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
4521
4522 // fixmap
4523 case 0x80:
4524 case 0x81:
4525 case 0x82:
4526 case 0x83:
4527 case 0x84:
4528 case 0x85:
4529 case 0x86:
4530 case 0x87:
4531 case 0x88:
4532 case 0x89:
4533 case 0x8A:
4534 case 0x8B:
4535 case 0x8C:
4536 case 0x8D:
4537 case 0x8E:
4538 case 0x8F:
4539 return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
4540
4541 // fixarray
4542 case 0x90:
4543 case 0x91:
4544 case 0x92:
4545 case 0x93:
4546 case 0x94:
4547 case 0x95:
4548 case 0x96:
4549 case 0x97:
4550 case 0x98:
4551 case 0x99:
4552 case 0x9A:
4553 case 0x9B:
4554 case 0x9C:
4555 case 0x9D:
4556 case 0x9E:
4557 case 0x9F:
4558 return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
4559
4560 // fixstr
4561 case 0xA0:
4562 case 0xA1:
4563 case 0xA2:
4564 case 0xA3:
4565 case 0xA4:
4566 case 0xA5:
4567 case 0xA6:
4568 case 0xA7:
4569 case 0xA8:
4570 case 0xA9:
4571 case 0xAA:
4572 case 0xAB:
4573 case 0xAC:
4574 case 0xAD:
4575 case 0xAE:
4576 case 0xAF:
4577 case 0xB0:
4578 case 0xB1:
4579 case 0xB2:
4580 case 0xB3:
4581 case 0xB4:
4582 case 0xB5:
4583 case 0xB6:
4584 case 0xB7:
4585 case 0xB8:
4586 case 0xB9:
4587 case 0xBA:
4588 case 0xBB:
4589 case 0xBC:
4590 case 0xBD:
4591 case 0xBE:
4592 case 0xBF:
4593 {
4594 string_t s;
4595 return get_msgpack_string(s) and sax->string(s);
4596 }
4597
4598 case 0xC0: // nil
4599 return sax->null();
4600
4601 case 0xC2: // false
4602 return sax->boolean(false);
4603
4604 case 0xC3: // true
4605 return sax->boolean(true);
4606
4607 case 0xCA: // float 32
4608 {
4609 float number;
4610 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
4611 }
4612
4613 case 0xCB: // float 64
4614 {
4615 double number;
4616 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
4617 }
4618
4619 case 0xCC: // uint 8
4620 {
4621 std::uint8_t number;
4622 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4623 }
4624
4625 case 0xCD: // uint 16
4626 {
4627 std::uint16_t number;
4628 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4629 }
4630
4631 case 0xCE: // uint 32
4632 {
4633 std::uint32_t number;
4634 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4635 }
4636
4637 case 0xCF: // uint 64
4638 {
4639 std::uint64_t number;
4640 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4641 }
4642
4643 case 0xD0: // int 8
4644 {
4645 std::int8_t number;
4646 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4647 }
4648
4649 case 0xD1: // int 16
4650 {
4651 std::int16_t number;
4652 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4653 }
4654
4655 case 0xD2: // int 32
4656 {
4657 std::int32_t number;
4658 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4659 }
4660
4661 case 0xD3: // int 64
4662 {
4663 std::int64_t number;
4664 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4665 }
4666
4667 case 0xD9: // str 8
4668 case 0xDA: // str 16
4669 case 0xDB: // str 32
4670 {
4671 string_t s;
4672 return get_msgpack_string(s) and sax->string(s);
4673 }
4674
4675 case 0xDC: // array 16
4676 {
4677 std::uint16_t len;
4678 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
4679 }
4680
4681 case 0xDD: // array 32
4682 {
4683 std::uint32_t len;
4684 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
4685 }
4686
4687 case 0xDE: // map 16
4688 {
4689 std::uint16_t len;
4690 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
4691 }
4692
4693 case 0xDF: // map 32
4694 {
4695 std::uint32_t len;
4696 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
4697 }
4698
4699 // negative fixint
4700 case 0xE0:
4701 case 0xE1:
4702 case 0xE2:
4703 case 0xE3:
4704 case 0xE4:
4705 case 0xE5:
4706 case 0xE6:
4707 case 0xE7:
4708 case 0xE8:
4709 case 0xE9:
4710 case 0xEA:
4711 case 0xEB:
4712 case 0xEC:
4713 case 0xED:
4714 case 0xEE:
4715 case 0xEF:
4716 case 0xF0:
4717 case 0xF1:
4718 case 0xF2:
4719 case 0xF3:
4720 case 0xF4:
4721 case 0xF5:
4722 case 0xF6:
4723 case 0xF7:
4724 case 0xF8:
4725 case 0xF9:
4726 case 0xFA:
4727 case 0xFB:
4728 case 0xFC:
4729 case 0xFD:
4730 case 0xFE:
4731 case 0xFF:
4732 return sax->number_integer(static_cast<std::int8_t>(current));
4733
4734 default: // anything else
4735 {
4736 auto last_token = get_token_string();
4737 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
4738 }
4739 }
4740 }
4741
4753 {
4755 {
4756 return false;
4757 }
4758
4759 switch (current)
4760 {
4761 // fixstr
4762 case 0xA0:
4763 case 0xA1:
4764 case 0xA2:
4765 case 0xA3:
4766 case 0xA4:
4767 case 0xA5:
4768 case 0xA6:
4769 case 0xA7:
4770 case 0xA8:
4771 case 0xA9:
4772 case 0xAA:
4773 case 0xAB:
4774 case 0xAC:
4775 case 0xAD:
4776 case 0xAE:
4777 case 0xAF:
4778 case 0xB0:
4779 case 0xB1:
4780 case 0xB2:
4781 case 0xB3:
4782 case 0xB4:
4783 case 0xB5:
4784 case 0xB6:
4785 case 0xB7:
4786 case 0xB8:
4787 case 0xB9:
4788 case 0xBA:
4789 case 0xBB:
4790 case 0xBC:
4791 case 0xBD:
4792 case 0xBE:
4793 case 0xBF:
4794 {
4795 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
4796 }
4797
4798 case 0xD9: // str 8
4799 {
4800 std::uint8_t len;
4802 }
4803
4804 case 0xDA: // str 16
4805 {
4806 std::uint16_t len;
4808 }
4809
4810 case 0xDB: // str 32
4811 {
4812 std::uint32_t len;
4814 }
4815
4816 default:
4817 {
4818 auto last_token = get_token_string();
4819 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
4820 }
4821 }
4822 }
4823
4828 bool get_msgpack_array(const std::size_t len)
4829 {
4830 if (JSON_UNLIKELY(not sax->start_array(len)))
4831 {
4832 return false;
4833 }
4834
4835 for (std::size_t i = 0; i < len; ++i)
4836 {
4838 {
4839 return false;
4840 }
4841 }
4842
4843 return sax->end_array();
4844 }
4845
4850 bool get_msgpack_object(const std::size_t len)
4851 {
4852 if (JSON_UNLIKELY(not sax->start_object(len)))
4853 {
4854 return false;
4855 }
4856
4857 string_t key;
4858 for (std::size_t i = 0; i < len; ++i)
4859 {
4860 get();
4861 if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
4862 {
4863 return false;
4864 }
4865
4867 {
4868 return false;
4869 }
4870 key.clear();
4871 }
4872
4873 return sax->end_object();
4874 }
4875
4877 // UBJSON //
4879
4887 bool parse_ubjson_internal(const bool get_char = true)
4888 {
4889 return get_ubjson_value(get_char ? get_ignore_noop() : current);
4890 }
4891
4906 bool get_ubjson_string(string_t& result, const bool get_char = true)
4907 {
4908 if (get_char)
4909 {
4910 get(); // TODO(niels): may we ignore N here?
4911 }
4912
4914 {
4915 return false;
4916 }
4917
4918 switch (current)
4919 {
4920 case 'U':
4921 {
4922 std::uint8_t len;
4924 }
4925
4926 case 'i':
4927 {
4928 std::int8_t len;
4930 }
4931
4932 case 'I':
4933 {
4934 std::int16_t len;
4936 }
4937
4938 case 'l':
4939 {
4940 std::int32_t len;
4942 }
4943
4944 case 'L':
4945 {
4946 std::int64_t len;
4948 }
4949
4950 default:
4951 auto last_token = get_token_string();
4952 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
4953 }
4954 }
4955
4960 bool get_ubjson_size_value(std::size_t& result)
4961 {
4962 switch (get_ignore_noop())
4963 {
4964 case 'U':
4965 {
4966 std::uint8_t number;
4968 {
4969 return false;
4970 }
4971 result = static_cast<std::size_t>(number);
4972 return true;
4973 }
4974
4975 case 'i':
4976 {
4977 std::int8_t number;
4979 {
4980 return false;
4981 }
4982 result = static_cast<std::size_t>(number);
4983 return true;
4984 }
4985
4986 case 'I':
4987 {
4988 std::int16_t number;
4990 {
4991 return false;
4992 }
4993 result = static_cast<std::size_t>(number);
4994 return true;
4995 }
4996
4997 case 'l':
4998 {
4999 std::int32_t number;
5001 {
5002 return false;
5003 }
5004 result = static_cast<std::size_t>(number);
5005 return true;
5006 }
5007
5008 case 'L':
5009 {
5010 std::int64_t number;
5012 {
5013 return false;
5014 }
5015 result = static_cast<std::size_t>(number);
5016 return true;
5017 }
5018
5019 default:
5020 {
5021 auto last_token = get_token_string();
5022 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
5023 }
5024 }
5025 }
5026
5037 bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
5038 {
5039 result.first = string_t::npos; // size
5040 result.second = 0; // type
5041
5043
5044 if (current == '$')
5045 {
5046 result.second = get(); // must not ignore 'N', because 'N' maybe the type
5048 {
5049 return false;
5050 }
5051
5053 if (JSON_UNLIKELY(current != '#'))
5054 {
5056 {
5057 return false;
5058 }
5059 auto last_token = get_token_string();
5060 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
5061 }
5062
5063 return get_ubjson_size_value(result.first);
5064 }
5065
5066 if (current == '#')
5067 {
5068 return get_ubjson_size_value(result.first);
5069 }
5070
5071 return true;
5072 }
5073
5078 bool get_ubjson_value(const int prefix)
5079 {
5080 switch (prefix)
5081 {
5082 case std::char_traits<char>::eof(): // EOF
5083 return unexpect_eof(input_format_t::ubjson, "value");
5084
5085 case 'T': // true
5086 return sax->boolean(true);
5087 case 'F': // false
5088 return sax->boolean(false);
5089
5090 case 'Z': // null
5091 return sax->null();
5092
5093 case 'U':
5094 {
5095 std::uint8_t number;
5096 return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
5097 }
5098
5099 case 'i':
5100 {
5101 std::int8_t number;
5102 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5103 }
5104
5105 case 'I':
5106 {
5107 std::int16_t number;
5108 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5109 }
5110
5111 case 'l':
5112 {
5113 std::int32_t number;
5114 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5115 }
5116
5117 case 'L':
5118 {
5119 std::int64_t number;
5120 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5121 }
5122
5123 case 'd':
5124 {
5125 float number;
5126 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
5127 }
5128
5129 case 'D':
5130 {
5131 double number;
5132 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
5133 }
5134
5135 case 'C': // char
5136 {
5137 get();
5139 {
5140 return false;
5141 }
5142 if (JSON_UNLIKELY(current > 127))
5143 {
5144 auto last_token = get_token_string();
5145 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
5146 }
5147 string_t s(1, static_cast<char>(current));
5148 return sax->string(s);
5149 }
5150
5151 case 'S': // string
5152 {
5153 string_t s;
5154 return get_ubjson_string(s) and sax->string(s);
5155 }
5156
5157 case '[': // array
5158 return get_ubjson_array();
5159
5160 case '{': // object
5161 return get_ubjson_object();
5162
5163 default: // anything else
5164 {
5165 auto last_token = get_token_string();
5166 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
5167 }
5168 }
5169 }
5170
5175 {
5176 std::pair<std::size_t, int> size_and_type;
5177 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
5178 {
5179 return false;
5180 }
5181
5182 if (size_and_type.first != string_t::npos)
5183 {
5184 if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
5185 {
5186 return false;
5187 }
5188
5189 if (size_and_type.second != 0)
5190 {
5191 if (size_and_type.second != 'N')
5192 {
5193 for (std::size_t i = 0; i < size_and_type.first; ++i)
5194 {
5195 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
5196 {
5197 return false;
5198 }
5199 }
5200 }
5201 }
5202 else
5203 {
5204 for (std::size_t i = 0; i < size_and_type.first; ++i)
5205 {
5207 {
5208 return false;
5209 }
5210 }
5211 }
5212 }
5213 else
5214 {
5215 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
5216 {
5217 return false;
5218 }
5219
5220 while (current != ']')
5221 {
5222 if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
5223 {
5224 return false;
5225 }
5227 }
5228 }
5229
5230 return sax->end_array();
5231 }
5232
5237 {
5238 std::pair<std::size_t, int> size_and_type;
5239 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
5240 {
5241 return false;
5242 }
5243
5244 string_t key;
5245 if (size_and_type.first != string_t::npos)
5246 {
5247 if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
5248 {
5249 return false;
5250 }
5251
5252 if (size_and_type.second != 0)
5253 {
5254 for (std::size_t i = 0; i < size_and_type.first; ++i)
5255 {
5256 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
5257 {
5258 return false;
5259 }
5260 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
5261 {
5262 return false;
5263 }
5264 key.clear();
5265 }
5266 }
5267 else
5268 {
5269 for (std::size_t i = 0; i < size_and_type.first; ++i)
5270 {
5271 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
5272 {
5273 return false;
5274 }
5276 {
5277 return false;
5278 }
5279 key.clear();
5280 }
5281 }
5282 }
5283 else
5284 {
5285 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
5286 {
5287 return false;
5288 }
5289
5290 while (current != '}')
5291 {
5292 if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
5293 {
5294 return false;
5295 }
5297 {
5298 return false;
5299 }
5301 key.clear();
5302 }
5303 }
5304
5305 return sax->end_object();
5306 }
5307
5309 // Utility functions //
5311
5321 int get()
5322 {
5323 ++chars_read;
5324 return current = ia->get_character();
5325 }
5326
5331 {
5332 do
5333 {
5334 get();
5335 }
5336 while (current == 'N');
5337
5338 return current;
5339 }
5340
5341 /*
5342 @brief read a number from the input
5343
5344 @tparam NumberType the type of the number
5345 @param[in] format the current format (for diagnostics)
5346 @param[out] result number of type @a NumberType
5347
5348 @return whether conversion completed
5349
5350 @note This function needs to respect the system's endianess, because
5351 bytes in CBOR, MessagePack, and UBJSON are stored in network order
5352 (big endian) and therefore need reordering on little endian systems.
5353 */
5354 template<typename NumberType, bool InputIsLittleEndian = false>
5355 bool get_number(const input_format_t format, NumberType& result)
5356 {
5357 // step 1: read input into array with system's byte order
5358 std::array<std::uint8_t, sizeof(NumberType)> vec;
5359 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
5360 {
5361 get();
5362 if (JSON_UNLIKELY(not unexpect_eof(format, "number")))
5363 {
5364 return false;
5365 }
5366
5367 // reverse byte order prior to conversion if necessary
5368 if (is_little_endian != InputIsLittleEndian)
5369 {
5370 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
5371 }
5372 else
5373 {
5374 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
5375 }
5376 }
5377
5378 // step 2: convert array into number of type T and return
5379 std::memcpy(&result, vec.data(), sizeof(NumberType));
5380 return true;
5381 }
5382
5397 template<typename NumberType>
5398 bool get_string(const input_format_t format,
5399 const NumberType len,
5400 string_t& result)
5401 {
5402 bool success = true;
5403 std::generate_n(std::back_inserter(result), len, [this, &success, &format]()
5404 {
5405 get();
5406 if (JSON_UNLIKELY(not unexpect_eof(format, "string")))
5407 {
5408 success = false;
5409 }
5410 return static_cast<char>(current);
5411 });
5412 return success;
5413 }
5414
5420 bool unexpect_eof(const input_format_t format, const char* context) const
5421 {
5422 if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
5423 {
5424 return sax->parse_error(chars_read, "<end of file>",
5425 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
5426 }
5427 return true;
5428 }
5429
5433 std::string get_token_string() const
5434 {
5435 std::array<char, 3> cr{{}};
5436 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
5437 return std::string{cr.data()};
5438 }
5439
5446 std::string exception_message(const input_format_t format,
5447 const std::string& detail,
5448 const std::string& context) const
5449 {
5450 std::string error_msg = "syntax error while parsing ";
5451
5452 switch (format)
5453 {
5455 error_msg += "CBOR";
5456 break;
5457
5459 error_msg += "MessagePack";
5460 break;
5461
5463 error_msg += "UBJSON";
5464 break;
5465
5467 error_msg += "BSON";
5468 break;
5469
5470 default: // LCOV_EXCL_LINE
5471 assert(false); // LCOV_EXCL_LINE
5472 }
5473
5474 return error_msg + " " + context + ": " + detail;
5475 }
5476
5477 private:
5480
5482 int current = std::char_traits<char>::eof();
5483
5485 std::size_t chars_read = 0;
5486
5489
5491 json_sax_t* sax = nullptr;
5492 };
5493 } // namespace detail
5494} // namespace nlohmann
5495
5496// #include <nlohmann/detail/input/input_adapters.hpp>
5497
5498// #include <nlohmann/detail/input/lexer.hpp>
5499
5500
5501#include <array> // array
5502#include <clocale> // localeconv
5503#include <cstddef> // size_t
5504#include <cstdio> // snprintf
5505#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
5506#include <initializer_list> // initializer_list
5507#include <string> // char_traits, string
5508#include <utility> // move
5509#include <vector> // vector
5510
5511// #include <nlohmann/detail/input/input_adapters.hpp>
5512
5513// #include <nlohmann/detail/input/position_t.hpp>
5514
5515// #include <nlohmann/detail/macro_scope.hpp>
5516
5517
5518namespace nlohmann
5519{
5520 namespace detail
5521 {
5523// lexer //
5525
5531 template<typename BasicJsonType>
5532 class lexer
5533 {
5534 using number_integer_t = typename BasicJsonType::number_integer_t;
5535 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5536 using number_float_t = typename BasicJsonType::number_float_t;
5537 using string_t = typename BasicJsonType::string_t;
5538
5539 public:
5541 enum class token_type
5542 {
5543 uninitialized,
5544 literal_true,
5545 literal_false,
5546 literal_null,
5547 value_string,
5550 value_float,
5551 begin_array,
5552 begin_object,
5553 end_array,
5554 end_object,
5555 name_separator,
5556 value_separator,
5557 parse_error,
5558 end_of_input,
5559 literal_or_value
5560 };
5561
5563 static const char* token_type_name(const token_type t) noexcept
5564 {
5565 switch (t)
5566 {
5568 return "<uninitialized>";
5570 return "true literal";
5572 return "false literal";
5574 return "null literal";
5576 return "string literal";
5580 return "number literal";
5582 return "'['";
5584 return "'{'";
5586 return "']'";
5588 return "'}'";
5590 return "':'";
5592 return "','";
5594 return "<parse error>";
5596 return "end of input";
5598 return "'[', '{', or a literal";
5599 // LCOV_EXCL_START
5600 default: // catch non-enum values
5601 return "unknown token";
5602 // LCOV_EXCL_STOP
5603 }
5604 }
5605
5606 explicit lexer(detail::input_adapter_t&& adapter)
5607 : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
5608
5609 // delete because of pointer members
5610 lexer(const lexer&) = delete;
5611 lexer(lexer&&) = delete;
5612 lexer& operator=(lexer&) = delete;
5613 lexer& operator=(lexer&&) = delete;
5614 ~lexer() = default;
5615
5616 private:
5618 // locales
5620
5622 static char get_decimal_point() noexcept
5623 {
5624 const auto loc = localeconv();
5625 assert(loc != nullptr);
5626 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
5627 }
5628
5630 // scan functions
5632
5649 {
5650 // this function only makes sense after reading `\u`
5651 assert(current == 'u');
5652 int codepoint = 0;
5653
5654 const auto factors = { 12u, 8u, 4u, 0u };
5655 for (const auto factor : factors)
5656 {
5657 get();
5658
5659 if (current >= '0' and current <= '9')
5660 {
5661 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
5662 }
5663 else if (current >= 'A' and current <= 'F')
5664 {
5665 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
5666 }
5667 else if (current >= 'a' and current <= 'f')
5668 {
5669 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
5670 }
5671 else
5672 {
5673 return -1;
5674 }
5675 }
5676
5677 assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
5678 return codepoint;
5679 }
5680
5696 bool next_byte_in_range(std::initializer_list<int> ranges)
5697 {
5698 assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
5699 add(current);
5700
5701 for (auto range = ranges.begin(); range != ranges.end(); ++range)
5702 {
5703 get();
5704 if (JSON_LIKELY(*range <= current and current <= *(++range)))
5705 {
5706 add(current);
5707 }
5708 else
5709 {
5710 error_message = "invalid string: ill-formed UTF-8 byte";
5711 return false;
5712 }
5713 }
5714
5715 return true;
5716 }
5717
5734 {
5735 // reset token_buffer (ignore opening quote)
5736 reset();
5737
5738 // we entered the function by reading an open quote
5739 assert(current == '\"');
5740
5741 while (true)
5742 {
5743 // get next character
5744 switch (get())
5745 {
5746 // end of file while parsing string
5747 case std::char_traits<char>::eof():
5748 {
5749 error_message = "invalid string: missing closing quote";
5751 }
5752
5753 // closing quote
5754 case '\"':
5755 {
5757 }
5758
5759 // escapes
5760 case '\\':
5761 {
5762 switch (get())
5763 {
5764 // quotation mark
5765 case '\"':
5766 add('\"');
5767 break;
5768 // reverse solidus
5769 case '\\':
5770 add('\\');
5771 break;
5772 // solidus
5773 case '/':
5774 add('/');
5775 break;
5776 // backspace
5777 case 'b':
5778 add('\b');
5779 break;
5780 // form feed
5781 case 'f':
5782 add('\f');
5783 break;
5784 // line feed
5785 case 'n':
5786 add('\n');
5787 break;
5788 // carriage return
5789 case 'r':
5790 add('\r');
5791 break;
5792 // tab
5793 case 't':
5794 add('\t');
5795 break;
5796
5797 // unicode escapes
5798 case 'u':
5799 {
5800 const int codepoint1 = get_codepoint();
5801 int codepoint = codepoint1; // start with codepoint1
5802
5803 if (JSON_UNLIKELY(codepoint1 == -1))
5804 {
5805 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
5807 }
5808
5809 // check if code point is a high surrogate
5810 if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
5811 {
5812 // expect next \uxxxx entry
5813 if (JSON_LIKELY(get() == '\\' and get() == 'u'))
5814 {
5815 const int codepoint2 = get_codepoint();
5816
5817 if (JSON_UNLIKELY(codepoint2 == -1))
5818 {
5819 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
5821 }
5822
5823 // check if codepoint2 is a low surrogate
5824 if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
5825 {
5826 // overwrite codepoint
5827 codepoint = static_cast<int>(
5828 // high surrogate occupies the most significant 22 bits
5829 (static_cast<unsigned int>(codepoint1) << 10u)
5830 // low surrogate occupies the least significant 15 bits
5831 + static_cast<unsigned int>(codepoint2)
5832 // there is still the 0xD800, 0xDC00 and 0x10000 noise
5833 // in the result so we have to subtract with:
5834 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
5835 - 0x35FDC00u);
5836 }
5837 else
5838 {
5839 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
5841 }
5842 }
5843 else
5844 {
5845 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
5847 }
5848 }
5849 else
5850 {
5851 if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
5852 {
5853 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
5855 }
5856 }
5857
5858 // result of the above calculation yields a proper codepoint
5859 assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
5860
5861 // translate codepoint into bytes
5862 if (codepoint < 0x80)
5863 {
5864 // 1-byte characters: 0xxxxxxx (ASCII)
5865 add(codepoint);
5866 }
5867 else if (codepoint <= 0x7FF)
5868 {
5869 // 2-byte characters: 110xxxxx 10xxxxxx
5870 add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
5871 add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
5872 }
5873 else if (codepoint <= 0xFFFF)
5874 {
5875 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
5876 add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
5877 add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
5878 add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
5879 }
5880 else
5881 {
5882 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5883 add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
5884 add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
5885 add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
5886 add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
5887 }
5888
5889 break;
5890 }
5891
5892 // other characters after escape
5893 default:
5894 error_message = "invalid string: forbidden character after backslash";
5896 }
5897
5898 break;
5899 }
5900
5901 // invalid control characters
5902 case 0x00:
5903 {
5904 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
5906 }
5907
5908 case 0x01:
5909 {
5910 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
5912 }
5913
5914 case 0x02:
5915 {
5916 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
5918 }
5919
5920 case 0x03:
5921 {
5922 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
5924 }
5925
5926 case 0x04:
5927 {
5928 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
5930 }
5931
5932 case 0x05:
5933 {
5934 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
5936 }
5937
5938 case 0x06:
5939 {
5940 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
5942 }
5943
5944 case 0x07:
5945 {
5946 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
5948 }
5949
5950 case 0x08:
5951 {
5952 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
5954 }
5955
5956 case 0x09:
5957 {
5958 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
5960 }
5961
5962 case 0x0A:
5963 {
5964 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
5966 }
5967
5968 case 0x0B:
5969 {
5970 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
5972 }
5973
5974 case 0x0C:
5975 {
5976 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
5978 }
5979
5980 case 0x0D:
5981 {
5982 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
5984 }
5985
5986 case 0x0E:
5987 {
5988 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
5990 }
5991
5992 case 0x0F:
5993 {
5994 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
5996 }
5997
5998 case 0x10:
5999 {
6000 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6002 }
6003
6004 case 0x11:
6005 {
6006 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6008 }
6009
6010 case 0x12:
6011 {
6012 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6014 }
6015
6016 case 0x13:
6017 {
6018 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6020 }
6021
6022 case 0x14:
6023 {
6024 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6026 }
6027
6028 case 0x15:
6029 {
6030 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6032 }
6033
6034 case 0x16:
6035 {
6036 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6038 }
6039
6040 case 0x17:
6041 {
6042 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6044 }
6045
6046 case 0x18:
6047 {
6048 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6050 }
6051
6052 case 0x19:
6053 {
6054 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6056 }
6057
6058 case 0x1A:
6059 {
6060 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6062 }
6063
6064 case 0x1B:
6065 {
6066 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6068 }
6069
6070 case 0x1C:
6071 {
6072 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6074 }
6075
6076 case 0x1D:
6077 {
6078 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
6080 }
6081
6082 case 0x1E:
6083 {
6084 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
6086 }
6087
6088 case 0x1F:
6089 {
6090 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
6092 }
6093
6094 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
6095 case 0x20:
6096 case 0x21:
6097 case 0x23:
6098 case 0x24:
6099 case 0x25:
6100 case 0x26:
6101 case 0x27:
6102 case 0x28:
6103 case 0x29:
6104 case 0x2A:
6105 case 0x2B:
6106 case 0x2C:
6107 case 0x2D:
6108 case 0x2E:
6109 case 0x2F:
6110 case 0x30:
6111 case 0x31:
6112 case 0x32:
6113 case 0x33:
6114 case 0x34:
6115 case 0x35:
6116 case 0x36:
6117 case 0x37:
6118 case 0x38:
6119 case 0x39:
6120 case 0x3A:
6121 case 0x3B:
6122 case 0x3C:
6123 case 0x3D:
6124 case 0x3E:
6125 case 0x3F:
6126 case 0x40:
6127 case 0x41:
6128 case 0x42:
6129 case 0x43:
6130 case 0x44:
6131 case 0x45:
6132 case 0x46:
6133 case 0x47:
6134 case 0x48:
6135 case 0x49:
6136 case 0x4A:
6137 case 0x4B:
6138 case 0x4C:
6139 case 0x4D:
6140 case 0x4E:
6141 case 0x4F:
6142 case 0x50:
6143 case 0x51:
6144 case 0x52:
6145 case 0x53:
6146 case 0x54:
6147 case 0x55:
6148 case 0x56:
6149 case 0x57:
6150 case 0x58:
6151 case 0x59:
6152 case 0x5A:
6153 case 0x5B:
6154 case 0x5D:
6155 case 0x5E:
6156 case 0x5F:
6157 case 0x60:
6158 case 0x61:
6159 case 0x62:
6160 case 0x63:
6161 case 0x64:
6162 case 0x65:
6163 case 0x66:
6164 case 0x67:
6165 case 0x68:
6166 case 0x69:
6167 case 0x6A:
6168 case 0x6B:
6169 case 0x6C:
6170 case 0x6D:
6171 case 0x6E:
6172 case 0x6F:
6173 case 0x70:
6174 case 0x71:
6175 case 0x72:
6176 case 0x73:
6177 case 0x74:
6178 case 0x75:
6179 case 0x76:
6180 case 0x77:
6181 case 0x78:
6182 case 0x79:
6183 case 0x7A:
6184 case 0x7B:
6185 case 0x7C:
6186 case 0x7D:
6187 case 0x7E:
6188 case 0x7F:
6189 {
6190 add(current);
6191 break;
6192 }
6193
6194 // U+0080..U+07FF: bytes C2..DF 80..BF
6195 case 0xC2:
6196 case 0xC3:
6197 case 0xC4:
6198 case 0xC5:
6199 case 0xC6:
6200 case 0xC7:
6201 case 0xC8:
6202 case 0xC9:
6203 case 0xCA:
6204 case 0xCB:
6205 case 0xCC:
6206 case 0xCD:
6207 case 0xCE:
6208 case 0xCF:
6209 case 0xD0:
6210 case 0xD1:
6211 case 0xD2:
6212 case 0xD3:
6213 case 0xD4:
6214 case 0xD5:
6215 case 0xD6:
6216 case 0xD7:
6217 case 0xD8:
6218 case 0xD9:
6219 case 0xDA:
6220 case 0xDB:
6221 case 0xDC:
6222 case 0xDD:
6223 case 0xDE:
6224 case 0xDF:
6225 {
6226 if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
6227 {
6229 }
6230 break;
6231 }
6232
6233 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
6234 case 0xE0:
6235 {
6236 if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
6237 {
6239 }
6240 break;
6241 }
6242
6243 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
6244 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
6245 case 0xE1:
6246 case 0xE2:
6247 case 0xE3:
6248 case 0xE4:
6249 case 0xE5:
6250 case 0xE6:
6251 case 0xE7:
6252 case 0xE8:
6253 case 0xE9:
6254 case 0xEA:
6255 case 0xEB:
6256 case 0xEC:
6257 case 0xEE:
6258 case 0xEF:
6259 {
6260 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
6261 {
6263 }
6264 break;
6265 }
6266
6267 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
6268 case 0xED:
6269 {
6270 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
6271 {
6273 }
6274 break;
6275 }
6276
6277 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
6278 case 0xF0:
6279 {
6280 if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6281 {
6283 }
6284 break;
6285 }
6286
6287 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
6288 case 0xF1:
6289 case 0xF2:
6290 case 0xF3:
6291 {
6292 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6293 {
6295 }
6296 break;
6297 }
6298
6299 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
6300 case 0xF4:
6301 {
6302 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
6303 {
6305 }
6306 break;
6307 }
6308
6309 // remaining bytes (80..C1 and F5..FF) are ill-formed
6310 default:
6311 {
6312 error_message = "invalid string: ill-formed UTF-8 byte";
6314 }
6315 }
6316 }
6317 }
6318
6319 static void strtof(float& f, const char* str, char** endptr) noexcept
6320 {
6321 f = std::strtof(str, endptr);
6322 }
6323
6324 static void strtof(double& f, const char* str, char** endptr) noexcept
6325 {
6326 f = std::strtod(str, endptr);
6327 }
6328
6329 static void strtof(long double& f, const char* str, char** endptr) noexcept
6330 {
6331 f = std::strtold(str, endptr);
6332 }
6333
6374 token_type scan_number() // lgtm [cpp/use-of-goto]
6375 {
6376 // reset token_buffer to store the number's bytes
6377 reset();
6378
6379 // the type of the parsed number; initially set to unsigned; will be
6380 // changed if minus sign, decimal point or exponent is read
6382
6383 // state (init): we just found out we need to scan a number
6384 switch (current)
6385 {
6386 case '-':
6387 {
6388 add(current);
6389 goto scan_number_minus;
6390 }
6391
6392 case '0':
6393 {
6394 add(current);
6395 goto scan_number_zero;
6396 }
6397
6398 case '1':
6399 case '2':
6400 case '3':
6401 case '4':
6402 case '5':
6403 case '6':
6404 case '7':
6405 case '8':
6406 case '9':
6407 {
6408 add(current);
6409 goto scan_number_any1;
6410 }
6411
6412 // all other characters are rejected outside scan_number()
6413 default: // LCOV_EXCL_LINE
6414 assert(false); // LCOV_EXCL_LINE
6415 }
6416
6417 scan_number_minus:
6418 // state: we just parsed a leading minus sign
6419 number_type = token_type::value_integer;
6420 switch (get())
6421 {
6422 case '0':
6423 {
6424 add(current);
6425 goto scan_number_zero;
6426 }
6427
6428 case '1':
6429 case '2':
6430 case '3':
6431 case '4':
6432 case '5':
6433 case '6':
6434 case '7':
6435 case '8':
6436 case '9':
6437 {
6438 add(current);
6439 goto scan_number_any1;
6440 }
6441
6442 default:
6443 {
6444 error_message = "invalid number; expected digit after '-'";
6446 }
6447 }
6448
6449 scan_number_zero:
6450 // state: we just parse a zero (maybe with a leading minus sign)
6451 switch (get())
6452 {
6453 case '.':
6454 {
6456 goto scan_number_decimal1;
6457 }
6458
6459 case 'e':
6460 case 'E':
6461 {
6462 add(current);
6463 goto scan_number_exponent;
6464 }
6465
6466 default:
6467 goto scan_number_done;
6468 }
6469
6470 scan_number_any1:
6471 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
6472 switch (get())
6473 {
6474 case '0':
6475 case '1':
6476 case '2':
6477 case '3':
6478 case '4':
6479 case '5':
6480 case '6':
6481 case '7':
6482 case '8':
6483 case '9':
6484 {
6485 add(current);
6486 goto scan_number_any1;
6487 }
6488
6489 case '.':
6490 {
6492 goto scan_number_decimal1;
6493 }
6494
6495 case 'e':
6496 case 'E':
6497 {
6498 add(current);
6499 goto scan_number_exponent;
6500 }
6501
6502 default:
6503 goto scan_number_done;
6504 }
6505
6506 scan_number_decimal1:
6507 // state: we just parsed a decimal point
6508 number_type = token_type::value_float;
6509 switch (get())
6510 {
6511 case '0':
6512 case '1':
6513 case '2':
6514 case '3':
6515 case '4':
6516 case '5':
6517 case '6':
6518 case '7':
6519 case '8':
6520 case '9':
6521 {
6522 add(current);
6523 goto scan_number_decimal2;
6524 }
6525
6526 default:
6527 {
6528 error_message = "invalid number; expected digit after '.'";
6530 }
6531 }
6532
6533 scan_number_decimal2:
6534 // we just parsed at least one number after a decimal point
6535 switch (get())
6536 {
6537 case '0':
6538 case '1':
6539 case '2':
6540 case '3':
6541 case '4':
6542 case '5':
6543 case '6':
6544 case '7':
6545 case '8':
6546 case '9':
6547 {
6548 add(current);
6549 goto scan_number_decimal2;
6550 }
6551
6552 case 'e':
6553 case 'E':
6554 {
6555 add(current);
6556 goto scan_number_exponent;
6557 }
6558
6559 default:
6560 goto scan_number_done;
6561 }
6562
6563 scan_number_exponent:
6564 // we just parsed an exponent
6565 number_type = token_type::value_float;
6566 switch (get())
6567 {
6568 case '+':
6569 case '-':
6570 {
6571 add(current);
6572 goto scan_number_sign;
6573 }
6574
6575 case '0':
6576 case '1':
6577 case '2':
6578 case '3':
6579 case '4':
6580 case '5':
6581 case '6':
6582 case '7':
6583 case '8':
6584 case '9':
6585 {
6586 add(current);
6587 goto scan_number_any2;
6588 }
6589
6590 default:
6591 {
6593 "invalid number; expected '+', '-', or digit after exponent";
6595 }
6596 }
6597
6598 scan_number_sign:
6599 // we just parsed an exponent sign
6600 switch (get())
6601 {
6602 case '0':
6603 case '1':
6604 case '2':
6605 case '3':
6606 case '4':
6607 case '5':
6608 case '6':
6609 case '7':
6610 case '8':
6611 case '9':
6612 {
6613 add(current);
6614 goto scan_number_any2;
6615 }
6616
6617 default:
6618 {
6619 error_message = "invalid number; expected digit after exponent sign";
6621 }
6622 }
6623
6624 scan_number_any2:
6625 // we just parsed a number after the exponent or exponent sign
6626 switch (get())
6627 {
6628 case '0':
6629 case '1':
6630 case '2':
6631 case '3':
6632 case '4':
6633 case '5':
6634 case '6':
6635 case '7':
6636 case '8':
6637 case '9':
6638 {
6639 add(current);
6640 goto scan_number_any2;
6641 }
6642
6643 default:
6644 goto scan_number_done;
6645 }
6646
6647 scan_number_done:
6648 // unget the character after the number (we only read it to know that
6649 // we are done scanning a number)
6650 unget();
6651
6652 char* endptr = nullptr;
6653 errno = 0;
6654
6655 // try to parse integers first and fall back to floats
6656 if (number_type == token_type::value_unsigned)
6657 {
6658 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
6659
6660 // we checked the number format before
6661 assert(endptr == token_buffer.data() + token_buffer.size());
6662
6663 if (errno == 0)
6664 {
6665 value_unsigned = static_cast<number_unsigned_t>(x);
6666 if (value_unsigned == x)
6667 {
6669 }
6670 }
6671 }
6672 else if (number_type == token_type::value_integer)
6673 {
6674 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
6675
6676 // we checked the number format before
6677 assert(endptr == token_buffer.data() + token_buffer.size());
6678
6679 if (errno == 0)
6680 {
6681 value_integer = static_cast<number_integer_t>(x);
6682 if (value_integer == x)
6683 {
6685 }
6686 }
6687 }
6688
6689 // this code is reached if we parse a floating-point number or if an
6690 // integer conversion above failed
6691 strtof(value_float, token_buffer.data(), &endptr);
6692
6693 // we checked the number format before
6694 assert(endptr == token_buffer.data() + token_buffer.size());
6695
6697 }
6698
6704 token_type scan_literal(const char* literal_text, const std::size_t length,
6705 token_type return_type)
6706 {
6707 assert(current == literal_text[0]);
6708 for (std::size_t i = 1; i < length; ++i)
6709 {
6710 if (JSON_UNLIKELY(get() != literal_text[i]))
6711 {
6712 error_message = "invalid literal";
6714 }
6715 }
6716 return return_type;
6717 }
6718
6720 // input management
6722
6724 void reset() noexcept
6725 {
6726 token_buffer.clear();
6728 token_string.push_back(std::char_traits<char>::to_char_type(current));
6729 }
6730
6731 /*
6732 @brief get next character from the input
6733
6734 This function provides the interface to the used input adapter. It does
6735 not throw in case the input reached EOF, but returns a
6736 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
6737 for use in error messages.
6738
6739 @return character read from the input
6740 */
6741 std::char_traits<char>::int_type get()
6742 {
6745
6746 if (next_unget)
6747 {
6748 // just reset the next_unget variable and work with current
6749 next_unget = false;
6750 }
6751 else
6752 {
6753 current = ia->get_character();
6754 }
6755
6756 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
6757 {
6758 token_string.push_back(std::char_traits<char>::to_char_type(current));
6759 }
6760
6761 if (current == '\n')
6762 {
6765 }
6766
6767 return current;
6768 }
6769
6778 void unget()
6779 {
6780 next_unget = true;
6781
6783
6784 // in case we "unget" a newline, we have to also decrement the lines_read
6786 {
6787 if (position.lines_read > 0)
6788 {
6790 }
6791 }
6792 else
6793 {
6795 }
6796
6797 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
6798 {
6799 assert(not token_string.empty());
6801 }
6802 }
6803
6805 void add(int c)
6806 {
6807 token_buffer.push_back(std::char_traits<char>::to_char_type(c));
6808 }
6809
6810 public:
6812 // value getters
6814
6816 constexpr number_integer_t get_number_integer() const noexcept
6817 {
6818 return value_integer;
6819 }
6820
6822 constexpr number_unsigned_t get_number_unsigned() const noexcept
6823 {
6824 return value_unsigned;
6825 }
6826
6828 constexpr number_float_t get_number_float() const noexcept
6829 {
6830 return value_float;
6831 }
6832
6835 {
6836 return token_buffer;
6837 }
6838
6840 // diagnostics
6842
6844 constexpr position_t get_position() const noexcept
6845 {
6846 return position;
6847 }
6848
6852 std::string get_token_string() const
6853 {
6854 // escape control characters
6855 std::string result;
6856 for (const auto c : token_string)
6857 {
6858 if ('\x00' <= c and c <= '\x1F')
6859 {
6860 // escape control characters
6861 std::array<char, 9> cs{{}};
6862 (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
6863 result += cs.data();
6864 }
6865 else
6866 {
6867 // add character as is
6868 result.push_back(c);
6869 }
6870 }
6871
6872 return result;
6873 }
6874
6876 constexpr const char* get_error_message() const noexcept
6877 {
6878 return error_message;
6879 }
6880
6882 // actual scanner
6884
6890 {
6891 if (get() == 0xEF)
6892 {
6893 // check if we completely parse the BOM
6894 return get() == 0xBB and get() == 0xBF;
6895 }
6896
6897 // the first character is not the beginning of the BOM; unget it to
6898 // process is later
6899 unget();
6900 return true;
6901 }
6902
6904 {
6905 // initially, skip the BOM
6906 if (position.chars_read_total == 0 and not skip_bom())
6907 {
6908 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
6910 }
6911
6912 // read next character and ignore whitespace
6913 do
6914 {
6915 get();
6916 }
6917 while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
6918
6919 switch (current)
6920 {
6921 // structural characters
6922 case '[':
6924 case ']':
6925 return token_type::end_array;
6926 case '{':
6928 case '}':
6930 case ':':
6932 case ',':
6934
6935 // literals
6936 case 't':
6937 return scan_literal("true", 4, token_type::literal_true);
6938 case 'f':
6939 return scan_literal("false", 5, token_type::literal_false);
6940 case 'n':
6941 return scan_literal("null", 4, token_type::literal_null);
6942
6943 // string
6944 case '\"':
6945 return scan_string();
6946
6947 // number
6948 case '-':
6949 case '0':
6950 case '1':
6951 case '2':
6952 case '3':
6953 case '4':
6954 case '5':
6955 case '6':
6956 case '7':
6957 case '8':
6958 case '9':
6959 return scan_number();
6960
6961 // end of input (the null byte is needed when parsing from
6962 // string literals)
6963 case '\0':
6964 case std::char_traits<char>::eof():
6966
6967 // error
6968 default:
6969 error_message = "invalid literal";
6971 }
6972 }
6973
6974 private:
6977
6979 std::char_traits<char>::int_type current = std::char_traits<char>::eof();
6980
6982 bool next_unget = false;
6983
6986
6989
6992
6994 const char* error_message = "";
6995
6996 // number values
7000
7002 const char decimal_point_char = '.';
7003 };
7004 } // namespace detail
7005} // namespace nlohmann
7006
7007// #include <nlohmann/detail/input/parser.hpp>
7008
7009
7010#include <cassert> // assert
7011#include <cmath> // isfinite
7012#include <cstdint> // uint8_t
7013#include <functional> // function
7014#include <string> // string
7015#include <utility> // move
7016#include <vector> // vector
7017
7018// #include <nlohmann/detail/exceptions.hpp>
7019
7020// #include <nlohmann/detail/input/input_adapters.hpp>
7021
7022// #include <nlohmann/detail/input/json_sax.hpp>
7023
7024// #include <nlohmann/detail/input/lexer.hpp>
7025
7026// #include <nlohmann/detail/macro_scope.hpp>
7027
7028// #include <nlohmann/detail/meta/is_sax.hpp>
7029
7030// #include <nlohmann/detail/value_t.hpp>
7031
7032
7033namespace nlohmann
7034{
7035 namespace detail
7036 {
7038// parser //
7040
7046 template<typename BasicJsonType>
7048 {
7049 using number_integer_t = typename BasicJsonType::number_integer_t;
7050 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7051 using number_float_t = typename BasicJsonType::number_float_t;
7052 using string_t = typename BasicJsonType::string_t;
7055
7056 public:
7057 enum class parse_event_t : uint8_t
7058 {
7060 object_start,
7062 object_end,
7064 array_start,
7066 array_end,
7068 key,
7070 value
7071 };
7072
7074 std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
7075
7078 const parser_callback_t cb = nullptr,
7079 const bool allow_exceptions_ = true)
7080 : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
7081 {
7082 // read first token
7083 get_token();
7084 }
7085
7096 void parse(const bool strict, BasicJsonType& result)
7097 {
7098 if (callback)
7099 {
7101 sax_parse_internal(&sdp);
7102 result.assert_invariant();
7103
7104 // in strict mode, input must be completely read
7105 if (strict and (get_token() != token_type::end_of_input))
7106 {
7110 exception_message(token_type::end_of_input, "value")));
7111 }
7112
7113 // in case of an error, return discarded value
7114 if (sdp.is_errored())
7115 {
7116 result = value_t::discarded;
7117 return;
7118 }
7119
7120 // set top-level value to null if it was discarded by the callback
7121 // function
7122 if (result.is_discarded())
7123 {
7124 result = nullptr;
7125 }
7126 }
7127 else
7128 {
7130 sax_parse_internal(&sdp);
7131 result.assert_invariant();
7132
7133 // in strict mode, input must be completely read
7134 if (strict and (get_token() != token_type::end_of_input))
7135 {
7139 exception_message(token_type::end_of_input, "value")));
7140 }
7141
7142 // in case of an error, return discarded value
7143 if (sdp.is_errored())
7144 {
7145 result = value_t::discarded;
7146 return;
7147 }
7148 }
7149 }
7150
7157 bool accept(const bool strict = true)
7158 {
7160 return sax_parse(&sax_acceptor, strict);
7161 }
7162
7163 template <typename SAX>
7164 bool sax_parse(SAX* sax, const bool strict = true)
7165 {
7167 const bool result = sax_parse_internal(sax);
7168
7169 // strict mode: next byte must be EOF
7170 if (result and strict and (get_token() != token_type::end_of_input))
7171 {
7172 return sax->parse_error(m_lexer.get_position(),
7175 exception_message(token_type::end_of_input, "value")));
7176 }
7177
7178 return result;
7179 }
7180
7181 private:
7182 template <typename SAX>
7183 bool sax_parse_internal(SAX* sax)
7184 {
7185 // stack to remember the hierarchy of structured values we are parsing
7186 // true = array; false = object
7187 std::vector<bool> states;
7188 // value to avoid a goto (see comment where set to true)
7189 bool skip_to_state_evaluation = false;
7190
7191 while (true)
7192 {
7193 if (not skip_to_state_evaluation)
7194 {
7195 // invariant: get_token() was called before each iteration
7196 switch (last_token)
7197 {
7198 case token_type::begin_object:
7199 {
7200 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
7201 {
7202 return false;
7203 }
7204
7205 // closing } -> we are done
7206 if (get_token() == token_type::end_object)
7207 {
7208 if (JSON_UNLIKELY(not sax->end_object()))
7209 {
7210 return false;
7211 }
7212 break;
7213 }
7214
7215 // parse key
7216 if (JSON_UNLIKELY(last_token != token_type::value_string))
7217 {
7218 return sax->parse_error(m_lexer.get_position(),
7221 exception_message(token_type::value_string, "object key")));
7222 }
7223 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
7224 {
7225 return false;
7226 }
7227
7228 // parse separator (:)
7229 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
7230 {
7231 return sax->parse_error(m_lexer.get_position(),
7234 exception_message(token_type::name_separator, "object separator")));
7235 }
7236
7237 // remember we are now inside an object
7238 states.push_back(false);
7239
7240 // parse values
7241 get_token();
7242 continue;
7243 }
7244
7245 case token_type::begin_array:
7246 {
7247 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
7248 {
7249 return false;
7250 }
7251
7252 // closing ] -> we are done
7253 if (get_token() == token_type::end_array)
7254 {
7255 if (JSON_UNLIKELY(not sax->end_array()))
7256 {
7257 return false;
7258 }
7259 break;
7260 }
7261
7262 // remember we are now inside an array
7263 states.push_back(true);
7264
7265 // parse values (no need to call get_token)
7266 continue;
7267 }
7268
7269 case token_type::value_float:
7270 {
7271 const auto res = m_lexer.get_number_float();
7272
7273 if (JSON_UNLIKELY(not std::isfinite(res)))
7274 {
7275 return sax->parse_error(m_lexer.get_position(),
7277 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
7278 }
7279
7280 if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
7281 {
7282 return false;
7283 }
7284
7285 break;
7286 }
7287
7288 case token_type::literal_false:
7289 {
7290 if (JSON_UNLIKELY(not sax->boolean(false)))
7291 {
7292 return false;
7293 }
7294 break;
7295 }
7296
7297 case token_type::literal_null:
7298 {
7299 if (JSON_UNLIKELY(not sax->null()))
7300 {
7301 return false;
7302 }
7303 break;
7304 }
7305
7306 case token_type::literal_true:
7307 {
7308 if (JSON_UNLIKELY(not sax->boolean(true)))
7309 {
7310 return false;
7311 }
7312 break;
7313 }
7314
7315 case token_type::value_integer:
7316 {
7317 if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
7318 {
7319 return false;
7320 }
7321 break;
7322 }
7323
7324 case token_type::value_string:
7325 {
7326 if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
7327 {
7328 return false;
7329 }
7330 break;
7331 }
7332
7333 case token_type::value_unsigned:
7334 {
7335 if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
7336 {
7337 return false;
7338 }
7339 break;
7340 }
7341
7342 case token_type::parse_error:
7343 {
7344 // using "uninitialized" to avoid "expected" message
7345 return sax->parse_error(m_lexer.get_position(),
7348 exception_message(token_type::uninitialized, "value")));
7349 }
7350
7351 default: // the last token was unexpected
7352 {
7353 return sax->parse_error(m_lexer.get_position(),
7356 exception_message(token_type::literal_or_value, "value")));
7357 }
7358 }
7359 }
7360 else
7361 {
7362 skip_to_state_evaluation = false;
7363 }
7364
7365 // we reached this line after we successfully parsed a value
7366 if (states.empty())
7367 {
7368 // empty stack: we reached the end of the hierarchy: done
7369 return true;
7370 }
7371
7372 if (states.back()) // array
7373 {
7374 // comma -> next value
7375 if (get_token() == token_type::value_separator)
7376 {
7377 // parse a new value
7378 get_token();
7379 continue;
7380 }
7381
7382 // closing ]
7383 if (JSON_LIKELY(last_token == token_type::end_array))
7384 {
7385 if (JSON_UNLIKELY(not sax->end_array()))
7386 {
7387 return false;
7388 }
7389
7390 // We are done with this array. Before we can parse a
7391 // new value, we need to evaluate the new state first.
7392 // By setting skip_to_state_evaluation to false, we
7393 // are effectively jumping to the beginning of this if.
7394 assert(not states.empty());
7395 states.pop_back();
7396 skip_to_state_evaluation = true;
7397 continue;
7398 }
7399
7400 return sax->parse_error(m_lexer.get_position(),
7403 exception_message(token_type::end_array, "array")));
7404 }
7405 else // object
7406 {
7407 // comma -> next value
7408 if (get_token() == token_type::value_separator)
7409 {
7410 // parse key
7411 if (JSON_UNLIKELY(get_token() != token_type::value_string))
7412 {
7413 return sax->parse_error(m_lexer.get_position(),
7416 exception_message(token_type::value_string, "object key")));
7417 }
7418
7419 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
7420 {
7421 return false;
7422 }
7423
7424 // parse separator (:)
7425 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
7426 {
7427 return sax->parse_error(m_lexer.get_position(),
7430 exception_message(token_type::name_separator, "object separator")));
7431 }
7432
7433 // parse values
7434 get_token();
7435 continue;
7436 }
7437
7438 // closing }
7439 if (JSON_LIKELY(last_token == token_type::end_object))
7440 {
7441 if (JSON_UNLIKELY(not sax->end_object()))
7442 {
7443 return false;
7444 }
7445
7446 // We are done with this object. Before we can parse a
7447 // new value, we need to evaluate the new state first.
7448 // By setting skip_to_state_evaluation to false, we
7449 // are effectively jumping to the beginning of this if.
7450 assert(not states.empty());
7451 states.pop_back();
7452 skip_to_state_evaluation = true;
7453 continue;
7454 }
7455
7456 return sax->parse_error(m_lexer.get_position(),
7459 exception_message(token_type::end_object, "object")));
7460 }
7461 }
7462 }
7463
7466 {
7467 return last_token = m_lexer.scan();
7468 }
7469
7470 std::string exception_message(const token_type expected, const std::string& context)
7471 {
7472 std::string error_msg = "syntax error ";
7473
7474 if (not context.empty())
7475 {
7476 error_msg += "while parsing " + context + " ";
7477 }
7478
7479 error_msg += "- ";
7480
7481 if (last_token == token_type::parse_error)
7482 {
7483 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
7484 m_lexer.get_token_string() + "'";
7485 }
7486 else
7487 {
7488 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
7489 }
7490
7491 if (expected != token_type::uninitialized)
7492 {
7493 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
7494 }
7495
7496 return error_msg;
7497 }
7498
7499 private:
7503 token_type last_token = token_type::uninitialized;
7507 const bool allow_exceptions = true;
7508 };
7509 } // namespace detail
7510} // namespace nlohmann
7511
7512// #include <nlohmann/detail/iterators/internal_iterator.hpp>
7513
7514
7515// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
7516
7517
7518#include <cstddef> // ptrdiff_t
7519#include <limits> // numeric_limits
7520
7521namespace nlohmann
7522{
7523 namespace detail
7524 {
7525/*
7526@brief an iterator for primitive JSON types
7527
7528This class models an iterator for primitive JSON types (boolean, number,
7529string). It's only purpose is to allow the iterator/const_iterator classes
7530to "iterate" over primitive values. Internally, the iterator is modeled by
7531a `difference_type` variable. Value begin_value (`0`) models the begin,
7532end_value (`1`) models past the end.
7533*/
7535 {
7536 private:
7537 using difference_type = std::ptrdiff_t;
7538 static constexpr difference_type begin_value = 0;
7539 static constexpr difference_type end_value = begin_value + 1;
7540
7542 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
7543
7544 public:
7545 constexpr difference_type get_value() const noexcept
7546 {
7547 return m_it;
7548 }
7549
7551 void set_begin() noexcept
7552 {
7553 m_it = begin_value;
7554 }
7555
7557 void set_end() noexcept
7558 {
7559 m_it = end_value;
7560 }
7561
7563 constexpr bool is_begin() const noexcept
7564 {
7565 return m_it == begin_value;
7566 }
7567
7569 constexpr bool is_end() const noexcept
7570 {
7571 return m_it == end_value;
7572 }
7573
7574 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
7575 {
7576 return lhs.m_it == rhs.m_it;
7577 }
7578
7579 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
7580 {
7581 return lhs.m_it < rhs.m_it;
7582 }
7583
7585 {
7586 auto result = *this;
7587 result += n;
7588 return result;
7589 }
7590
7592 {
7593 return lhs.m_it - rhs.m_it;
7594 }
7595
7597 {
7598 ++m_it;
7599 return *this;
7600 }
7601
7603 {
7604 auto result = *this;
7605 ++m_it;
7606 return result;
7607 }
7608
7610 {
7611 --m_it;
7612 return *this;
7613 }
7614
7616 {
7617 auto result = *this;
7618 --m_it;
7619 return result;
7620 }
7621
7623 {
7624 m_it += n;
7625 return *this;
7626 }
7627
7629 {
7630 m_it -= n;
7631 return *this;
7632 }
7633 };
7634 } // namespace detail
7635} // namespace nlohmann
7636
7637
7638namespace nlohmann
7639{
7640 namespace detail
7641 {
7648 template<typename BasicJsonType> struct internal_iterator
7649 {
7651 typename BasicJsonType::object_t::iterator object_iterator {};
7653 typename BasicJsonType::array_t::iterator array_iterator {};
7656 };
7657 } // namespace detail
7658} // namespace nlohmann
7659
7660// #include <nlohmann/detail/iterators/iter_impl.hpp>
7661
7662
7663#include <ciso646> // not
7664#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
7665#include <type_traits> // conditional, is_const, remove_const
7666
7667// #include <nlohmann/detail/exceptions.hpp>
7668
7669// #include <nlohmann/detail/iterators/internal_iterator.hpp>
7670
7671// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
7672
7673// #include <nlohmann/detail/macro_scope.hpp>
7674
7675// #include <nlohmann/detail/meta/cpp_future.hpp>
7676
7677// #include <nlohmann/detail/meta/type_traits.hpp>
7678
7679// #include <nlohmann/detail/value_t.hpp>
7680
7681
7682namespace nlohmann
7683{
7684 namespace detail
7685 {
7686// forward declare, to be able to friend it later on
7687 template<typename IteratorType> class iteration_proxy;
7688 template<typename IteratorType> class iteration_proxy_value;
7689
7706 template<typename BasicJsonType>
7708 {
7710 friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
7714
7715 using object_t = typename BasicJsonType::object_t;
7716 using array_t = typename BasicJsonType::array_t;
7717 // make sure BasicJsonType is basic_json or const basic_json
7719 "iter_impl only accepts (const) basic_json");
7720
7721 public:
7722
7728 using iterator_category = std::bidirectional_iterator_tag;
7729
7731 using value_type = typename BasicJsonType::value_type;
7733 using difference_type = typename BasicJsonType::difference_type;
7735 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
7736 typename BasicJsonType::const_pointer,
7737 typename BasicJsonType::pointer>::type;
7740 typename std::conditional<std::is_const<BasicJsonType>::value,
7741 typename BasicJsonType::const_reference,
7742 typename BasicJsonType::reference>::type;
7743
7745 iter_impl() = default;
7746
7753 explicit iter_impl(pointer object) noexcept : m_object(object)
7754 {
7755 assert(m_object != nullptr);
7756
7757 switch (m_object->m_type)
7758 {
7759 case value_t::object:
7760 {
7761 m_it.object_iterator = typename object_t::iterator();
7762 break;
7763 }
7764
7765 case value_t::array:
7766 {
7767 m_it.array_iterator = typename array_t::iterator();
7768 break;
7769 }
7770
7771 default:
7772 {
7774 break;
7775 }
7776 }
7777 }
7778
7793 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
7794 : m_object(other.m_object), m_it(other.m_it) {}
7795
7802 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
7803 {
7804 m_object = other.m_object;
7805 m_it = other.m_it;
7806 return *this;
7807 }
7808
7809 private:
7814 void set_begin() noexcept
7815 {
7816 assert(m_object != nullptr);
7817
7818 switch (m_object->m_type)
7819 {
7820 case value_t::object:
7821 {
7822 m_it.object_iterator = m_object->m_value.object->begin();
7823 break;
7824 }
7825
7826 case value_t::array:
7827 {
7828 m_it.array_iterator = m_object->m_value.array->begin();
7829 break;
7830 }
7831
7832 case value_t::null:
7833 {
7834 // set to end so begin()==end() is true: null is empty
7836 break;
7837 }
7838
7839 default:
7840 {
7842 break;
7843 }
7844 }
7845 }
7846
7851 void set_end() noexcept
7852 {
7853 assert(m_object != nullptr);
7854
7855 switch (m_object->m_type)
7856 {
7857 case value_t::object:
7858 {
7859 m_it.object_iterator = m_object->m_value.object->end();
7860 break;
7861 }
7862
7863 case value_t::array:
7864 {
7865 m_it.array_iterator = m_object->m_value.array->end();
7866 break;
7867 }
7868
7869 default:
7870 {
7872 break;
7873 }
7874 }
7875 }
7876
7877 public:
7883 {
7884 assert(m_object != nullptr);
7885
7886 switch (m_object->m_type)
7887 {
7888 case value_t::object:
7889 {
7890 assert(m_it.object_iterator != m_object->m_value.object->end());
7891 return m_it.object_iterator->second;
7892 }
7893
7894 case value_t::array:
7895 {
7896 assert(m_it.array_iterator != m_object->m_value.array->end());
7897 return *m_it.array_iterator;
7898 }
7899
7900 case value_t::null:
7901 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
7902
7903 default:
7904 {
7906 {
7907 return *m_object;
7908 }
7909
7910 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
7911 }
7912 }
7913 }
7914
7920 {
7921 assert(m_object != nullptr);
7922
7923 switch (m_object->m_type)
7924 {
7925 case value_t::object:
7926 {
7927 assert(m_it.object_iterator != m_object->m_value.object->end());
7928 return &(m_it.object_iterator->second);
7929 }
7930
7931 case value_t::array:
7932 {
7933 assert(m_it.array_iterator != m_object->m_value.array->end());
7934 return &*m_it.array_iterator;
7935 }
7936
7937 default:
7938 {
7940 {
7941 return m_object;
7942 }
7943
7944 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
7945 }
7946 }
7947 }
7948
7954 {
7955 auto result = *this;
7956 ++(*this);
7957 return result;
7958 }
7959
7965 {
7966 assert(m_object != nullptr);
7967
7968 switch (m_object->m_type)
7969 {
7970 case value_t::object:
7971 {
7972 std::advance(m_it.object_iterator, 1);
7973 break;
7974 }
7975
7976 case value_t::array:
7977 {
7978 std::advance(m_it.array_iterator, 1);
7979 break;
7980 }
7981
7982 default:
7983 {
7985 break;
7986 }
7987 }
7988
7989 return *this;
7990 }
7991
7997 {
7998 auto result = *this;
7999 --(*this);
8000 return result;
8001 }
8002
8008 {
8009 assert(m_object != nullptr);
8010
8011 switch (m_object->m_type)
8012 {
8013 case value_t::object:
8014 {
8015 std::advance(m_it.object_iterator, -1);
8016 break;
8017 }
8018
8019 case value_t::array:
8020 {
8021 std::advance(m_it.array_iterator, -1);
8022 break;
8023 }
8024
8025 default:
8026 {
8028 break;
8029 }
8030 }
8031
8032 return *this;
8033 }
8034
8039 bool operator==(const iter_impl& other) const
8040 {
8041 // if objects are not the same, the comparison is undefined
8042 if (JSON_UNLIKELY(m_object != other.m_object))
8043 {
8044 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
8045 }
8046
8047 assert(m_object != nullptr);
8048
8049 switch (m_object->m_type)
8050 {
8051 case value_t::object:
8052 return (m_it.object_iterator == other.m_it.object_iterator);
8053
8054 case value_t::array:
8055 return (m_it.array_iterator == other.m_it.array_iterator);
8056
8057 default:
8059 }
8060 }
8061
8066 bool operator!=(const iter_impl& other) const
8067 {
8068 return not operator==(other);
8069 }
8070
8075 bool operator<(const iter_impl& other) const
8076 {
8077 // if objects are not the same, the comparison is undefined
8078 if (JSON_UNLIKELY(m_object != other.m_object))
8079 {
8080 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
8081 }
8082
8083 assert(m_object != nullptr);
8084
8085 switch (m_object->m_type)
8086 {
8087 case value_t::object:
8088 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
8089
8090 case value_t::array:
8091 return (m_it.array_iterator < other.m_it.array_iterator);
8092
8093 default:
8095 }
8096 }
8097
8102 bool operator<=(const iter_impl& other) const
8103 {
8104 return not other.operator < (*this);
8105 }
8106
8111 bool operator>(const iter_impl& other) const
8112 {
8113 return not operator<=(other);
8114 }
8115
8120 bool operator>=(const iter_impl& other) const
8121 {
8122 return not operator<(other);
8123 }
8124
8130 {
8131 assert(m_object != nullptr);
8132
8133 switch (m_object->m_type)
8134 {
8135 case value_t::object:
8136 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
8137
8138 case value_t::array:
8139 {
8140 std::advance(m_it.array_iterator, i);
8141 break;
8142 }
8143
8144 default:
8145 {
8147 break;
8148 }
8149 }
8150
8151 return *this;
8152 }
8153
8159 {
8160 return operator+=(-i);
8161 }
8162
8168 {
8169 auto result = *this;
8170 result += i;
8171 return result;
8172 }
8173
8179 {
8180 auto result = it;
8181 result += i;
8182 return result;
8183 }
8184
8190 {
8191 auto result = *this;
8192 result -= i;
8193 return result;
8194 }
8195
8201 {
8202 assert(m_object != nullptr);
8203
8204 switch (m_object->m_type)
8205 {
8206 case value_t::object:
8207 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
8208
8209 case value_t::array:
8210 return m_it.array_iterator - other.m_it.array_iterator;
8211
8212 default:
8214 }
8215 }
8216
8222 {
8223 assert(m_object != nullptr);
8224
8225 switch (m_object->m_type)
8226 {
8227 case value_t::object:
8228 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
8229
8230 case value_t::array:
8231 return *std::next(m_it.array_iterator, n);
8232
8233 case value_t::null:
8234 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
8235
8236 default:
8237 {
8239 {
8240 return *m_object;
8241 }
8242
8243 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
8244 }
8245 }
8246 }
8247
8252 const typename object_t::key_type& key() const
8253 {
8254 assert(m_object != nullptr);
8255
8256 if (JSON_LIKELY(m_object->is_object()))
8257 {
8258 return m_it.object_iterator->first;
8259 }
8260
8261 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
8262 }
8263
8269 {
8270 return operator*();
8271 }
8272
8273 private:
8278 };
8279 } // namespace detail
8280} // namespace nlohmann
8281
8282// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
8283
8284// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
8285
8286
8287#include <cstddef> // ptrdiff_t
8288#include <iterator> // reverse_iterator
8289#include <utility> // declval
8290
8291namespace nlohmann
8292{
8293 namespace detail
8294 {
8296// reverse_iterator //
8298
8317 template<typename Base>
8318 class json_reverse_iterator : public std::reverse_iterator<Base>
8319 {
8320 public:
8321 using difference_type = std::ptrdiff_t;
8323 using base_iterator = std::reverse_iterator<Base>;
8325 using reference = typename Base::reference;
8326
8328 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
8329 : base_iterator(it) {}
8330
8332 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
8333
8336 {
8337 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
8338 }
8339
8342 {
8343 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
8344 }
8345
8348 {
8349 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
8350 }
8351
8354 {
8355 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
8356 }
8357
8360 {
8361 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
8362 }
8363
8366 {
8367 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
8368 }
8369
8372 {
8373 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
8374 }
8375
8378 {
8379 return base_iterator(*this) - base_iterator(other);
8380 }
8381
8384 {
8385 return *(this->operator+(n));
8386 }
8387
8389 auto key() const -> decltype(std::declval<Base>().key())
8390 {
8391 auto it = --this->base();
8392 return it.key();
8393 }
8394
8397 {
8398 auto it = --this->base();
8399 return it.operator * ();
8400 }
8401 };
8402 } // namespace detail
8403} // namespace nlohmann
8404
8405// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
8406
8407// #include <nlohmann/detail/json_pointer.hpp>
8408
8409
8410#include <algorithm> // all_of
8411#include <cassert> // assert
8412#include <numeric> // accumulate
8413#include <string> // string
8414#include <utility> // move
8415#include <vector> // vector
8416
8417// #include <nlohmann/detail/exceptions.hpp>
8418
8419// #include <nlohmann/detail/macro_scope.hpp>
8420
8421// #include <nlohmann/detail/value_t.hpp>
8422
8423
8424namespace nlohmann
8425{
8426 template<typename BasicJsonType>
8428 {
8429 // allow basic_json to access private members
8431 friend class basic_json;
8432
8433 public:
8455 explicit json_pointer(const std::string& s = "")
8457 {}
8458
8473 std::string to_string() const
8474 {
8475 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
8476 std::string{},
8477 [](const std::string & a, const std::string & b)
8478 {
8479 return a + "/" + escape(b);
8480 });
8481 }
8482
8484 operator std::string() const
8485 {
8486 return to_string();
8487 }
8488
8506 {
8508 ptr.reference_tokens.begin(),
8509 ptr.reference_tokens.end());
8510 return *this;
8511 }
8512
8529 json_pointer& operator/=(std::string token)
8530 {
8531 push_back(std::move(token));
8532 return *this;
8533 }
8534
8552 {
8553 return *this /= std::to_string(array_index);
8554 }
8555
8572 const json_pointer& rhs)
8573 {
8574 return json_pointer(lhs) /= rhs;
8575 }
8576
8592 friend json_pointer operator/(const json_pointer& ptr, std::string token)
8593 {
8594 return json_pointer(ptr) /= std::move(token);
8595 }
8596
8613 {
8614 return json_pointer(ptr) /= array_index;
8615 }
8616
8631 {
8632 if (empty())
8633 {
8634 return *this;
8635 }
8636
8637 json_pointer res = *this;
8638 res.pop_back();
8639 return res;
8640 }
8641
8656 {
8657 if (JSON_UNLIKELY(empty()))
8658 {
8659 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
8660 }
8661
8663 }
8664
8679 const std::string& back()
8680 {
8681 if (JSON_UNLIKELY(empty()))
8682 {
8683 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
8684 }
8685
8686 return reference_tokens.back();
8687 }
8688
8701 void push_back(const std::string& token)
8702 {
8704 }
8705
8707 void push_back(std::string&& token)
8708 {
8709 reference_tokens.push_back(std::move(token));
8710 }
8711
8726 bool empty() const noexcept
8727 {
8728 return reference_tokens.empty();
8729 }
8730
8731 private:
8739 static int array_index(const std::string& s)
8740 {
8741 std::size_t processed_chars = 0;
8742 const int res = std::stoi(s, &processed_chars);
8743
8744 // check if the string was completely read
8745 if (JSON_UNLIKELY(processed_chars != s.size()))
8746 {
8747 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
8748 }
8749
8750 return res;
8751 }
8752
8754 {
8755 if (JSON_UNLIKELY(empty()))
8756 {
8757 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
8758 }
8759
8760 json_pointer result = *this;
8761 result.reference_tokens = {reference_tokens[0]};
8762 return result;
8763 }
8764
8773 BasicJsonType& get_and_create(BasicJsonType& j) const
8774 {
8775 using size_type = typename BasicJsonType::size_type;
8776 auto result = &j;
8777
8778 // in case no reference tokens exist, return a reference to the JSON value
8779 // j which will be overwritten by a primitive value
8780 for (const auto& reference_token : reference_tokens)
8781 {
8782 switch (result->m_type)
8783 {
8785 {
8786 if (reference_token == "0")
8787 {
8788 // start a new array if reference token is 0
8789 result = &result->operator[](0);
8790 }
8791 else
8792 {
8793 // start a new object otherwise
8794 result = &result->operator[](reference_token);
8795 }
8796 break;
8797 }
8798
8800 {
8801 // create an entry in the object
8802 result = &result->operator[](reference_token);
8803 break;
8804 }
8805
8807 {
8808 // create an entry in the array
8809 JSON_TRY
8810 {
8811 result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
8812 }
8813 JSON_CATCH(std::invalid_argument&)
8814 {
8815 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
8816 }
8817 break;
8818 }
8819
8820 /*
8821 The following code is only reached if there exists a reference
8822 token _and_ the current value is primitive. In this case, we have
8823 an error situation, because primitive values may only occur as
8824 single value; that is, with an empty list of reference tokens.
8825 */
8826 default:
8827 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
8828 }
8829 }
8830
8831 return *result;
8832 }
8833
8853 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
8854 {
8855 using size_type = typename BasicJsonType::size_type;
8856 for (const auto& reference_token : reference_tokens)
8857 {
8858 // convert null values to arrays or objects before continuing
8859 if (ptr->m_type == detail::value_t::null)
8860 {
8861 // check if reference token is a number
8862 const bool nums =
8863 std::all_of(reference_token.begin(), reference_token.end(),
8864 [](const char x)
8865 {
8866 return x >= '0' and x <= '9';
8867 });
8868
8869 // change value to array for numbers or "-" or to object otherwise
8870 *ptr = (nums or reference_token == "-")
8873 }
8874
8875 switch (ptr->m_type)
8876 {
8878 {
8879 // use unchecked object access
8880 ptr = &ptr->operator[](reference_token);
8881 break;
8882 }
8883
8885 {
8886 // error condition (cf. RFC 6901, Sect. 4)
8887 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
8888 {
8890 "array index '" + reference_token +
8891 "' must not begin with '0'"));
8892 }
8893
8894 if (reference_token == "-")
8895 {
8896 // explicitly treat "-" as index beyond the end
8897 ptr = &ptr->operator[](ptr->m_value.array->size());
8898 }
8899 else
8900 {
8901 // convert array index to number; unchecked access
8902 JSON_TRY
8903 {
8904 ptr = &ptr->operator[](
8905 static_cast<size_type>(array_index(reference_token)));
8906 }
8907 JSON_CATCH(std::invalid_argument&)
8908 {
8909 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
8910 }
8911 }
8912 break;
8913 }
8914
8915 default:
8916 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
8917 }
8918 }
8919
8920 return *ptr;
8921 }
8922
8929 BasicJsonType& get_checked(BasicJsonType* ptr) const
8930 {
8931 using size_type = typename BasicJsonType::size_type;
8932 for (const auto& reference_token : reference_tokens)
8933 {
8934 switch (ptr->m_type)
8935 {
8937 {
8938 // note: at performs range check
8939 ptr = &ptr->at(reference_token);
8940 break;
8941 }
8942
8944 {
8945 if (JSON_UNLIKELY(reference_token == "-"))
8946 {
8947 // "-" always fails the range check
8949 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
8950 ") is out of range"));
8951 }
8952
8953 // error condition (cf. RFC 6901, Sect. 4)
8954 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
8955 {
8957 "array index '" + reference_token +
8958 "' must not begin with '0'"));
8959 }
8960
8961 // note: at performs range check
8962 JSON_TRY
8963 {
8964 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
8965 }
8966 JSON_CATCH(std::invalid_argument&)
8967 {
8968 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
8969 }
8970 break;
8971 }
8972
8973 default:
8974 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
8975 }
8976 }
8977
8978 return *ptr;
8979 }
8980
8994 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
8995 {
8996 using size_type = typename BasicJsonType::size_type;
8997 for (const auto& reference_token : reference_tokens)
8998 {
8999 switch (ptr->m_type)
9000 {
9002 {
9003 // use unchecked object access
9004 ptr = &ptr->operator[](reference_token);
9005 break;
9006 }
9007
9009 {
9010 if (JSON_UNLIKELY(reference_token == "-"))
9011 {
9012 // "-" cannot be used for const access
9014 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
9015 ") is out of range"));
9016 }
9017
9018 // error condition (cf. RFC 6901, Sect. 4)
9019 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
9020 {
9022 "array index '" + reference_token +
9023 "' must not begin with '0'"));
9024 }
9025
9026 // use unchecked array access
9027 JSON_TRY
9028 {
9029 ptr = &ptr->operator[](
9030 static_cast<size_type>(array_index(reference_token)));
9031 }
9032 JSON_CATCH(std::invalid_argument&)
9033 {
9034 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
9035 }
9036 break;
9037 }
9038
9039 default:
9040 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
9041 }
9042 }
9043
9044 return *ptr;
9045 }
9046
9053 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
9054 {
9055 using size_type = typename BasicJsonType::size_type;
9056 for (const auto& reference_token : reference_tokens)
9057 {
9058 switch (ptr->m_type)
9059 {
9061 {
9062 // note: at performs range check
9063 ptr = &ptr->at(reference_token);
9064 break;
9065 }
9066
9068 {
9069 if (JSON_UNLIKELY(reference_token == "-"))
9070 {
9071 // "-" always fails the range check
9073 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
9074 ") is out of range"));
9075 }
9076
9077 // error condition (cf. RFC 6901, Sect. 4)
9078 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
9079 {
9081 "array index '" + reference_token +
9082 "' must not begin with '0'"));
9083 }
9084
9085 // note: at performs range check
9086 JSON_TRY
9087 {
9088 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
9089 }
9090 JSON_CATCH(std::invalid_argument&)
9091 {
9092 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
9093 }
9094 break;
9095 }
9096
9097 default:
9098 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
9099 }
9100 }
9101
9102 return *ptr;
9103 }
9104
9114 static std::vector<std::string> split(const std::string& reference_string)
9115 {
9117
9118 // special case: empty reference string -> no reference tokens
9119 if (reference_string.empty())
9120 {
9121 return result;
9122 }
9123
9124 // check if nonempty reference string begins with slash
9125 if (JSON_UNLIKELY(reference_string[0] != '/'))
9126 {
9128 "JSON pointer must be empty or begin with '/' - was: '" +
9129 reference_string + "'"));
9130 }
9131
9132 // extract the reference tokens:
9133 // - slash: position of the last read slash (or end of string)
9134 // - start: position after the previous slash
9135 for (
9136 // search for the first slash after the first character
9137 std::size_t slash = reference_string.find_first_of('/', 1),
9138 // set the beginning of the first reference token
9139 start = 1;
9140 // we can stop if start == 0 (if slash == std::string::npos)
9141 start != 0;
9142 // set the beginning of the next reference token
9143 // (will eventually be 0 if slash == std::string::npos)
9144 start = (slash == std::string::npos) ? 0 : slash + 1,
9145 // find next slash
9146 slash = reference_string.find_first_of('/', start))
9147 {
9148 // use the text between the beginning of the reference token
9149 // (start) and the last slash (slash).
9150 auto reference_token = reference_string.substr(start, slash - start);
9151
9152 // check reference tokens are properly escaped
9153 for (std::size_t pos = reference_token.find_first_of('~');
9154 pos != std::string::npos;
9155 pos = reference_token.find_first_of('~', pos + 1))
9156 {
9157 assert(reference_token[pos] == '~');
9158
9159 // ~ must be followed by 0 or 1
9160 if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
9161 (reference_token[pos + 1] != '0' and
9162 reference_token[pos + 1] != '1')))
9163 {
9164 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
9165 }
9166 }
9167
9168 // finally, store the reference token
9169 unescape(reference_token);
9170 result.push_back(reference_token);
9171 }
9172
9173 return result;
9174 }
9175
9189 static void replace_substring(std::string& s, const std::string& f,
9190 const std::string& t)
9191 {
9192 assert(not f.empty());
9193 for (auto pos = s.find(f); // find first occurrence of f
9194 pos != std::string::npos; // make sure f was found
9195 s.replace(pos, f.size(), t), // replace with t, and
9196 pos = s.find(f, pos + t.size())) // find next occurrence of f
9197 {}
9198 }
9199
9201 static std::string escape(std::string s)
9202 {
9203 replace_substring(s, "~", "~0");
9204 replace_substring(s, "/", "~1");
9205 return s;
9206 }
9207
9209 static void unescape(std::string& s)
9210 {
9211 replace_substring(s, "~1", "/");
9212 replace_substring(s, "~0", "~");
9213 }
9214
9222 static void flatten(const std::string& reference_string,
9223 const BasicJsonType& value,
9224 BasicJsonType& result)
9225 {
9226 switch (value.m_type)
9227 {
9229 {
9230 if (value.m_value.array->empty())
9231 {
9232 // flatten empty array as null
9233 result[reference_string] = nullptr;
9234 }
9235 else
9236 {
9237 // iterate array and use index as reference string
9238 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
9239 {
9240 flatten(reference_string + "/" + std::to_string(i),
9241 value.m_value.array->operator[](i), result);
9242 }
9243 }
9244 break;
9245 }
9246
9248 {
9249 if (value.m_value.object->empty())
9250 {
9251 // flatten empty object as null
9252 result[reference_string] = nullptr;
9253 }
9254 else
9255 {
9256 // iterate object and use keys as reference string
9257 for (const auto& element : *value.m_value.object)
9258 {
9259 flatten(reference_string + "/" + escape(element.first), element.second, result);
9260 }
9261 }
9262 break;
9263 }
9264
9265 default:
9266 {
9267 // add primitive value with its reference string
9268 result[reference_string] = value;
9269 break;
9270 }
9271 }
9272 }
9273
9284 static BasicJsonType
9285 unflatten(const BasicJsonType& value)
9286 {
9287 if (JSON_UNLIKELY(not value.is_object()))
9288 {
9289 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
9290 }
9291
9292 BasicJsonType result;
9293
9294 // iterate the JSON object values
9295 for (const auto& element : *value.m_value.object)
9296 {
9297 if (JSON_UNLIKELY(not element.second.is_primitive()))
9298 {
9299 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
9300 }
9301
9302 // assign value to reference pointed to by JSON pointer; Note that if
9303 // the JSON pointer is "" (i.e., points to the whole value), function
9304 // get_and_create returns a reference to result itself. An assignment
9305 // will then create a primitive value.
9306 json_pointer(element.first).get_and_create(result) = element.second;
9307 }
9308
9309 return result;
9310 }
9311
9323 friend bool operator==(json_pointer const& lhs,
9324 json_pointer const& rhs) noexcept
9325 {
9326 return lhs.reference_tokens == rhs.reference_tokens;
9327 }
9328
9340 friend bool operator!=(json_pointer const& lhs,
9341 json_pointer const& rhs) noexcept
9342 {
9343 return not (lhs == rhs);
9344 }
9345
9348 };
9349} // namespace nlohmann
9350
9351// #include <nlohmann/detail/json_ref.hpp>
9352
9353
9354#include <initializer_list>
9355#include <utility>
9356
9357// #include <nlohmann/detail/meta/type_traits.hpp>
9358
9359
9360namespace nlohmann
9361{
9362 namespace detail
9363 {
9364 template<typename BasicJsonType>
9366 {
9367 public:
9368 using value_type = BasicJsonType;
9369
9371 : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
9372 {}
9373
9374 json_ref(const value_type& value)
9375 : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
9376 {}
9377
9378 json_ref(std::initializer_list<json_ref> init)
9379 : owned_value(init), value_ref(&owned_value), is_rvalue(true)
9380 {}
9381
9382 template <
9383 class... Args,
9384 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
9385 json_ref(Args && ... args)
9386 : owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
9387 is_rvalue(true) {}
9388
9389 // class should be movable only
9390 json_ref(json_ref&&) = default;
9391 json_ref(const json_ref&) = delete;
9392 json_ref& operator=(const json_ref&) = delete;
9394 ~json_ref() = default;
9395
9397 {
9398 if (is_rvalue)
9399 {
9400 return std::move(*value_ref);
9401 }
9402 return *value_ref;
9403 }
9404
9405 value_type const& operator*() const
9406 {
9407 return *static_cast<value_type const*>(value_ref);
9408 }
9409
9410 value_type const* operator->() const
9411 {
9412 return static_cast<value_type const*>(value_ref);
9413 }
9414
9415 private:
9416 mutable value_type owned_value = nullptr;
9418 const bool is_rvalue;
9419 };
9420 } // namespace detail
9421} // namespace nlohmann
9422
9423// #include <nlohmann/detail/macro_scope.hpp>
9424
9425// #include <nlohmann/detail/meta/cpp_future.hpp>
9426
9427// #include <nlohmann/detail/meta/type_traits.hpp>
9428
9429// #include <nlohmann/detail/output/binary_writer.hpp>
9430
9431
9432#include <algorithm> // reverse
9433#include <array> // array
9434#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
9435#include <cstring> // memcpy
9436#include <limits> // numeric_limits
9437#include <string> // string
9438
9439// #include <nlohmann/detail/input/binary_reader.hpp>
9440
9441// #include <nlohmann/detail/output/output_adapters.hpp>
9442
9443
9444#include <algorithm> // copy
9445#include <cstddef> // size_t
9446#include <ios> // streamsize
9447#include <iterator> // back_inserter
9448#include <memory> // shared_ptr, make_shared
9449#include <ostream> // basic_ostream
9450#include <string> // basic_string
9451#include <vector> // vector
9452
9453namespace nlohmann
9454{
9455 namespace detail
9456 {
9458 template<typename CharType> struct output_adapter_protocol
9459 {
9460 virtual void write_character(CharType c) = 0;
9461 virtual void write_characters(const CharType* s, std::size_t length) = 0;
9462 virtual ~output_adapter_protocol() = default;
9463 };
9464
9466 template<typename CharType>
9467 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
9468
9470 template<typename CharType>
9472 {
9473 public:
9475 : v(vec)
9476 {}
9477
9478 void write_character(CharType c) override
9479 {
9480 v.push_back(c);
9481 }
9482
9483 void write_characters(const CharType* s, std::size_t length) override
9484 {
9485 std::copy(s, s + length, std::back_inserter(v));
9486 }
9487
9488 private:
9490 };
9491
9493 template<typename CharType>
9495 {
9496 public:
9497 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
9498 : stream(s)
9499 {}
9500
9501 void write_character(CharType c) override
9502 {
9503 stream.put(c);
9504 }
9505
9506 void write_characters(const CharType* s, std::size_t length) override
9507 {
9508 stream.write(s, static_cast<std::streamsize>(length));
9509 }
9510
9511 private:
9512 std::basic_ostream<CharType>& stream;
9513 };
9514
9516 template<typename CharType, typename StringType = std::basic_string<CharType>>
9518 {
9519 public:
9520 explicit output_string_adapter(StringType& s) noexcept
9521 : str(s)
9522 {}
9523
9524 void write_character(CharType c) override
9525 {
9526 str.push_back(c);
9527 }
9528
9529 void write_characters(const CharType* s, std::size_t length) override
9530 {
9531 str.append(s, length);
9532 }
9533
9534 private:
9535 StringType& str;
9536 };
9537
9538 template<typename CharType, typename StringType = std::basic_string<CharType>>
9540 {
9541 public:
9543 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
9544
9545 output_adapter(std::basic_ostream<CharType>& s)
9546 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
9547
9548 output_adapter(StringType& s)
9549 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
9550
9552 {
9553 return oa;
9554 }
9555
9556 private:
9558 };
9559 } // namespace detail
9560} // namespace nlohmann
9561
9562
9563namespace nlohmann
9564{
9565 namespace detail
9566 {
9568// binary writer //
9570
9574 template<typename BasicJsonType, typename CharType>
9576 {
9577 using string_t = typename BasicJsonType::string_t;
9578
9579 public:
9585 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
9586 {
9587 assert(oa);
9588 }
9589
9594 void write_bson(const BasicJsonType& j)
9595 {
9596 switch (j.type())
9597 {
9598 case value_t::object:
9599 {
9600 write_bson_object(*j.m_value.object);
9601 break;
9602 }
9603
9604 default:
9605 {
9606 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
9607 }
9608 }
9609 }
9610
9614 void write_cbor(const BasicJsonType& j)
9615 {
9616 switch (j.type())
9617 {
9618 case value_t::null:
9619 {
9620 oa->write_character(to_char_type(0xF6));
9621 break;
9622 }
9623
9624 case value_t::boolean:
9625 {
9626 oa->write_character(j.m_value.boolean
9627 ? to_char_type(0xF5)
9628 : to_char_type(0xF4));
9629 break;
9630 }
9631
9633 {
9634 if (j.m_value.number_integer >= 0)
9635 {
9636 // CBOR does not differentiate between positive signed
9637 // integers and unsigned integers. Therefore, we used the
9638 // code from the value_t::number_unsigned case here.
9639 if (j.m_value.number_integer <= 0x17)
9640 {
9641 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
9642 }
9643 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
9644 {
9645 oa->write_character(to_char_type(0x18));
9646 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
9647 }
9648 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
9649 {
9650 oa->write_character(to_char_type(0x19));
9651 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
9652 }
9653 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
9654 {
9655 oa->write_character(to_char_type(0x1A));
9656 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
9657 }
9658 else
9659 {
9660 oa->write_character(to_char_type(0x1B));
9661 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
9662 }
9663 }
9664 else
9665 {
9666 // The conversions below encode the sign in the first
9667 // byte, and the value is converted to a positive number.
9668 const auto positive_number = -1 - j.m_value.number_integer;
9669 if (j.m_value.number_integer >= -24)
9670 {
9671 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
9672 }
9673 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
9674 {
9675 oa->write_character(to_char_type(0x38));
9676 write_number(static_cast<std::uint8_t>(positive_number));
9677 }
9678 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
9679 {
9680 oa->write_character(to_char_type(0x39));
9681 write_number(static_cast<std::uint16_t>(positive_number));
9682 }
9683 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
9684 {
9685 oa->write_character(to_char_type(0x3A));
9686 write_number(static_cast<std::uint32_t>(positive_number));
9687 }
9688 else
9689 {
9690 oa->write_character(to_char_type(0x3B));
9691 write_number(static_cast<std::uint64_t>(positive_number));
9692 }
9693 }
9694 break;
9695 }
9696
9698 {
9699 if (j.m_value.number_unsigned <= 0x17)
9700 {
9701 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
9702 }
9703 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
9704 {
9705 oa->write_character(to_char_type(0x18));
9706 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
9707 }
9708 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
9709 {
9710 oa->write_character(to_char_type(0x19));
9711 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
9712 }
9713 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
9714 {
9715 oa->write_character(to_char_type(0x1A));
9716 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
9717 }
9718 else
9719 {
9720 oa->write_character(to_char_type(0x1B));
9721 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
9722 }
9723 break;
9724 }
9725
9727 {
9728 oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
9729 write_number(j.m_value.number_float);
9730 break;
9731 }
9732
9733 case value_t::string:
9734 {
9735 // step 1: write control byte and the string length
9736 const auto N = j.m_value.string->size();
9737 if (N <= 0x17)
9738 {
9739 write_number(static_cast<std::uint8_t>(0x60 + N));
9740 }
9741 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
9742 {
9743 oa->write_character(to_char_type(0x78));
9744 write_number(static_cast<std::uint8_t>(N));
9745 }
9746 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
9747 {
9748 oa->write_character(to_char_type(0x79));
9749 write_number(static_cast<std::uint16_t>(N));
9750 }
9751 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
9752 {
9753 oa->write_character(to_char_type(0x7A));
9754 write_number(static_cast<std::uint32_t>(N));
9755 }
9756 // LCOV_EXCL_START
9757 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
9758 {
9759 oa->write_character(to_char_type(0x7B));
9760 write_number(static_cast<std::uint64_t>(N));
9761 }
9762 // LCOV_EXCL_STOP
9763
9764 // step 2: write the string
9765 oa->write_characters(
9766 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
9767 j.m_value.string->size());
9768 break;
9769 }
9770
9771 case value_t::array:
9772 {
9773 // step 1: write control byte and the array size
9774 const auto N = j.m_value.array->size();
9775 if (N <= 0x17)
9776 {
9777 write_number(static_cast<std::uint8_t>(0x80 + N));
9778 }
9779 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
9780 {
9781 oa->write_character(to_char_type(0x98));
9782 write_number(static_cast<std::uint8_t>(N));
9783 }
9784 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
9785 {
9786 oa->write_character(to_char_type(0x99));
9787 write_number(static_cast<std::uint16_t>(N));
9788 }
9789 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
9790 {
9791 oa->write_character(to_char_type(0x9A));
9792 write_number(static_cast<std::uint32_t>(N));
9793 }
9794 // LCOV_EXCL_START
9795 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
9796 {
9797 oa->write_character(to_char_type(0x9B));
9798 write_number(static_cast<std::uint64_t>(N));
9799 }
9800 // LCOV_EXCL_STOP
9801
9802 // step 2: write each element
9803 for (const auto& el : *j.m_value.array)
9804 {
9805 write_cbor(el);
9806 }
9807 break;
9808 }
9809
9810 case value_t::object:
9811 {
9812 // step 1: write control byte and the object size
9813 const auto N = j.m_value.object->size();
9814 if (N <= 0x17)
9815 {
9816 write_number(static_cast<std::uint8_t>(0xA0 + N));
9817 }
9818 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
9819 {
9820 oa->write_character(to_char_type(0xB8));
9821 write_number(static_cast<std::uint8_t>(N));
9822 }
9823 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
9824 {
9825 oa->write_character(to_char_type(0xB9));
9826 write_number(static_cast<std::uint16_t>(N));
9827 }
9828 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
9829 {
9830 oa->write_character(to_char_type(0xBA));
9831 write_number(static_cast<std::uint32_t>(N));
9832 }
9833 // LCOV_EXCL_START
9834 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
9835 {
9836 oa->write_character(to_char_type(0xBB));
9837 write_number(static_cast<std::uint64_t>(N));
9838 }
9839 // LCOV_EXCL_STOP
9840
9841 // step 2: write each element
9842 for (const auto& el : *j.m_value.object)
9843 {
9844 write_cbor(el.first);
9845 write_cbor(el.second);
9846 }
9847 break;
9848 }
9849
9850 default:
9851 break;
9852 }
9853 }
9854
9858 void write_msgpack(const BasicJsonType& j)
9859 {
9860 switch (j.type())
9861 {
9862 case value_t::null: // nil
9863 {
9864 oa->write_character(to_char_type(0xC0));
9865 break;
9866 }
9867
9868 case value_t::boolean: // true and false
9869 {
9870 oa->write_character(j.m_value.boolean
9871 ? to_char_type(0xC3)
9872 : to_char_type(0xC2));
9873 break;
9874 }
9875
9877 {
9878 if (j.m_value.number_integer >= 0)
9879 {
9880 // MessagePack does not differentiate between positive
9881 // signed integers and unsigned integers. Therefore, we used
9882 // the code from the value_t::number_unsigned case here.
9883 if (j.m_value.number_unsigned < 128)
9884 {
9885 // positive fixnum
9886 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
9887 }
9888 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
9889 {
9890 // uint 8
9891 oa->write_character(to_char_type(0xCC));
9892 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
9893 }
9894 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
9895 {
9896 // uint 16
9897 oa->write_character(to_char_type(0xCD));
9898 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
9899 }
9900 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
9901 {
9902 // uint 32
9903 oa->write_character(to_char_type(0xCE));
9904 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
9905 }
9906 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
9907 {
9908 // uint 64
9909 oa->write_character(to_char_type(0xCF));
9910 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
9911 }
9912 }
9913 else
9914 {
9915 if (j.m_value.number_integer >= -32)
9916 {
9917 // negative fixnum
9918 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
9919 }
9920 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
9921 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
9922 {
9923 // int 8
9924 oa->write_character(to_char_type(0xD0));
9925 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
9926 }
9927 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
9928 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
9929 {
9930 // int 16
9931 oa->write_character(to_char_type(0xD1));
9932 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
9933 }
9934 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
9935 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
9936 {
9937 // int 32
9938 oa->write_character(to_char_type(0xD2));
9939 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
9940 }
9941 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
9942 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
9943 {
9944 // int 64
9945 oa->write_character(to_char_type(0xD3));
9946 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
9947 }
9948 }
9949 break;
9950 }
9951
9953 {
9954 if (j.m_value.number_unsigned < 128)
9955 {
9956 // positive fixnum
9957 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
9958 }
9959 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
9960 {
9961 // uint 8
9962 oa->write_character(to_char_type(0xCC));
9963 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
9964 }
9965 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
9966 {
9967 // uint 16
9968 oa->write_character(to_char_type(0xCD));
9969 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
9970 }
9971 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
9972 {
9973 // uint 32
9974 oa->write_character(to_char_type(0xCE));
9975 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
9976 }
9977 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
9978 {
9979 // uint 64
9980 oa->write_character(to_char_type(0xCF));
9981 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
9982 }
9983 break;
9984 }
9985
9987 {
9988 oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
9989 write_number(j.m_value.number_float);
9990 break;
9991 }
9992
9993 case value_t::string:
9994 {
9995 // step 1: write control byte and the string length
9996 const auto N = j.m_value.string->size();
9997 if (N <= 31)
9998 {
9999 // fixstr
10000 write_number(static_cast<std::uint8_t>(0xA0 | N));
10001 }
10002 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
10003 {
10004 // str 8
10005 oa->write_character(to_char_type(0xD9));
10006 write_number(static_cast<std::uint8_t>(N));
10007 }
10008 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
10009 {
10010 // str 16
10011 oa->write_character(to_char_type(0xDA));
10012 write_number(static_cast<std::uint16_t>(N));
10013 }
10014 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
10015 {
10016 // str 32
10017 oa->write_character(to_char_type(0xDB));
10018 write_number(static_cast<std::uint32_t>(N));
10019 }
10020
10021 // step 2: write the string
10022 oa->write_characters(
10023 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
10024 j.m_value.string->size());
10025 break;
10026 }
10027
10028 case value_t::array:
10029 {
10030 // step 1: write control byte and the array size
10031 const auto N = j.m_value.array->size();
10032 if (N <= 15)
10033 {
10034 // fixarray
10035 write_number(static_cast<std::uint8_t>(0x90 | N));
10036 }
10037 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
10038 {
10039 // array 16
10040 oa->write_character(to_char_type(0xDC));
10041 write_number(static_cast<std::uint16_t>(N));
10042 }
10043 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
10044 {
10045 // array 32
10046 oa->write_character(to_char_type(0xDD));
10047 write_number(static_cast<std::uint32_t>(N));
10048 }
10049
10050 // step 2: write each element
10051 for (const auto& el : *j.m_value.array)
10052 {
10053 write_msgpack(el);
10054 }
10055 break;
10056 }
10057
10058 case value_t::object:
10059 {
10060 // step 1: write control byte and the object size
10061 const auto N = j.m_value.object->size();
10062 if (N <= 15)
10063 {
10064 // fixmap
10065 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
10066 }
10067 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
10068 {
10069 // map 16
10070 oa->write_character(to_char_type(0xDE));
10071 write_number(static_cast<std::uint16_t>(N));
10072 }
10073 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
10074 {
10075 // map 32
10076 oa->write_character(to_char_type(0xDF));
10077 write_number(static_cast<std::uint32_t>(N));
10078 }
10079
10080 // step 2: write each element
10081 for (const auto& el : *j.m_value.object)
10082 {
10083 write_msgpack(el.first);
10084 write_msgpack(el.second);
10085 }
10086 break;
10087 }
10088
10089 default:
10090 break;
10091 }
10092 }
10093
10100 void write_ubjson(const BasicJsonType& j, const bool use_count,
10101 const bool use_type, const bool add_prefix = true)
10102 {
10103 switch (j.type())
10104 {
10105 case value_t::null:
10106 {
10107 if (add_prefix)
10108 {
10109 oa->write_character(to_char_type('Z'));
10110 }
10111 break;
10112 }
10113
10114 case value_t::boolean:
10115 {
10116 if (add_prefix)
10117 {
10118 oa->write_character(j.m_value.boolean
10119 ? to_char_type('T')
10120 : to_char_type('F'));
10121 }
10122 break;
10123 }
10124
10126 {
10127 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
10128 break;
10129 }
10130
10132 {
10133 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
10134 break;
10135 }
10136
10138 {
10139 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
10140 break;
10141 }
10142
10143 case value_t::string:
10144 {
10145 if (add_prefix)
10146 {
10147 oa->write_character(to_char_type('S'));
10148 }
10149 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
10150 oa->write_characters(
10151 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
10152 j.m_value.string->size());
10153 break;
10154 }
10155
10156 case value_t::array:
10157 {
10158 if (add_prefix)
10159 {
10160 oa->write_character(to_char_type('['));
10161 }
10162
10163 bool prefix_required = true;
10164 if (use_type and not j.m_value.array->empty())
10165 {
10166 assert(use_count);
10167 const CharType first_prefix = ubjson_prefix(j.front());
10168 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
10169 [this, first_prefix](const BasicJsonType & v)
10170 {
10171 return ubjson_prefix(v) == first_prefix;
10172 });
10173
10174 if (same_prefix)
10175 {
10176 prefix_required = false;
10177 oa->write_character(to_char_type('$'));
10178 oa->write_character(first_prefix);
10179 }
10180 }
10181
10182 if (use_count)
10183 {
10184 oa->write_character(to_char_type('#'));
10185 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
10186 }
10187
10188 for (const auto& el : *j.m_value.array)
10189 {
10190 write_ubjson(el, use_count, use_type, prefix_required);
10191 }
10192
10193 if (not use_count)
10194 {
10195 oa->write_character(to_char_type(']'));
10196 }
10197
10198 break;
10199 }
10200
10201 case value_t::object:
10202 {
10203 if (add_prefix)
10204 {
10205 oa->write_character(to_char_type('{'));
10206 }
10207
10208 bool prefix_required = true;
10209 if (use_type and not j.m_value.object->empty())
10210 {
10211 assert(use_count);
10212 const CharType first_prefix = ubjson_prefix(j.front());
10213 const bool same_prefix = std::all_of(j.begin(), j.end(),
10214 [this, first_prefix](const BasicJsonType & v)
10215 {
10216 return ubjson_prefix(v) == first_prefix;
10217 });
10218
10219 if (same_prefix)
10220 {
10221 prefix_required = false;
10222 oa->write_character(to_char_type('$'));
10223 oa->write_character(first_prefix);
10224 }
10225 }
10226
10227 if (use_count)
10228 {
10229 oa->write_character(to_char_type('#'));
10230 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
10231 }
10232
10233 for (const auto& el : *j.m_value.object)
10234 {
10235 write_number_with_ubjson_prefix(el.first.size(), true);
10236 oa->write_characters(
10237 reinterpret_cast<const CharType*>(el.first.c_str()),
10238 el.first.size());
10239 write_ubjson(el.second, use_count, use_type, prefix_required);
10240 }
10241
10242 if (not use_count)
10243 {
10244 oa->write_character(to_char_type('}'));
10245 }
10246
10247 break;
10248 }
10249
10250 default:
10251 break;
10252 }
10253 }
10254
10255 private:
10257 // BSON //
10259
10264 static std::size_t calc_bson_entry_header_size(const string_t& name)
10265 {
10266 const auto it = name.find(static_cast<typename string_t::value_type>(0));
10267 if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
10268 {
10270 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
10271 }
10272
10273 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
10274 }
10275
10280 const std::uint8_t element_type)
10281 {
10282 oa->write_character(to_char_type(element_type)); // boolean
10283 oa->write_characters(
10284 reinterpret_cast<const CharType*>(name.c_str()),
10285 name.size() + 1u);
10286 }
10287
10292 const bool value)
10293 {
10294 write_bson_entry_header(name, 0x08);
10295 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
10296 }
10297
10301 void write_bson_double(const string_t& name,
10302 const double value)
10303 {
10304 write_bson_entry_header(name, 0x01);
10305 write_number<double, true>(value);
10306 }
10307
10311 static std::size_t calc_bson_string_size(const string_t& value)
10312 {
10313 return sizeof(std::int32_t) + value.size() + 1ul;
10314 }
10315
10319 void write_bson_string(const string_t& name,
10320 const string_t& value)
10321 {
10322 write_bson_entry_header(name, 0x02);
10323
10324 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
10325 oa->write_characters(
10326 reinterpret_cast<const CharType*>(value.c_str()),
10327 value.size() + 1);
10328 }
10329
10333 void write_bson_null(const string_t& name)
10334 {
10335 write_bson_entry_header(name, 0x0A);
10336 }
10337
10341 static std::size_t calc_bson_integer_size(const std::int64_t value)
10342 {
10343 return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
10344 ? sizeof(std::int32_t)
10345 : sizeof(std::int64_t);
10346 }
10347
10352 const std::int64_t value)
10353 {
10354 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
10355 {
10356 write_bson_entry_header(name, 0x10); // int32
10357 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
10358 }
10359 else
10360 {
10361 write_bson_entry_header(name, 0x12); // int64
10362 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
10363 }
10364 }
10365
10369 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
10370 {
10371 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
10372 ? sizeof(std::int32_t)
10373 : sizeof(std::int64_t);
10374 }
10375
10380 const std::uint64_t value)
10381 {
10382 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
10383 {
10384 write_bson_entry_header(name, 0x10 /* int32 */);
10385 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
10386 }
10387 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
10388 {
10389 write_bson_entry_header(name, 0x12 /* int64 */);
10390 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
10391 }
10392 else
10393 {
10394 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
10395 }
10396 }
10397
10402 const typename BasicJsonType::object_t& value)
10403 {
10404 write_bson_entry_header(name, 0x03); // object
10405 write_bson_object(value);
10406 }
10407
10411 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
10412 {
10413 std::size_t embedded_document_size = 0ul;
10414 std::size_t array_index = 0ul;
10415
10416 for (const auto& el : value)
10417 {
10418 embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el);
10419 }
10420
10421 return sizeof(std::int32_t) + embedded_document_size + 1ul;
10422 }
10423
10427 void write_bson_array(const string_t& name,
10428 const typename BasicJsonType::array_t& value)
10429 {
10430 write_bson_entry_header(name, 0x04); // array
10431 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
10432
10433 std::size_t array_index = 0ul;
10434
10435 for (const auto& el : value)
10436 {
10437 write_bson_element(std::to_string(array_index++), el);
10438 }
10439
10440 oa->write_character(to_char_type(0x00));
10441 }
10442
10447 static std::size_t calc_bson_element_size(const string_t& name,
10448 const BasicJsonType& j)
10449 {
10450 const auto header_size = calc_bson_entry_header_size(name);
10451 switch (j.type())
10452 {
10453 case value_t::object:
10454 return header_size + calc_bson_object_size(*j.m_value.object);
10455
10456 case value_t::array:
10457 return header_size + calc_bson_array_size(*j.m_value.array);
10458
10459 case value_t::boolean:
10460 return header_size + 1ul;
10461
10463 return header_size + 8ul;
10464
10466 return header_size + calc_bson_integer_size(j.m_value.number_integer);
10467
10469 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
10470
10471 case value_t::string:
10472 return header_size + calc_bson_string_size(*j.m_value.string);
10473
10474 case value_t::null:
10475 return header_size + 0ul;
10476
10477 // LCOV_EXCL_START
10478 default:
10479 assert(false);
10480 return 0ul;
10481 // LCOV_EXCL_STOP
10482 }
10483 }
10484
10493 const BasicJsonType& j)
10494 {
10495 switch (j.type())
10496 {
10497 case value_t::object:
10498 return write_bson_object_entry(name, *j.m_value.object);
10499
10500 case value_t::array:
10501 return write_bson_array(name, *j.m_value.array);
10502
10503 case value_t::boolean:
10504 return write_bson_boolean(name, j.m_value.boolean);
10505
10507 return write_bson_double(name, j.m_value.number_float);
10508
10510 return write_bson_integer(name, j.m_value.number_integer);
10511
10513 return write_bson_unsigned(name, j.m_value.number_unsigned);
10514
10515 case value_t::string:
10516 return write_bson_string(name, *j.m_value.string);
10517
10518 case value_t::null:
10519 return write_bson_null(name);
10520
10521 // LCOV_EXCL_START
10522 default:
10523 assert(false);
10524 return;
10525 // LCOV_EXCL_STOP
10526 }
10527 }
10528
10535 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
10536 {
10537 std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,
10538 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
10539 {
10540 return result += calc_bson_element_size(el.first, el.second);
10541 });
10542
10543 return sizeof(std::int32_t) + document_size + 1ul;
10544 }
10545
10550 void write_bson_object(const typename BasicJsonType::object_t& value)
10551 {
10552 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
10553
10554 for (const auto& el : value)
10555 {
10556 write_bson_element(el.first, el.second);
10557 }
10558
10559 oa->write_character(to_char_type(0x00));
10560 }
10561
10563 // CBOR //
10565
10566 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
10567 {
10568 return to_char_type(0xFA); // Single-Precision Float
10569 }
10570
10571 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
10572 {
10573 return to_char_type(0xFB); // Double-Precision Float
10574 }
10575
10577 // MsgPack //
10579
10580 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
10581 {
10582 return to_char_type(0xCA); // float 32
10583 }
10584
10585 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
10586 {
10587 return to_char_type(0xCB); // float 64
10588 }
10589
10591 // UBJSON //
10593
10594 // UBJSON: write number (floating point)
10595 template<typename NumberType, typename std::enable_if<
10596 std::is_floating_point<NumberType>::value, int>::type = 0>
10597 void write_number_with_ubjson_prefix(const NumberType n,
10598 const bool add_prefix)
10599 {
10600 if (add_prefix)
10601 {
10602 oa->write_character(get_ubjson_float_prefix(n));
10603 }
10604 write_number(n);
10605 }
10606
10607 // UBJSON: write number (unsigned integer)
10608 template<typename NumberType, typename std::enable_if<
10609 std::is_unsigned<NumberType>::value, int>::type = 0>
10610 void write_number_with_ubjson_prefix(const NumberType n,
10611 const bool add_prefix)
10612 {
10613 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
10614 {
10615 if (add_prefix)
10616 {
10617 oa->write_character(to_char_type('i')); // int8
10618 }
10619 write_number(static_cast<std::uint8_t>(n));
10620 }
10621 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
10622 {
10623 if (add_prefix)
10624 {
10625 oa->write_character(to_char_type('U')); // uint8
10626 }
10627 write_number(static_cast<std::uint8_t>(n));
10628 }
10629 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
10630 {
10631 if (add_prefix)
10632 {
10633 oa->write_character(to_char_type('I')); // int16
10634 }
10635 write_number(static_cast<std::int16_t>(n));
10636 }
10637 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
10638 {
10639 if (add_prefix)
10640 {
10641 oa->write_character(to_char_type('l')); // int32
10642 }
10643 write_number(static_cast<std::int32_t>(n));
10644 }
10645 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
10646 {
10647 if (add_prefix)
10648 {
10649 oa->write_character(to_char_type('L')); // int64
10650 }
10651 write_number(static_cast<std::int64_t>(n));
10652 }
10653 else
10654 {
10655 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
10656 }
10657 }
10658
10659 // UBJSON: write number (signed integer)
10660 template<typename NumberType, typename std::enable_if<
10661 std::is_signed<NumberType>::value and
10662 not std::is_floating_point<NumberType>::value, int>::type = 0>
10663 void write_number_with_ubjson_prefix(const NumberType n,
10664 const bool add_prefix)
10665 {
10666 if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
10667 {
10668 if (add_prefix)
10669 {
10670 oa->write_character(to_char_type('i')); // int8
10671 }
10672 write_number(static_cast<std::int8_t>(n));
10673 }
10674 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
10675 {
10676 if (add_prefix)
10677 {
10678 oa->write_character(to_char_type('U')); // uint8
10679 }
10680 write_number(static_cast<std::uint8_t>(n));
10681 }
10682 else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
10683 {
10684 if (add_prefix)
10685 {
10686 oa->write_character(to_char_type('I')); // int16
10687 }
10688 write_number(static_cast<std::int16_t>(n));
10689 }
10690 else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
10691 {
10692 if (add_prefix)
10693 {
10694 oa->write_character(to_char_type('l')); // int32
10695 }
10696 write_number(static_cast<std::int32_t>(n));
10697 }
10698 else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
10699 {
10700 if (add_prefix)
10701 {
10702 oa->write_character(to_char_type('L')); // int64
10703 }
10704 write_number(static_cast<std::int64_t>(n));
10705 }
10706 // LCOV_EXCL_START
10707 else
10708 {
10709 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
10710 }
10711 // LCOV_EXCL_STOP
10712 }
10713
10723 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
10724 {
10725 switch (j.type())
10726 {
10727 case value_t::null:
10728 return 'Z';
10729
10730 case value_t::boolean:
10731 return j.m_value.boolean ? 'T' : 'F';
10732
10734 {
10735 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
10736 {
10737 return 'i';
10738 }
10739 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
10740 {
10741 return 'U';
10742 }
10743 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
10744 {
10745 return 'I';
10746 }
10747 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
10748 {
10749 return 'l';
10750 }
10751 // no check and assume int64_t (see note above)
10752 return 'L';
10753 }
10754
10756 {
10757 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int8_t>::max)())
10758 {
10759 return 'i';
10760 }
10761 if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
10762 {
10763 return 'U';
10764 }
10765 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int16_t>::max)())
10766 {
10767 return 'I';
10768 }
10769 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int32_t>::max)())
10770 {
10771 return 'l';
10772 }
10773 // no check and assume int64_t (see note above)
10774 return 'L';
10775 }
10776
10778 return get_ubjson_float_prefix(j.m_value.number_float);
10779
10780 case value_t::string:
10781 return 'S';
10782
10783 case value_t::array:
10784 return '[';
10785
10786 case value_t::object:
10787 return '{';
10788
10789 default: // discarded values
10790 return 'N';
10791 }
10792 }
10793
10794 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
10795 {
10796 return 'd'; // float 32
10797 }
10798
10799 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
10800 {
10801 return 'D'; // float 64
10802 }
10803
10805 // Utility functions //
10807
10808 /*
10809 @brief write a number to output input
10810 @param[in] n number of type @a NumberType
10811 @tparam NumberType the type of the number
10812 @tparam OutputIsLittleEndian Set to true if output data is
10813 required to be little endian
10814
10815 @note This function needs to respect the system's endianess, because bytes
10816 in CBOR, MessagePack, and UBJSON are stored in network order (big
10817 endian) and therefore need reordering on little endian systems.
10818 */
10819 template<typename NumberType, bool OutputIsLittleEndian = false>
10820 void write_number(const NumberType n)
10821 {
10822 // step 1: write number to array of length NumberType
10823 std::array<CharType, sizeof(NumberType)> vec;
10824 std::memcpy(vec.data(), &n, sizeof(NumberType));
10825
10826 // step 2: write array to output (with possible reordering)
10827 if (is_little_endian != OutputIsLittleEndian)
10828 {
10829 // reverse byte order prior to conversion if necessary
10830 std::reverse(vec.begin(), vec.end());
10831 }
10832
10833 oa->write_characters(vec.data(), sizeof(NumberType));
10834 }
10835
10836 public:
10837 // The following to_char_type functions are implement the conversion
10838 // between uint8_t and CharType. In case CharType is not unsigned,
10839 // such a conversion is required to allow values greater than 128.
10840 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
10841 template < typename C = CharType,
10842 enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
10843 static constexpr CharType to_char_type(std::uint8_t x) noexcept
10844 {
10845 return *reinterpret_cast<char*>(&x);
10846 }
10847
10848 template < typename C = CharType,
10849 enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
10850 static CharType to_char_type(std::uint8_t x) noexcept
10851 {
10852 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
10853 static_assert(std::is_pod<CharType>::value, "CharType must be POD");
10854 CharType result;
10855 std::memcpy(&result, &x, sizeof(x));
10856 return result;
10857 }
10858
10859 template<typename C = CharType,
10861 static constexpr CharType to_char_type(std::uint8_t x) noexcept
10862 {
10863 return x;
10864 }
10865
10866 template < typename InputCharType, typename C = CharType,
10867 enable_if_t <
10868 std::is_signed<C>::value and
10869 std::is_signed<char>::value and
10870 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
10871 > * = nullptr >
10872 static constexpr CharType to_char_type(InputCharType x) noexcept
10873 {
10874 return x;
10875 }
10876
10877 private:
10880
10883 };
10884 } // namespace detail
10885} // namespace nlohmann
10886
10887// #include <nlohmann/detail/output/output_adapters.hpp>
10888
10889// #include <nlohmann/detail/output/serializer.hpp>
10890
10891
10892#include <algorithm> // reverse, remove, fill, find, none_of
10893#include <array> // array
10894#include <cassert> // assert
10895#include <ciso646> // and, or
10896#include <clocale> // localeconv, lconv
10897#include <cmath> // labs, isfinite, isnan, signbit
10898#include <cstddef> // size_t, ptrdiff_t
10899#include <cstdint> // uint8_t
10900#include <cstdio> // snprintf
10901#include <limits> // numeric_limits
10902#include <string> // string
10903#include <type_traits> // is_same
10904#include <utility> // move
10905
10906// #include <nlohmann/detail/conversions/to_chars.hpp>
10907
10908
10909#include <array> // array
10910#include <cassert> // assert
10911#include <ciso646> // or, and, not
10912#include <cmath> // signbit, isfinite
10913#include <cstdint> // intN_t, uintN_t
10914#include <cstring> // memcpy, memmove
10915#include <limits> // numeric_limits
10916#include <type_traits> // conditional
10917
10918namespace nlohmann
10919{
10920 namespace detail
10921 {
10922
10942 namespace dtoa_impl
10943 {
10944
10945 template <typename Target, typename Source>
10946 Target reinterpret_bits(const Source source)
10947 {
10948 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
10949
10950 Target target;
10951 std::memcpy(&target, &source, sizeof(Source));
10952 return target;
10953 }
10954
10955 struct diyfp // f * 2^e
10956 {
10957 static constexpr int kPrecision = 64; // = q
10958
10959 std::uint64_t f = 0;
10960 int e = 0;
10961
10962 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
10963
10968 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
10969 {
10970 assert(x.e == y.e);
10971 assert(x.f >= y.f);
10972
10973 return {x.f - y.f, x.e};
10974 }
10975
10980 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
10981 {
10982 static_assert(kPrecision == 64, "internal error");
10983
10984 // Computes:
10985 // f = round((x.f * y.f) / 2^q)
10986 // e = x.e + y.e + q
10987
10988 // Emulate the 64-bit * 64-bit multiplication:
10989 //
10990 // p = u * v
10991 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
10992 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
10993 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
10994 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
10995 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
10996 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
10997 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
10998 //
10999 // (Since Q might be larger than 2^32 - 1)
11000 //
11001 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
11002 //
11003 // (Q_hi + H does not overflow a 64-bit int)
11004 //
11005 // = p_lo + 2^64 p_hi
11006
11007 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
11008 const std::uint64_t u_hi = x.f >> 32u;
11009 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
11010 const std::uint64_t v_hi = y.f >> 32u;
11011
11012 const std::uint64_t p0 = u_lo * v_lo;
11013 const std::uint64_t p1 = u_lo * v_hi;
11014 const std::uint64_t p2 = u_hi * v_lo;
11015 const std::uint64_t p3 = u_hi * v_hi;
11016
11017 const std::uint64_t p0_hi = p0 >> 32u;
11018 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
11019 const std::uint64_t p1_hi = p1 >> 32u;
11020 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
11021 const std::uint64_t p2_hi = p2 >> 32u;
11022
11023 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
11024
11025 // The full product might now be computed as
11026 //
11027 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
11028 // p_lo = p0_lo + (Q << 32)
11029 //
11030 // But in this particular case here, the full p_lo is not required.
11031 // Effectively we only need to add the highest bit in p_lo to p_hi (and
11032 // Q_hi + 1 does not overflow).
11033
11034 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
11035
11036 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
11037
11038 return {h, x.e + y.e + 64};
11039 }
11040
11045 static diyfp normalize(diyfp x) noexcept
11046 {
11047 assert(x.f != 0);
11048
11049 while ((x.f >> 63u) == 0)
11050 {
11051 x.f <<= 1u;
11052 x.e--;
11053 }
11054
11055 return x;
11056 }
11057
11062 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
11063 {
11064 const int delta = x.e - target_exponent;
11065
11066 assert(delta >= 0);
11067 assert(((x.f << delta) >> delta) == x.f);
11068
11069 return {x.f << delta, target_exponent};
11070 }
11071 };
11072
11074 {
11078 };
11079
11086 template <typename FloatType>
11088 {
11089 assert(std::isfinite(value));
11090 assert(value > 0);
11091
11092 // Convert the IEEE representation into a diyfp.
11093 //
11094 // If v is denormal:
11095 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
11096 // If v is normalized:
11097 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
11098
11099 static_assert(std::numeric_limits<FloatType>::is_iec559,
11100 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
11101
11102 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
11103 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
11104 constexpr int kMinExp = 1 - kBias;
11105 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
11106
11107 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
11108
11109 const std::uint64_t bits = reinterpret_bits<bits_type>(value);
11110 const std::uint64_t E = bits >> (kPrecision - 1);
11111 const std::uint64_t F = bits & (kHiddenBit - 1);
11112
11113 const bool is_denormal = E == 0;
11114 const diyfp v = is_denormal
11115 ? diyfp(F, kMinExp)
11116 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
11117
11118 // Compute the boundaries m- and m+ of the floating-point value
11119 // v = f * 2^e.
11120 //
11121 // Determine v- and v+, the floating-point predecessor and successor if v,
11122 // respectively.
11123 //
11124 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
11125 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
11126 //
11127 // v+ = v + 2^e
11128 //
11129 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
11130 // between m- and m+ round to v, regardless of how the input rounding
11131 // algorithm breaks ties.
11132 //
11133 // ---+-------------+-------------+-------------+-------------+--- (A)
11134 // v- m- v m+ v+
11135 //
11136 // -----------------+------+------+-------------+-------------+--- (B)
11137 // v- m- v m+ v+
11138
11139 const bool lower_boundary_is_closer = F == 0 and E > 1;
11140 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
11141 const diyfp m_minus = lower_boundary_is_closer
11142 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
11143 : diyfp(2 * v.f - 1, v.e - 1); // (A)
11144
11145 // Determine the normalized w+ = m+.
11146 const diyfp w_plus = diyfp::normalize(m_plus);
11147
11148 // Determine w- = m- such that e_(w-) = e_(w+).
11149 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
11150
11151 return {diyfp::normalize(v), w_minus, w_plus};
11152 }
11153
11154// Given normalized diyfp w, Grisu needs to find a (normalized) cached
11155// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
11156// within a certain range [alpha, gamma] (Definition 3.2 from [1])
11157//
11158// alpha <= e = e_c + e_w + q <= gamma
11159//
11160// or
11161//
11162// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
11163// <= f_c * f_w * 2^gamma
11164//
11165// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
11166//
11167// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
11168//
11169// or
11170//
11171// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
11172//
11173// The choice of (alpha,gamma) determines the size of the table and the form of
11174// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
11175// in practice:
11176//
11177// The idea is to cut the number c * w = f * 2^e into two parts, which can be
11178// processed independently: An integral part p1, and a fractional part p2:
11179//
11180// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
11181// = (f div 2^-e) + (f mod 2^-e) * 2^e
11182// = p1 + p2 * 2^e
11183//
11184// The conversion of p1 into decimal form requires a series of divisions and
11185// modulos by (a power of) 10. These operations are faster for 32-bit than for
11186// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
11187// achieved by choosing
11188//
11189// -e >= 32 or e <= -32 := gamma
11190//
11191// In order to convert the fractional part
11192//
11193// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
11194//
11195// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
11196// d[-i] are extracted in order:
11197//
11198// (10 * p2) div 2^-e = d[-1]
11199// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
11200//
11201// The multiplication by 10 must not overflow. It is sufficient to choose
11202//
11203// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
11204//
11205// Since p2 = f mod 2^-e < 2^-e,
11206//
11207// -e <= 60 or e >= -60 := alpha
11208
11209 constexpr int kAlpha = -60;
11210 constexpr int kGamma = -32;
11211
11212 struct cached_power // c = f * 2^e ~= 10^k
11213 {
11214 std::uint64_t f;
11215 int e;
11216 int k;
11217 };
11218
11227 {
11228 // Now
11229 //
11230 // alpha <= e_c + e + q <= gamma (1)
11231 // ==> f_c * 2^alpha <= c * 2^e * 2^q
11232 //
11233 // and since the c's are normalized, 2^(q-1) <= f_c,
11234 //
11235 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
11236 // ==> 2^(alpha - e - 1) <= c
11237 //
11238 // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
11239 //
11240 // k = ceil( log_10( 2^(alpha - e - 1) ) )
11241 // = ceil( (alpha - e - 1) * log_10(2) )
11242 //
11243 // From the paper:
11244 // "In theory the result of the procedure could be wrong since c is rounded,
11245 // and the computation itself is approximated [...]. In practice, however,
11246 // this simple function is sufficient."
11247 //
11248 // For IEEE double precision floating-point numbers converted into
11249 // normalized diyfp's w = f * 2^e, with q = 64,
11250 //
11251 // e >= -1022 (min IEEE exponent)
11252 // -52 (p - 1)
11253 // -52 (p - 1, possibly normalize denormal IEEE numbers)
11254 // -11 (normalize the diyfp)
11255 // = -1137
11256 //
11257 // and
11258 //
11259 // e <= +1023 (max IEEE exponent)
11260 // -52 (p - 1)
11261 // -11 (normalize the diyfp)
11262 // = 960
11263 //
11264 // This binary exponent range [-1137,960] results in a decimal exponent
11265 // range [-307,324]. One does not need to store a cached power for each
11266 // k in this range. For each such k it suffices to find a cached power
11267 // such that the exponent of the product lies in [alpha,gamma].
11268 // This implies that the difference of the decimal exponents of adjacent
11269 // table entries must be less than or equal to
11270 //
11271 // floor( (gamma - alpha) * log_10(2) ) = 8.
11272 //
11273 // (A smaller distance gamma-alpha would require a larger table.)
11274
11275 // NB:
11276 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
11277
11278 constexpr int kCachedPowersMinDecExp = -300;
11279 constexpr int kCachedPowersDecStep = 8;
11280
11281 static constexpr std::array<cached_power, 79> kCachedPowers =
11282 {
11283 {
11284 { 0xAB70FE17C79AC6CA, -1060, -300 },
11285 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
11286 { 0xBE5691EF416BD60C, -1007, -284 },
11287 { 0x8DD01FAD907FFC3C, -980, -276 },
11288 { 0xD3515C2831559A83, -954, -268 },
11289 { 0x9D71AC8FADA6C9B5, -927, -260 },
11290 { 0xEA9C227723EE8BCB, -901, -252 },
11291 { 0xAECC49914078536D, -874, -244 },
11292 { 0x823C12795DB6CE57, -847, -236 },
11293 { 0xC21094364DFB5637, -821, -228 },
11294 { 0x9096EA6F3848984F, -794, -220 },
11295 { 0xD77485CB25823AC7, -768, -212 },
11296 { 0xA086CFCD97BF97F4, -741, -204 },
11297 { 0xEF340A98172AACE5, -715, -196 },
11298 { 0xB23867FB2A35B28E, -688, -188 },
11299 { 0x84C8D4DFD2C63F3B, -661, -180 },
11300 { 0xC5DD44271AD3CDBA, -635, -172 },
11301 { 0x936B9FCEBB25C996, -608, -164 },
11302 { 0xDBAC6C247D62A584, -582, -156 },
11303 { 0xA3AB66580D5FDAF6, -555, -148 },
11304 { 0xF3E2F893DEC3F126, -529, -140 },
11305 { 0xB5B5ADA8AAFF80B8, -502, -132 },
11306 { 0x87625F056C7C4A8B, -475, -124 },
11307 { 0xC9BCFF6034C13053, -449, -116 },
11308 { 0x964E858C91BA2655, -422, -108 },
11309 { 0xDFF9772470297EBD, -396, -100 },
11310 { 0xA6DFBD9FB8E5B88F, -369, -92 },
11311 { 0xF8A95FCF88747D94, -343, -84 },
11312 { 0xB94470938FA89BCF, -316, -76 },
11313 { 0x8A08F0F8BF0F156B, -289, -68 },
11314 { 0xCDB02555653131B6, -263, -60 },
11315 { 0x993FE2C6D07B7FAC, -236, -52 },
11316 { 0xE45C10C42A2B3B06, -210, -44 },
11317 { 0xAA242499697392D3, -183, -36 },
11318 { 0xFD87B5F28300CA0E, -157, -28 },
11319 { 0xBCE5086492111AEB, -130, -20 },
11320 { 0x8CBCCC096F5088CC, -103, -12 },
11321 { 0xD1B71758E219652C, -77, -4 },
11322 { 0x9C40000000000000, -50, 4 },
11323 { 0xE8D4A51000000000, -24, 12 },
11324 { 0xAD78EBC5AC620000, 3, 20 },
11325 { 0x813F3978F8940984, 30, 28 },
11326 { 0xC097CE7BC90715B3, 56, 36 },
11327 { 0x8F7E32CE7BEA5C70, 83, 44 },
11328 { 0xD5D238A4ABE98068, 109, 52 },
11329 { 0x9F4F2726179A2245, 136, 60 },
11330 { 0xED63A231D4C4FB27, 162, 68 },
11331 { 0xB0DE65388CC8ADA8, 189, 76 },
11332 { 0x83C7088E1AAB65DB, 216, 84 },
11333 { 0xC45D1DF942711D9A, 242, 92 },
11334 { 0x924D692CA61BE758, 269, 100 },
11335 { 0xDA01EE641A708DEA, 295, 108 },
11336 { 0xA26DA3999AEF774A, 322, 116 },
11337 { 0xF209787BB47D6B85, 348, 124 },
11338 { 0xB454E4A179DD1877, 375, 132 },
11339 { 0x865B86925B9BC5C2, 402, 140 },
11340 { 0xC83553C5C8965D3D, 428, 148 },
11341 { 0x952AB45CFA97A0B3, 455, 156 },
11342 { 0xDE469FBD99A05FE3, 481, 164 },
11343 { 0xA59BC234DB398C25, 508, 172 },
11344 { 0xF6C69A72A3989F5C, 534, 180 },
11345 { 0xB7DCBF5354E9BECE, 561, 188 },
11346 { 0x88FCF317F22241E2, 588, 196 },
11347 { 0xCC20CE9BD35C78A5, 614, 204 },
11348 { 0x98165AF37B2153DF, 641, 212 },
11349 { 0xE2A0B5DC971F303A, 667, 220 },
11350 { 0xA8D9D1535CE3B396, 694, 228 },
11351 { 0xFB9B7CD9A4A7443C, 720, 236 },
11352 { 0xBB764C4CA7A44410, 747, 244 },
11353 { 0x8BAB8EEFB6409C1A, 774, 252 },
11354 { 0xD01FEF10A657842C, 800, 260 },
11355 { 0x9B10A4E5E9913129, 827, 268 },
11356 { 0xE7109BFBA19C0C9D, 853, 276 },
11357 { 0xAC2820D9623BF429, 880, 284 },
11358 { 0x80444B5E7AA7CF85, 907, 292 },
11359 { 0xBF21E44003ACDD2D, 933, 300 },
11360 { 0x8E679C2F5E44FF8F, 960, 308 },
11361 { 0xD433179D9C8CB841, 986, 316 },
11362 { 0x9E19DB92B4E31BA9, 1013, 324 },
11363 }
11364 };
11365
11366 // This computation gives exactly the same results for k as
11367 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
11368 // for |e| <= 1500, but doesn't require floating-point operations.
11369 // NB: log_10(2) ~= 78913 / 2^18
11370 assert(e >= -1500);
11371 assert(e <= 1500);
11372 const int f = kAlpha - e - 1;
11373 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
11374
11375 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
11376 assert(index >= 0);
11377 assert(static_cast<std::size_t>(index) < kCachedPowers.size());
11378
11379 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
11380 assert(kAlpha <= cached.e + e + 64);
11381 assert(kGamma >= cached.e + e + 64);
11382
11383 return cached;
11384 }
11385
11390 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
11391 {
11392 // LCOV_EXCL_START
11393 if (n >= 1000000000)
11394 {
11395 pow10 = 1000000000;
11396 return 10;
11397 }
11398 // LCOV_EXCL_STOP
11399 else if (n >= 100000000)
11400 {
11401 pow10 = 100000000;
11402 return 9;
11403 }
11404 else if (n >= 10000000)
11405 {
11406 pow10 = 10000000;
11407 return 8;
11408 }
11409 else if (n >= 1000000)
11410 {
11411 pow10 = 1000000;
11412 return 7;
11413 }
11414 else if (n >= 100000)
11415 {
11416 pow10 = 100000;
11417 return 6;
11418 }
11419 else if (n >= 10000)
11420 {
11421 pow10 = 10000;
11422 return 5;
11423 }
11424 else if (n >= 1000)
11425 {
11426 pow10 = 1000;
11427 return 4;
11428 }
11429 else if (n >= 100)
11430 {
11431 pow10 = 100;
11432 return 3;
11433 }
11434 else if (n >= 10)
11435 {
11436 pow10 = 10;
11437 return 2;
11438 }
11439 else
11440 {
11441 pow10 = 1;
11442 return 1;
11443 }
11444 }
11445
11446 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
11447 std::uint64_t rest, std::uint64_t ten_k)
11448 {
11449 assert(len >= 1);
11450 assert(dist <= delta);
11451 assert(rest <= delta);
11452 assert(ten_k > 0);
11453
11454 // <--------------------------- delta ---->
11455 // <---- dist --------->
11456 // --------------[------------------+-------------------]--------------
11457 // M- w M+
11458 //
11459 // ten_k
11460 // <------>
11461 // <---- rest ---->
11462 // --------------[------------------+----+--------------]--------------
11463 // w V
11464 // = buf * 10^k
11465 //
11466 // ten_k represents a unit-in-the-last-place in the decimal representation
11467 // stored in buf.
11468 // Decrement buf by ten_k while this takes buf closer to w.
11469
11470 // The tests are written in this order to avoid overflow in unsigned
11471 // integer arithmetic.
11472
11473 while (rest < dist
11474 and delta - rest >= ten_k
11475 and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
11476 {
11477 assert(buf[len - 1] != '0');
11478 buf[len - 1]--;
11479 rest += ten_k;
11480 }
11481 }
11482
11487 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
11488 diyfp M_minus, diyfp w, diyfp M_plus)
11489 {
11490 static_assert(kAlpha >= -60, "internal error");
11491 static_assert(kGamma <= -32, "internal error");
11492
11493 // Generates the digits (and the exponent) of a decimal floating-point
11494 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
11495 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
11496 //
11497 // <--------------------------- delta ---->
11498 // <---- dist --------->
11499 // --------------[------------------+-------------------]--------------
11500 // M- w M+
11501 //
11502 // Grisu2 generates the digits of M+ from left to right and stops as soon as
11503 // V is in [M-,M+].
11504
11505 assert(M_plus.e >= kAlpha);
11506 assert(M_plus.e <= kGamma);
11507
11508 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
11509 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
11510
11511 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
11512 //
11513 // M+ = f * 2^e
11514 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
11515 // = ((p1 ) * 2^-e + (p2 )) * 2^e
11516 // = p1 + p2 * 2^e
11517
11518 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
11519
11520 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
11521 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
11522
11523 // 1)
11524 //
11525 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
11526
11527 assert(p1 > 0);
11528
11529 std::uint32_t pow10;
11530 const int k = find_largest_pow10(p1, pow10);
11531
11532 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
11533 //
11534 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
11535 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
11536 //
11537 // M+ = p1 + p2 * 2^e
11538 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
11539 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
11540 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
11541 //
11542 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
11543 //
11544 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
11545 //
11546 // but stop as soon as
11547 //
11548 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
11549
11550 int n = k;
11551 while (n > 0)
11552 {
11553 // Invariants:
11554 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
11555 // pow10 = 10^(n-1) <= p1 < 10^n
11556 //
11557 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
11558 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
11559 //
11560 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
11561 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
11562 //
11563 assert(d <= 9);
11564 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
11565 //
11566 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
11567 //
11568 p1 = r;
11569 n--;
11570 //
11571 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
11572 // pow10 = 10^n
11573 //
11574
11575 // Now check if enough digits have been generated.
11576 // Compute
11577 //
11578 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
11579 //
11580 // Note:
11581 // Since rest and delta share the same exponent e, it suffices to
11582 // compare the significands.
11583 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
11584 if (rest <= delta)
11585 {
11586 // V = buffer * 10^n, with M- <= V <= M+.
11587
11588 decimal_exponent += n;
11589
11590 // We may now just stop. But instead look if the buffer could be
11591 // decremented to bring V closer to w.
11592 //
11593 // pow10 = 10^n is now 1 ulp in the decimal representation V.
11594 // The rounding procedure works with diyfp's with an implicit
11595 // exponent of e.
11596 //
11597 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
11598 //
11599 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
11600 grisu2_round(buffer, length, dist, delta, rest, ten_n);
11601
11602 return;
11603 }
11604
11605 pow10 /= 10;
11606 //
11607 // pow10 = 10^(n-1) <= p1 < 10^n
11608 // Invariants restored.
11609 }
11610
11611 // 2)
11612 //
11613 // The digits of the integral part have been generated:
11614 //
11615 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
11616 // = buffer + p2 * 2^e
11617 //
11618 // Now generate the digits of the fractional part p2 * 2^e.
11619 //
11620 // Note:
11621 // No decimal point is generated: the exponent is adjusted instead.
11622 //
11623 // p2 actually represents the fraction
11624 //
11625 // p2 * 2^e
11626 // = p2 / 2^-e
11627 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
11628 //
11629 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
11630 //
11631 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
11632 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
11633 //
11634 // using
11635 //
11636 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
11637 // = ( d) * 2^-e + ( r)
11638 //
11639 // or
11640 // 10^m * p2 * 2^e = d + r * 2^e
11641 //
11642 // i.e.
11643 //
11644 // M+ = buffer + p2 * 2^e
11645 // = buffer + 10^-m * (d + r * 2^e)
11646 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
11647 //
11648 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
11649
11650 assert(p2 > delta);
11651
11652 int m = 0;
11653 for (;;)
11654 {
11655 // Invariant:
11656 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
11657 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
11658 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
11659 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
11660 //
11661 assert(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
11662 p2 *= 10;
11663 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
11664 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
11665 //
11666 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
11667 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
11668 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
11669 //
11670 assert(d <= 9);
11671 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
11672 //
11673 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
11674 //
11675 p2 = r;
11676 m++;
11677 //
11678 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
11679 // Invariant restored.
11680
11681 // Check if enough digits have been generated.
11682 //
11683 // 10^-m * p2 * 2^e <= delta * 2^e
11684 // p2 * 2^e <= 10^m * delta * 2^e
11685 // p2 <= 10^m * delta
11686 delta *= 10;
11687 dist *= 10;
11688 if (p2 <= delta)
11689 {
11690 break;
11691 }
11692 }
11693
11694 // V = buffer * 10^-m, with M- <= V <= M+.
11695
11696 decimal_exponent -= m;
11697
11698 // 1 ulp in the decimal representation is now 10^-m.
11699 // Since delta and dist are now scaled by 10^m, we need to do the
11700 // same with ulp in order to keep the units in sync.
11701 //
11702 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
11703 //
11704 const std::uint64_t ten_m = one.f;
11705 grisu2_round(buffer, length, dist, delta, p2, ten_m);
11706
11707 // By construction this algorithm generates the shortest possible decimal
11708 // number (Loitsch, Theorem 6.2) which rounds back to w.
11709 // For an input number of precision p, at least
11710 //
11711 // N = 1 + ceil(p * log_10(2))
11712 //
11713 // decimal digits are sufficient to identify all binary floating-point
11714 // numbers (Matula, "In-and-Out conversions").
11715 // This implies that the algorithm does not produce more than N decimal
11716 // digits.
11717 //
11718 // N = 17 for p = 53 (IEEE double precision)
11719 // N = 9 for p = 24 (IEEE single precision)
11720 }
11721
11727 inline void grisu2(char* buf, int& len, int& decimal_exponent,
11728 diyfp m_minus, diyfp v, diyfp m_plus)
11729 {
11730 assert(m_plus.e == m_minus.e);
11731 assert(m_plus.e == v.e);
11732
11733 // --------(-----------------------+-----------------------)-------- (A)
11734 // m- v m+
11735 //
11736 // --------------------(-----------+-----------------------)-------- (B)
11737 // m- v m+
11738 //
11739 // First scale v (and m- and m+) such that the exponent is in the range
11740 // [alpha, gamma].
11741
11743
11744 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
11745
11746 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
11747 const diyfp w = diyfp::mul(v, c_minus_k);
11748 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
11749 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
11750
11751 // ----(---+---)---------------(---+---)---------------(---+---)----
11752 // w- w w+
11753 // = c*m- = c*v = c*m+
11754 //
11755 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
11756 // w+ are now off by a small amount.
11757 // In fact:
11758 //
11759 // w - v * 10^k < 1 ulp
11760 //
11761 // To account for this inaccuracy, add resp. subtract 1 ulp.
11762 //
11763 // --------+---[---------------(---+---)---------------]---+--------
11764 // w- M- w M+ w+
11765 //
11766 // Now any number in [M-, M+] (bounds included) will round to w when input,
11767 // regardless of how the input rounding algorithm breaks ties.
11768 //
11769 // And digit_gen generates the shortest possible such number in [M-, M+].
11770 // Note that this does not mean that Grisu2 always generates the shortest
11771 // possible number in the interval (m-, m+).
11772 const diyfp M_minus(w_minus.f + 1, w_minus.e);
11773 const diyfp M_plus (w_plus.f - 1, w_plus.e );
11774
11775 decimal_exponent = -cached.k; // = -(-k) = k
11776
11777 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
11778 }
11779
11785 template <typename FloatType>
11786 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
11787 {
11788 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
11789 "internal error: not enough precision");
11790
11791 assert(std::isfinite(value));
11792 assert(value > 0);
11793
11794 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
11795 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
11796 // decimal representations are not exactly "short".
11797 //
11798 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
11799 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
11800 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
11801 // does.
11802 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
11803 // representation using the corresponding std::from_chars function recovers value exactly". That
11804 // indicates that single precision floating-point numbers should be recovered using
11805 // 'std::strtof'.
11806 //
11807 // NB: If the neighbors are computed for single-precision numbers, there is a single float
11808 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
11809 // value is off by 1 ulp.
11810#if 0
11811 const boundaries w = compute_boundaries(static_cast<double>(value));
11812#else
11813 const boundaries w = compute_boundaries(value);
11814#endif
11815
11816 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
11817 }
11818
11824 inline char* append_exponent(char* buf, int e)
11825 {
11826 assert(e > -1000);
11827 assert(e < 1000);
11828
11829 if (e < 0)
11830 {
11831 e = -e;
11832 *buf++ = '-';
11833 }
11834 else
11835 {
11836 *buf++ = '+';
11837 }
11838
11839 auto k = static_cast<std::uint32_t>(e);
11840 if (k < 10)
11841 {
11842 // Always print at least two digits in the exponent.
11843 // This is for compatibility with printf("%g").
11844 *buf++ = '0';
11845 *buf++ = static_cast<char>('0' + k);
11846 }
11847 else if (k < 100)
11848 {
11849 *buf++ = static_cast<char>('0' + k / 10);
11850 k %= 10;
11851 *buf++ = static_cast<char>('0' + k);
11852 }
11853 else
11854 {
11855 *buf++ = static_cast<char>('0' + k / 100);
11856 k %= 100;
11857 *buf++ = static_cast<char>('0' + k / 10);
11858 k %= 10;
11859 *buf++ = static_cast<char>('0' + k);
11860 }
11861
11862 return buf;
11863 }
11864
11874 inline char* format_buffer(char* buf, int len, int decimal_exponent,
11875 int min_exp, int max_exp)
11876 {
11877 assert(min_exp < 0);
11878 assert(max_exp > 0);
11879
11880 const int k = len;
11881 const int n = len + decimal_exponent;
11882
11883 // v = buf * 10^(n-k)
11884 // k is the length of the buffer (number of decimal digits)
11885 // n is the position of the decimal point relative to the start of the buffer.
11886
11887 if (k <= n and n <= max_exp)
11888 {
11889 // digits[000]
11890 // len <= max_exp + 2
11891
11892 std::memset(buf + k, '0', static_cast<size_t>(n - k));
11893 // Make it look like a floating-point number (#362, #378)
11894 buf[n + 0] = '.';
11895 buf[n + 1] = '0';
11896 return buf + (n + 2);
11897 }
11898
11899 if (0 < n and n <= max_exp)
11900 {
11901 // dig.its
11902 // len <= max_digits10 + 1
11903
11904 assert(k > n);
11905
11906 std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
11907 buf[n] = '.';
11908 return buf + (k + 1);
11909 }
11910
11911 if (min_exp < n and n <= 0)
11912 {
11913 // 0.[000]digits
11914 // len <= 2 + (-min_exp - 1) + max_digits10
11915
11916 std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
11917 buf[0] = '0';
11918 buf[1] = '.';
11919 std::memset(buf + 2, '0', static_cast<size_t>(-n));
11920 return buf + (2 + (-n) + k);
11921 }
11922
11923 if (k == 1)
11924 {
11925 // dE+123
11926 // len <= 1 + 5
11927
11928 buf += 1;
11929 }
11930 else
11931 {
11932 // d.igitsE+123
11933 // len <= max_digits10 + 1 + 5
11934
11935 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
11936 buf[1] = '.';
11937 buf += 1 + k;
11938 }
11939
11940 *buf++ = 'e';
11941 return append_exponent(buf, n - 1);
11942 }
11943
11944 } // namespace dtoa_impl
11945
11956 template <typename FloatType>
11957 char* to_chars(char* first, const char* last, FloatType value)
11958 {
11959 static_cast<void>(last); // maybe unused - fix warning
11960 assert(std::isfinite(value));
11961
11962 // Use signbit(value) instead of (value < 0) since signbit works for -0.
11963 if (std::signbit(value))
11964 {
11965 value = -value;
11966 *first++ = '-';
11967 }
11968
11969 if (value == 0) // +-0
11970 {
11971 *first++ = '0';
11972 // Make it look like a floating-point number (#362, #378)
11973 *first++ = '.';
11974 *first++ = '0';
11975 return first;
11976 }
11977
11978 assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
11979
11980 // Compute v = buffer * 10^decimal_exponent.
11981 // The decimal digits are stored in the buffer, which needs to be interpreted
11982 // as an unsigned decimal integer.
11983 // len is the length of the buffer, i.e. the number of decimal digits.
11984 int len = 0;
11985 int decimal_exponent = 0;
11986 dtoa_impl::grisu2(first, len, decimal_exponent, value);
11987
11988 assert(len <= std::numeric_limits<FloatType>::max_digits10);
11989
11990 // Format the buffer like printf("%.*g", prec, value)
11991 constexpr int kMinExp = -4;
11992 // Use digits10 here to increase compatibility with version 2.
11993 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
11994
11995 assert(last - first >= kMaxExp + 2);
11996 assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
11997 assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
11998
11999 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
12000 }
12001
12002 } // namespace detail
12003} // namespace nlohmann
12004
12005// #include <nlohmann/detail/exceptions.hpp>
12006
12007// #include <nlohmann/detail/macro_scope.hpp>
12008
12009// #include <nlohmann/detail/meta/cpp_future.hpp>
12010
12011// #include <nlohmann/detail/output/binary_writer.hpp>
12012
12013// #include <nlohmann/detail/output/output_adapters.hpp>
12014
12015// #include <nlohmann/detail/value_t.hpp>
12016
12017
12018namespace nlohmann
12019{
12020 namespace detail
12021 {
12023// serialization //
12025
12028 {
12029 strict,
12030 replace,
12031 ignore
12032 };
12033
12034 template<typename BasicJsonType>
12036 {
12037 using string_t = typename BasicJsonType::string_t;
12038 using number_float_t = typename BasicJsonType::number_float_t;
12039 using number_integer_t = typename BasicJsonType::number_integer_t;
12040 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12041 static constexpr std::uint8_t UTF8_ACCEPT = 0;
12042 static constexpr std::uint8_t UTF8_REJECT = 1;
12043
12044 public:
12052 : o(std::move(s))
12053 , loc(std::localeconv())
12054 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
12055 , decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
12056 , indent_char(ichar)
12058 , error_handler(error_handler_)
12059 {}
12060
12061 // delete because of pointer members
12062 serializer(const serializer&) = delete;
12066 ~serializer() = default;
12067
12085 void dump(const BasicJsonType& val, const bool pretty_print,
12086 const bool ensure_ascii,
12087 const unsigned int indent_step,
12088 const unsigned int current_indent = 0)
12089 {
12090 switch (val.m_type)
12091 {
12092 case value_t::object:
12093 {
12094 if (val.m_value.object->empty())
12095 {
12096 o->write_characters("{}", 2);
12097 return;
12098 }
12099
12100 if (pretty_print)
12101 {
12102 o->write_characters("{\n", 2);
12103
12104 // variable to hold indentation for recursive calls
12105 const auto new_indent = current_indent + indent_step;
12106 if (JSON_UNLIKELY(indent_string.size() < new_indent))
12107 {
12108 indent_string.resize(indent_string.size() * 2, ' ');
12109 }
12110
12111 // first n-1 elements
12112 auto i = val.m_value.object->cbegin();
12113 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
12114 {
12115 o->write_characters(indent_string.c_str(), new_indent);
12116 o->write_character('\"');
12117 dump_escaped(i->first, ensure_ascii);
12118 o->write_characters("\": ", 3);
12119 dump(i->second, true, ensure_ascii, indent_step, new_indent);
12120 o->write_characters(",\n", 2);
12121 }
12122
12123 // last element
12124 assert(i != val.m_value.object->cend());
12125 assert(std::next(i) == val.m_value.object->cend());
12126 o->write_characters(indent_string.c_str(), new_indent);
12127 o->write_character('\"');
12128 dump_escaped(i->first, ensure_ascii);
12129 o->write_characters("\": ", 3);
12130 dump(i->second, true, ensure_ascii, indent_step, new_indent);
12131
12132 o->write_character('\n');
12133 o->write_characters(indent_string.c_str(), current_indent);
12134 o->write_character('}');
12135 }
12136 else
12137 {
12138 o->write_character('{');
12139
12140 // first n-1 elements
12141 auto i = val.m_value.object->cbegin();
12142 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
12143 {
12144 o->write_character('\"');
12145 dump_escaped(i->first, ensure_ascii);
12146 o->write_characters("\":", 2);
12147 dump(i->second, false, ensure_ascii, indent_step, current_indent);
12148 o->write_character(',');
12149 }
12150
12151 // last element
12152 assert(i != val.m_value.object->cend());
12153 assert(std::next(i) == val.m_value.object->cend());
12154 o->write_character('\"');
12155 dump_escaped(i->first, ensure_ascii);
12156 o->write_characters("\":", 2);
12157 dump(i->second, false, ensure_ascii, indent_step, current_indent);
12158
12159 o->write_character('}');
12160 }
12161
12162 return;
12163 }
12164
12165 case value_t::array:
12166 {
12167 if (val.m_value.array->empty())
12168 {
12169 o->write_characters("[]", 2);
12170 return;
12171 }
12172
12173 if (pretty_print)
12174 {
12175 o->write_characters("[\n", 2);
12176
12177 // variable to hold indentation for recursive calls
12178 const auto new_indent = current_indent + indent_step;
12179 if (JSON_UNLIKELY(indent_string.size() < new_indent))
12180 {
12181 indent_string.resize(indent_string.size() * 2, ' ');
12182 }
12183
12184 // first n-1 elements
12185 for (auto i = val.m_value.array->cbegin();
12186 i != val.m_value.array->cend() - 1; ++i)
12187 {
12188 o->write_characters(indent_string.c_str(), new_indent);
12189 dump(*i, true, ensure_ascii, indent_step, new_indent);
12190 o->write_characters(",\n", 2);
12191 }
12192
12193 // last element
12194 assert(not val.m_value.array->empty());
12195 o->write_characters(indent_string.c_str(), new_indent);
12196 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
12197
12198 o->write_character('\n');
12199 o->write_characters(indent_string.c_str(), current_indent);
12200 o->write_character(']');
12201 }
12202 else
12203 {
12204 o->write_character('[');
12205
12206 // first n-1 elements
12207 for (auto i = val.m_value.array->cbegin();
12208 i != val.m_value.array->cend() - 1; ++i)
12209 {
12210 dump(*i, false, ensure_ascii, indent_step, current_indent);
12211 o->write_character(',');
12212 }
12213
12214 // last element
12215 assert(not val.m_value.array->empty());
12216 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
12217
12218 o->write_character(']');
12219 }
12220
12221 return;
12222 }
12223
12224 case value_t::string:
12225 {
12226 o->write_character('\"');
12227 dump_escaped(*val.m_value.string, ensure_ascii);
12228 o->write_character('\"');
12229 return;
12230 }
12231
12232 case value_t::boolean:
12233 {
12234 if (val.m_value.boolean)
12235 {
12236 o->write_characters("true", 4);
12237 }
12238 else
12239 {
12240 o->write_characters("false", 5);
12241 }
12242 return;
12243 }
12244
12246 {
12247 dump_integer(val.m_value.number_integer);
12248 return;
12249 }
12250
12252 {
12253 dump_integer(val.m_value.number_unsigned);
12254 return;
12255 }
12256
12258 {
12259 dump_float(val.m_value.number_float);
12260 return;
12261 }
12262
12263 case value_t::discarded:
12264 {
12265 o->write_characters("<discarded>", 11);
12266 return;
12267 }
12268
12269 case value_t::null:
12270 {
12271 o->write_characters("null", 4);
12272 return;
12273 }
12274
12275 default: // LCOV_EXCL_LINE
12276 assert(false); // LCOV_EXCL_LINE
12277 }
12278 }
12279
12280 private:
12295 void dump_escaped(const string_t& s, const bool ensure_ascii)
12296 {
12297 std::uint32_t codepoint;
12298 std::uint8_t state = UTF8_ACCEPT;
12299 std::size_t bytes = 0; // number of bytes written to string_buffer
12300
12301 // number of bytes written at the point of the last valid byte
12302 std::size_t bytes_after_last_accept = 0;
12303 std::size_t undumped_chars = 0;
12304
12305 for (std::size_t i = 0; i < s.size(); ++i)
12306 {
12307 const auto byte = static_cast<uint8_t>(s[i]);
12308
12309 switch (decode(state, codepoint, byte))
12310 {
12311 case UTF8_ACCEPT: // decode found a new code point
12312 {
12313 switch (codepoint)
12314 {
12315 case 0x08: // backspace
12316 {
12317 string_buffer[bytes++] = '\\';
12318 string_buffer[bytes++] = 'b';
12319 break;
12320 }
12321
12322 case 0x09: // horizontal tab
12323 {
12324 string_buffer[bytes++] = '\\';
12325 string_buffer[bytes++] = 't';
12326 break;
12327 }
12328
12329 case 0x0A: // newline
12330 {
12331 string_buffer[bytes++] = '\\';
12332 string_buffer[bytes++] = 'n';
12333 break;
12334 }
12335
12336 case 0x0C: // formfeed
12337 {
12338 string_buffer[bytes++] = '\\';
12339 string_buffer[bytes++] = 'f';
12340 break;
12341 }
12342
12343 case 0x0D: // carriage return
12344 {
12345 string_buffer[bytes++] = '\\';
12346 string_buffer[bytes++] = 'r';
12347 break;
12348 }
12349
12350 case 0x22: // quotation mark
12351 {
12352 string_buffer[bytes++] = '\\';
12353 string_buffer[bytes++] = '\"';
12354 break;
12355 }
12356
12357 case 0x5C: // reverse solidus
12358 {
12359 string_buffer[bytes++] = '\\';
12360 string_buffer[bytes++] = '\\';
12361 break;
12362 }
12363
12364 default:
12365 {
12366 // escape control characters (0x00..0x1F) or, if
12367 // ensure_ascii parameter is used, non-ASCII characters
12368 if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
12369 {
12370 if (codepoint <= 0xFFFF)
12371 {
12372 (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
12373 static_cast<std::uint16_t>(codepoint));
12374 bytes += 6;
12375 }
12376 else
12377 {
12378 (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
12379 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
12380 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
12381 bytes += 12;
12382 }
12383 }
12384 else
12385 {
12386 // copy byte to buffer (all previous bytes
12387 // been copied have in default case above)
12388 string_buffer[bytes++] = s[i];
12389 }
12390 break;
12391 }
12392 }
12393
12394 // write buffer and reset index; there must be 13 bytes
12395 // left, as this is the maximal number of bytes to be
12396 // written ("\uxxxx\uxxxx\0") for one code point
12397 if (string_buffer.size() - bytes < 13)
12398 {
12399 o->write_characters(string_buffer.data(), bytes);
12400 bytes = 0;
12401 }
12402
12403 // remember the byte position of this accept
12404 bytes_after_last_accept = bytes;
12405 undumped_chars = 0;
12406 break;
12407 }
12408
12409 case UTF8_REJECT: // decode found invalid UTF-8 byte
12410 {
12411 switch (error_handler)
12412 {
12414 {
12415 std::string sn(3, '\0');
12416 (std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
12417 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
12418 }
12419
12422 {
12423 // in case we saw this character the first time, we
12424 // would like to read it again, because the byte
12425 // may be OK for itself, but just not OK for the
12426 // previous sequence
12427 if (undumped_chars > 0)
12428 {
12429 --i;
12430 }
12431
12432 // reset length buffer to the last accepted index;
12433 // thus removing/ignoring the invalid characters
12434 bytes = bytes_after_last_accept;
12435
12437 {
12438 // add a replacement character
12439 if (ensure_ascii)
12440 {
12441 string_buffer[bytes++] = '\\';
12442 string_buffer[bytes++] = 'u';
12443 string_buffer[bytes++] = 'f';
12444 string_buffer[bytes++] = 'f';
12445 string_buffer[bytes++] = 'f';
12446 string_buffer[bytes++] = 'd';
12447 }
12448 else
12449 {
12453 }
12454
12455 // write buffer and reset index; there must be 13 bytes
12456 // left, as this is the maximal number of bytes to be
12457 // written ("\uxxxx\uxxxx\0") for one code point
12458 if (string_buffer.size() - bytes < 13)
12459 {
12460 o->write_characters(string_buffer.data(), bytes);
12461 bytes = 0;
12462 }
12463
12464 bytes_after_last_accept = bytes;
12465 }
12466
12467 undumped_chars = 0;
12468
12469 // continue processing the string
12470 state = UTF8_ACCEPT;
12471 break;
12472 }
12473
12474 default: // LCOV_EXCL_LINE
12475 assert(false); // LCOV_EXCL_LINE
12476 }
12477 break;
12478 }
12479
12480 default: // decode found yet incomplete multi-byte code point
12481 {
12482 if (not ensure_ascii)
12483 {
12484 // code point will not be escaped - copy byte to buffer
12485 string_buffer[bytes++] = s[i];
12486 }
12487 ++undumped_chars;
12488 break;
12489 }
12490 }
12491 }
12492
12493 // we finished processing the string
12494 if (JSON_LIKELY(state == UTF8_ACCEPT))
12495 {
12496 // write buffer
12497 if (bytes > 0)
12498 {
12499 o->write_characters(string_buffer.data(), bytes);
12500 }
12501 }
12502 else
12503 {
12504 // we finish reading, but do not accept: string was incomplete
12505 switch (error_handler)
12506 {
12508 {
12509 std::string sn(3, '\0');
12510 (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
12511 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
12512 }
12513
12515 {
12516 // write all accepted bytes
12517 o->write_characters(string_buffer.data(), bytes_after_last_accept);
12518 break;
12519 }
12520
12522 {
12523 // write all accepted bytes
12524 o->write_characters(string_buffer.data(), bytes_after_last_accept);
12525 // add a replacement character
12526 if (ensure_ascii)
12527 {
12528 o->write_characters("\\ufffd", 6);
12529 }
12530 else
12531 {
12532 o->write_characters("\xEF\xBF\xBD", 3);
12533 }
12534 break;
12535 }
12536
12537 default: // LCOV_EXCL_LINE
12538 assert(false); // LCOV_EXCL_LINE
12539 }
12540 }
12541 }
12542
12551 inline unsigned int count_digits(number_unsigned_t x) noexcept
12552 {
12553 unsigned int n_digits = 1;
12554 for (;;)
12555 {
12556 if (x < 10)
12557 {
12558 return n_digits;
12559 }
12560 if (x < 100)
12561 {
12562 return n_digits + 1;
12563 }
12564 if (x < 1000)
12565 {
12566 return n_digits + 2;
12567 }
12568 if (x < 10000)
12569 {
12570 return n_digits + 3;
12571 }
12572 x = x / 10000u;
12573 n_digits += 4;
12574 }
12575 }
12576
12586 template<typename NumberType, detail::enable_if_t<
12587 std::is_same<NumberType, number_unsigned_t>::value or
12588 std::is_same<NumberType, number_integer_t>::value,
12589 int> = 0>
12590 void dump_integer(NumberType x)
12591 {
12592 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
12593 {
12594 {
12595 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
12596 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
12597 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
12598 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
12599 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
12600 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
12601 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
12602 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
12603 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
12604 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
12605 }
12606 };
12607
12608 // special case for "0"
12609 if (x == 0)
12610 {
12611 o->write_character('0');
12612 return;
12613 }
12614
12615 // use a pointer to fill the buffer
12616 auto buffer_ptr = number_buffer.begin();
12617
12618 const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
12619 number_unsigned_t abs_value;
12620
12621 unsigned int n_chars;
12622
12623 if (is_negative)
12624 {
12625 *buffer_ptr = '-';
12626 abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
12627
12628 // account one more byte for the minus sign
12629 n_chars = 1 + count_digits(abs_value);
12630 }
12631 else
12632 {
12633 abs_value = static_cast<number_unsigned_t>(x);
12634 n_chars = count_digits(abs_value);
12635 }
12636
12637 // spare 1 byte for '\0'
12638 assert(n_chars < number_buffer.size() - 1);
12639
12640 // jump to the end to generate the string from backward
12641 // so we later avoid reversing the result
12642 buffer_ptr += n_chars;
12643
12644 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
12645 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
12646 while (abs_value >= 100)
12647 {
12648 const auto digits_index = static_cast<unsigned>((abs_value % 100));
12649 abs_value /= 100;
12650 *(--buffer_ptr) = digits_to_99[digits_index][1];
12651 *(--buffer_ptr) = digits_to_99[digits_index][0];
12652 }
12653
12654 if (abs_value >= 10)
12655 {
12656 const auto digits_index = static_cast<unsigned>(abs_value);
12657 *(--buffer_ptr) = digits_to_99[digits_index][1];
12658 *(--buffer_ptr) = digits_to_99[digits_index][0];
12659 }
12660 else
12661 {
12662 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
12663 }
12664
12665 o->write_characters(number_buffer.data(), n_chars);
12666 }
12667
12677 {
12678 // NaN / inf
12679 if (not std::isfinite(x))
12680 {
12681 o->write_characters("null", 4);
12682 return;
12683 }
12684
12685 // If number_float_t is an IEEE-754 single or double precision number,
12686 // use the Grisu2 algorithm to produce short numbers which are
12687 // guaranteed to round-trip, using strtof and strtod, resp.
12688 //
12689 // NB: The test below works if <long double> == <double>.
12690 static constexpr bool is_ieee_single_or_double
12691 = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
12692 (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
12693
12694 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
12695 }
12696
12697 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
12698 {
12699 char* begin = number_buffer.data();
12700 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
12701
12702 o->write_characters(begin, static_cast<size_t>(end - begin));
12703 }
12704
12705 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
12706 {
12707 // get number of digits for a float -> text -> float round-trip
12708 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
12709
12710 // the actual conversion
12711 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
12712
12713 // negative value indicates an error
12714 assert(len > 0);
12715 // check if buffer was large enough
12716 assert(static_cast<std::size_t>(len) < number_buffer.size());
12717
12718 // erase thousands separator
12719 if (thousands_sep != '\0')
12720 {
12721 const auto end = std::remove(number_buffer.begin(),
12722 number_buffer.begin() + len, thousands_sep);
12723 std::fill(end, number_buffer.end(), '\0');
12724 assert((end - number_buffer.begin()) <= len);
12725 len = (end - number_buffer.begin());
12726 }
12727
12728 // convert decimal point to '.'
12729 if (decimal_point != '\0' and decimal_point != '.')
12730 {
12731 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
12732 if (dec_pos != number_buffer.end())
12733 {
12734 *dec_pos = '.';
12735 }
12736 }
12737
12738 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
12739
12740 // determine if need to append ".0"
12741 const bool value_is_int_like =
12742 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
12743 [](char c)
12744 {
12745 return c == '.' or c == 'e';
12746 });
12747
12748 if (value_is_int_like)
12749 {
12750 o->write_characters(".0", 2);
12751 }
12752 }
12753
12775 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
12776 {
12777 static const std::array<std::uint8_t, 400> utf8d =
12778 {
12779 {
12780 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
12781 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
12782 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
12783 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
12784 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
12785 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
12786 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
12787 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
12788 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
12789 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
12790 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
12791 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
12792 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
12793 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
12794 }
12795 };
12796
12797 const std::uint8_t type = utf8d[byte];
12798
12799 codep = (state != UTF8_ACCEPT)
12800 ? (byte & 0x3fu) | (codep << 6u)
12801 : (0xFFu >> type) & (byte);
12802
12803 state = utf8d[256u + state * 16u + type];
12804 return state;
12805 }
12806
12807 private:
12810
12812 std::array<char, 64> number_buffer{{}};
12813
12815 const std::lconv* loc = nullptr;
12817 const char thousands_sep = '\0';
12819 const char decimal_point = '\0';
12820
12822 std::array<char, 512> string_buffer{{}};
12823
12825 const char indent_char;
12828
12831 };
12832 } // namespace detail
12833} // namespace nlohmann
12834
12835// #include <nlohmann/detail/value_t.hpp>
12836
12837// #include <nlohmann/json_fwd.hpp>
12838
12839
12845namespace nlohmann
12846{
12847
12931 {
12932 private:
12933 template<detail::value_t> friend struct detail::external_constructor;
12934 friend ::nlohmann::json_pointer<basic_json>;
12935 friend ::nlohmann::detail::parser<basic_json>;
12936 friend ::nlohmann::detail::serializer<basic_json>;
12937 template<typename BasicJsonType>
12938 friend class ::nlohmann::detail::iter_impl;
12939 template<typename BasicJsonType, typename CharType>
12940 friend class ::nlohmann::detail::binary_writer;
12941 template<typename BasicJsonType, typename SAX>
12942 friend class ::nlohmann::detail::binary_reader;
12943 template<typename BasicJsonType>
12944 friend class ::nlohmann::detail::json_sax_dom_parser;
12945 template<typename BasicJsonType>
12946 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
12947
12950
12951 // convenience aliases for types residing in namespace detail;
12954
12956 template<typename BasicJsonType>
12958 template<typename BasicJsonType>
12960 template<typename Iterator>
12963
12964 template<typename CharType>
12966
12969
12971
12972 public:
12976 template<typename T, typename SFINAE>
12977 using json_serializer = JSONSerializer<T, SFINAE>;
12981 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
12982
12986
12988 // exceptions //
12990
12994
13007
13009
13010
13012 // container types //
13014
13019
13022
13027
13029 using difference_type = std::ptrdiff_t;
13031 using size_type = std::size_t;
13032
13034 using allocator_type = AllocatorType<basic_json>;
13035
13037 using pointer = typename std::allocator_traits<allocator_type>::pointer;
13039 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
13040
13049
13051
13052
13057 {
13058 return allocator_type();
13059 }
13060
13089 {
13090 basic_json result;
13091
13092 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
13093 result["name"] = "JSON for Modern C++";
13094 result["url"] = "https://github.com/nlohmann/json";
13095 result["version"]["string"] =
13096 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
13097 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
13098 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
13099 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
13100 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
13101 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
13102
13103#ifdef _WIN32
13104 result["platform"] = "win32";
13105#elif defined __linux__
13106 result["platform"] = "linux";
13107#elif defined __APPLE__
13108 result["platform"] = "apple";
13109#elif defined __unix__
13110 result["platform"] = "unix";
13111#else
13112 result["platform"] = "unknown";
13113#endif
13114
13115#if defined(__ICC) || defined(__INTEL_COMPILER)
13116 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
13117#elif defined(__clang__)
13118 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
13119#elif defined(__GNUC__) || defined(__GNUG__)
13120 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
13121#elif defined(__HP_cc) || defined(__HP_aCC)
13122 result["compiler"] = "hp"
13123#elif defined(__IBMCPP__)
13124 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
13125#elif defined(_MSC_VER)
13126 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
13127#elif defined(__PGI)
13128 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
13129#elif defined(__SUNPRO_CC)
13130 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
13131#else
13132 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
13133#endif
13134
13135#ifdef __cplusplus
13136 result["compiler"]["c++"] = std::to_string(__cplusplus);
13137#else
13138 result["compiler"]["c++"] = "unknown";
13139#endif
13140 return result;
13141 }
13142
13143
13145 // JSON value data types //
13147
13152
13153#if defined(JSON_HAS_CPP_14)
13154 // Use transparent comparator if possible, combined with perfect forwarding
13155 // on find() and count() calls prevents unnecessary string construction.
13156 using object_comparator_t = std::less<>;
13157#else
13158 using object_comparator_t = std::less<StringType>;
13159#endif
13160
13244 using object_t = ObjectType<StringType,
13245 basic_json,
13247 AllocatorType<std::pair<const StringType,
13248 basic_json>>>;
13249
13294 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
13295
13347 using string_t = StringType;
13348
13373 using boolean_t = BooleanType;
13374
13445 using number_integer_t = NumberIntegerType;
13446
13516 using number_unsigned_t = NumberUnsignedType;
13517
13584 using number_float_t = NumberFloatType;
13585
13587
13588 private:
13589
13591 template<typename T, typename... Args>
13592 static T* create(Args&& ... args)
13593 {
13594 AllocatorType<T> alloc;
13595 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
13596
13597 auto deleter = [&](T * object)
13598 {
13599 AllocatorTraits::deallocate(alloc, object, 1);
13600 };
13601 std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
13602 AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
13603 assert(object != nullptr);
13604 return object.release();
13605 }
13606
13608 // JSON value storage //
13610
13636 {
13651
13653 json_value() = default;
13655 json_value(boolean_t v) noexcept : boolean(v) {}
13664 {
13665 switch (t)
13666 {
13667 case value_t::object:
13668 {
13669 object = create<object_t>();
13670 break;
13671 }
13672
13673 case value_t::array:
13674 {
13675 array = create<array_t>();
13676 break;
13677 }
13678
13679 case value_t::string:
13680 {
13681 string = create<string_t>("");
13682 break;
13683 }
13684
13685 case value_t::boolean:
13686 {
13687 boolean = boolean_t(false);
13688 break;
13689 }
13690
13692 {
13694 break;
13695 }
13696
13698 {
13700 break;
13701 }
13702
13704 {
13706 break;
13707 }
13708
13709 case value_t::null:
13710 {
13711 object = nullptr; // silence warning, see #821
13712 break;
13713 }
13714
13715 default:
13716 {
13717 object = nullptr; // silence warning, see #821
13718 if (JSON_UNLIKELY(t == value_t::null))
13719 {
13720 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.6.1")); // LCOV_EXCL_LINE
13721 }
13722 break;
13723 }
13724 }
13725 }
13726
13729 {
13730 string = create<string_t>(value);
13731 }
13732
13735 {
13736 string = create<string_t>(std::move(value));
13737 }
13738
13741 {
13742 object = create<object_t>(value);
13743 }
13744
13747 {
13748 object = create<object_t>(std::move(value));
13749 }
13750
13753 {
13754 array = create<array_t>(value);
13755 }
13756
13759 {
13760 array = create<array_t>(std::move(value));
13761 }
13762
13763 void destroy(value_t t) noexcept
13764 {
13765 switch (t)
13766 {
13767 case value_t::object:
13768 {
13769 AllocatorType<object_t> alloc;
13770 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
13771 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
13772 break;
13773 }
13774
13775 case value_t::array:
13776 {
13777 AllocatorType<array_t> alloc;
13778 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
13779 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
13780 break;
13781 }
13782
13783 case value_t::string:
13784 {
13785 AllocatorType<string_t> alloc;
13786 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
13787 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
13788 break;
13789 }
13790
13791 default:
13792 {
13793 break;
13794 }
13795 }
13796 }
13797 };
13798
13808 void assert_invariant() const noexcept
13809 {
13810 assert(m_type != value_t::object or m_value.object != nullptr);
13811 assert(m_type != value_t::array or m_value.array != nullptr);
13812 assert(m_type != value_t::string or m_value.string != nullptr);
13813 }
13814
13815 public:
13817 // JSON parser callback //
13819
13836
13887
13889 // constructors //
13891
13896
13927 : m_type(v), m_value(v)
13928 {
13930 }
13931
13950 basic_json(std::nullptr_t = nullptr) noexcept
13951 : basic_json(value_t::null)
13952 {
13954 }
13955
14013 template <typename CompatibleType,
14017 basic_json(CompatibleType && val) noexcept(noexcept(
14018 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
14019 std::forward<CompatibleType>(val))))
14020 {
14021 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
14023 }
14024
14051 template <typename BasicJsonType,
14053 detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
14054 basic_json(const BasicJsonType& val)
14055 {
14056 using other_boolean_t = typename BasicJsonType::boolean_t;
14057 using other_number_float_t = typename BasicJsonType::number_float_t;
14058 using other_number_integer_t = typename BasicJsonType::number_integer_t;
14059 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
14060 using other_string_t = typename BasicJsonType::string_t;
14061 using other_object_t = typename BasicJsonType::object_t;
14062 using other_array_t = typename BasicJsonType::array_t;
14063
14064 switch (val.type())
14065 {
14066 case value_t::boolean:
14067 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
14068 break;
14070 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
14071 break;
14073 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
14074 break;
14076 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
14077 break;
14078 case value_t::string:
14079 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
14080 break;
14081 case value_t::object:
14082 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
14083 break;
14084 case value_t::array:
14085 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
14086 break;
14087 case value_t::null:
14088 *this = nullptr;
14089 break;
14090 case value_t::discarded:
14092 break;
14093 default: // LCOV_EXCL_LINE
14094 assert(false); // LCOV_EXCL_LINE
14095 }
14097 }
14098
14174 bool type_deduction = true,
14175 value_t manual_type = value_t::array)
14176 {
14177 // check if each element is an array with two elements whose first
14178 // element is a string
14179 bool is_an_object = std::all_of(init.begin(), init.end(),
14180 [](const detail::json_ref<basic_json>& element_ref)
14181 {
14182 return element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string();
14183 });
14184
14185 // adjust type if type deduction is not wanted
14186 if (not type_deduction)
14187 {
14188 // if array is wanted, do not create an object though possible
14189 if (manual_type == value_t::array)
14190 {
14191 is_an_object = false;
14192 }
14193
14194 // if object is wanted but impossible, throw an exception
14195 if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
14196 {
14197 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
14198 }
14199 }
14200
14201 if (is_an_object)
14202 {
14203 // the initializer list is a list of pairs -> create object
14206
14207 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
14208 {
14209 auto element = element_ref.moved_or_copied();
14210 m_value.object->emplace(
14211 std::move(*((*element.m_value.array)[0].m_value.string)),
14212 std::move((*element.m_value.array)[1]));
14213 });
14214 }
14215 else
14216 {
14217 // the initializer list describes an array -> create array
14219 m_value.array = create<array_t>(init.begin(), init.end());
14220 }
14221
14223 }
14224
14264 {
14265 return basic_json(init, false, value_t::array);
14266 }
14267
14308 {
14309 return basic_json(init, false, value_t::object);
14310 }
14311
14335 : m_type(value_t::array)
14336 {
14337 m_value.array = create<array_t>(cnt, val);
14339 }
14340
14396 template<class InputIT, typename std::enable_if<
14397 std::is_same<InputIT, typename basic_json_t::iterator>::value or
14398 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
14399 basic_json(InputIT first, InputIT last)
14400 {
14401 assert(first.m_object != nullptr);
14402 assert(last.m_object != nullptr);
14403
14404 // make sure iterator fits the current value
14405 if (JSON_UNLIKELY(first.m_object != last.m_object))
14406 {
14407 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
14408 }
14409
14410 // copy type from first iterator
14411 m_type = first.m_object->m_type;
14412
14413 // check if iterator range is complete for primitive values
14414 switch (m_type)
14415 {
14416 case value_t::boolean:
14420 case value_t::string:
14421 {
14422 if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
14423 or not last.m_it.primitive_iterator.is_end()))
14424 {
14425 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
14426 }
14427 break;
14428 }
14429
14430 default:
14431 break;
14432 }
14433
14434 switch (m_type)
14435 {
14437 {
14438 m_value.number_integer = first.m_object->m_value.number_integer;
14439 break;
14440 }
14441
14443 {
14444 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
14445 break;
14446 }
14447
14449 {
14450 m_value.number_float = first.m_object->m_value.number_float;
14451 break;
14452 }
14453
14454 case value_t::boolean:
14455 {
14456 m_value.boolean = first.m_object->m_value.boolean;
14457 break;
14458 }
14459
14460 case value_t::string:
14461 {
14462 m_value = *first.m_object->m_value.string;
14463 break;
14464 }
14465
14466 case value_t::object:
14467 {
14468 m_value.object = create<object_t>(first.m_it.object_iterator,
14469 last.m_it.object_iterator);
14470 break;
14471 }
14472
14473 case value_t::array:
14474 {
14475 m_value.array = create<array_t>(first.m_it.array_iterator,
14476 last.m_it.array_iterator);
14477 break;
14478 }
14479
14480 default:
14481 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
14482 std::string(first.m_object->type_name())));
14483 }
14484
14486 }
14487
14488
14490 // other constructors and destructor //
14492
14495 : basic_json(ref.moved_or_copied())
14496 {}
14497
14524 : m_type(other.m_type)
14525 {
14526 // check of passed value is valid
14527 other.assert_invariant();
14528
14529 switch (m_type)
14530 {
14531 case value_t::object:
14532 {
14533 m_value = *other.m_value.object;
14534 break;
14535 }
14536
14537 case value_t::array:
14538 {
14539 m_value = *other.m_value.array;
14540 break;
14541 }
14542
14543 case value_t::string:
14544 {
14545 m_value = *other.m_value.string;
14546 break;
14547 }
14548
14549 case value_t::boolean:
14550 {
14551 m_value = other.m_value.boolean;
14552 break;
14553 }
14554
14556 {
14558 break;
14559 }
14560
14562 {
14564 break;
14565 }
14566
14568 {
14570 break;
14571 }
14572
14573 default:
14574 break;
14575 }
14576
14578 }
14579
14606 basic_json(basic_json&& other) noexcept
14607 : m_type(std::move(other.m_type)),
14608 m_value(std::move(other.m_value))
14609 {
14610 // check that passed value is valid
14611 other.assert_invariant();
14612
14613 // invalidate payload
14614 other.m_type = value_t::null;
14615 other.m_value = {};
14616
14618 }
14619
14644 std::is_nothrow_move_constructible<value_t>::value and
14645 std::is_nothrow_move_assignable<value_t>::value and
14646 std::is_nothrow_move_constructible<json_value>::value and
14647 std::is_nothrow_move_assignable<json_value>::value
14648 )
14649 {
14650 // check that passed value is valid
14651 other.assert_invariant();
14652
14653 using std::swap;
14654 swap(m_type, other.m_type);
14655 swap(m_value, other.m_value);
14656
14658 return *this;
14659 }
14660
14676 ~basic_json() noexcept
14677 {
14680 }
14681
14683
14684 public:
14686 // object inspection //
14688
14692
14734 string_t dump(const int indent = -1,
14735 const char indent_char = ' ',
14736 const bool ensure_ascii = false,
14737 const error_handler_t error_handler = error_handler_t::strict) const
14738 {
14739 string_t result;
14740 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
14741
14742 if (indent >= 0)
14743 {
14744 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
14745 }
14746 else
14747 {
14748 s.dump(*this, false, ensure_ascii, 0);
14749 }
14750
14751 return result;
14752 }
14753
14786 constexpr value_t type() const noexcept
14787 {
14788 return m_type;
14789 }
14790
14816 constexpr bool is_primitive() const noexcept
14817 {
14818 return is_null() or is_string() or is_boolean() or is_number();
14819 }
14820
14843 constexpr bool is_structured() const noexcept
14844 {
14845 return is_array() or is_object();
14846 }
14847
14865 constexpr bool is_null() const noexcept
14866 {
14867 return m_type == value_t::null;
14868 }
14869
14887 constexpr bool is_boolean() const noexcept
14888 {
14889 return m_type == value_t::boolean;
14890 }
14891
14917 constexpr bool is_number() const noexcept
14918 {
14919 return is_number_integer() or is_number_float();
14920 }
14921
14946 constexpr bool is_number_integer() const noexcept
14947 {
14949 }
14950
14974 constexpr bool is_number_unsigned() const noexcept
14975 {
14977 }
14978
15002 constexpr bool is_number_float() const noexcept
15003 {
15004 return m_type == value_t::number_float;
15005 }
15006
15024 constexpr bool is_object() const noexcept
15025 {
15026 return m_type == value_t::object;
15027 }
15028
15046 constexpr bool is_array() const noexcept
15047 {
15048 return m_type == value_t::array;
15049 }
15050
15068 constexpr bool is_string() const noexcept
15069 {
15070 return m_type == value_t::string;
15071 }
15072
15095 constexpr bool is_discarded() const noexcept
15096 {
15097 return m_type == value_t::discarded;
15098 }
15099
15121 constexpr operator value_t() const noexcept
15122 {
15123 return m_type;
15124 }
15125
15127
15128 private:
15130 // value access //
15132
15134 boolean_t get_impl(boolean_t* /*unused*/) const
15135 {
15136 if (JSON_LIKELY(is_boolean()))
15137 {
15138 return m_value.boolean;
15139 }
15140
15141 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
15142 }
15143
15145 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
15146 {
15147 return is_object() ? m_value.object : nullptr;
15148 }
15149
15151 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
15152 {
15153 return is_object() ? m_value.object : nullptr;
15154 }
15155
15157 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
15158 {
15159 return is_array() ? m_value.array : nullptr;
15160 }
15161
15163 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
15164 {
15165 return is_array() ? m_value.array : nullptr;
15166 }
15167
15169 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
15170 {
15171 return is_string() ? m_value.string : nullptr;
15172 }
15173
15175 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
15176 {
15177 return is_string() ? m_value.string : nullptr;
15178 }
15179
15181 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
15182 {
15183 return is_boolean() ? &m_value.boolean : nullptr;
15184 }
15185
15187 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
15188 {
15189 return is_boolean() ? &m_value.boolean : nullptr;
15190 }
15191
15194 {
15195 return is_number_integer() ? &m_value.number_integer : nullptr;
15196 }
15197
15199 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
15200 {
15201 return is_number_integer() ? &m_value.number_integer : nullptr;
15202 }
15203
15206 {
15207 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
15208 }
15209
15211 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
15212 {
15213 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
15214 }
15215
15218 {
15219 return is_number_float() ? &m_value.number_float : nullptr;
15220 }
15221
15223 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
15224 {
15225 return is_number_float() ? &m_value.number_float : nullptr;
15226 }
15227
15239 template<typename ReferenceType, typename ThisType>
15240 static ReferenceType get_ref_impl(ThisType& obj)
15241 {
15242 // delegate the call to get_ptr<>()
15243 auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
15244
15245 if (JSON_LIKELY(ptr != nullptr))
15246 {
15247 return *ptr;
15248 }
15249
15250 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
15251 }
15252
15253 public:
15257
15272 template<typename BasicJsonType, detail::enable_if_t<
15273 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
15274 int> = 0>
15276 {
15277 return *this;
15278 }
15279
15295 template<typename BasicJsonType, detail::enable_if_t<
15296 not std::is_same<BasicJsonType, basic_json>::value and
15298 BasicJsonType get() const
15299 {
15300 return *this;
15301 }
15302
15342 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
15343 detail::enable_if_t <
15344 not detail::is_basic_json<ValueType>::value and
15345 detail::has_from_json<basic_json_t, ValueType>::value and
15346 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
15347 int> = 0>
15348 ValueType get() const noexcept(noexcept(
15349 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
15350 {
15351 // we cannot static_assert on ValueTypeCV being non-const, because
15352 // there is support for get<const basic_json_t>(), which is why we
15353 // still need the uncvref
15354 static_assert(not std::is_reference<ValueTypeCV>::value,
15355 "get() cannot be used with reference types, you might want to use get_ref()");
15356 static_assert(std::is_default_constructible<ValueType>::value,
15357 "types must be DefaultConstructible when used with get()");
15358
15359 ValueType ret;
15361 return ret;
15362 }
15363
15395 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
15396 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
15397 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
15398 int> = 0>
15399 ValueType get() const noexcept(noexcept(
15400 JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
15401 {
15402 static_assert(not std::is_reference<ValueTypeCV>::value,
15403 "get() cannot be used with reference types, you might want to use get_ref()");
15405 }
15406
15440 template<typename ValueType,
15444 int> = 0>
15445 ValueType & get_to(ValueType& v) const noexcept(noexcept(
15446 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
15447 {
15449 return v;
15450 }
15451
15452
15479 template<typename PointerType, typename std::enable_if<
15480 std::is_pointer<PointerType>::value, int>::type = 0>
15481 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
15482 {
15483 // delegate the call to get_impl_ptr<>()
15484 return get_impl_ptr(static_cast<PointerType>(nullptr));
15485 }
15486
15491 template<typename PointerType, typename std::enable_if<
15492 std::is_pointer<PointerType>::value and
15493 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
15494 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
15495 {
15496 // delegate the call to get_impl_ptr<>() const
15497 return get_impl_ptr(static_cast<PointerType>(nullptr));
15498 }
15499
15527 template<typename PointerType, typename std::enable_if<
15528 std::is_pointer<PointerType>::value, int>::type = 0>
15529 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
15530 {
15531 // delegate the call to get_ptr
15532 return get_ptr<PointerType>();
15533 }
15534
15539 template<typename PointerType, typename std::enable_if<
15540 std::is_pointer<PointerType>::value, int>::type = 0>
15541 constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
15542 {
15543 // delegate the call to get_ptr
15544 return get_ptr<PointerType>();
15545 }
15546
15573 template<typename ReferenceType, typename std::enable_if<
15574 std::is_reference<ReferenceType>::value, int>::type = 0>
15575 ReferenceType get_ref()
15576 {
15577 // delegate call to get_ref_impl
15578 return get_ref_impl<ReferenceType>(*this);
15579 }
15580
15585 template<typename ReferenceType, typename std::enable_if<
15586 std::is_reference<ReferenceType>::value and
15587 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
15588 ReferenceType get_ref() const
15589 {
15590 // delegate call to get_ref_impl
15591 return get_ref_impl<ReferenceType>(*this);
15592 }
15593
15623 template < typename ValueType, typename std::enable_if <
15624 not std::is_pointer<ValueType>::value and
15625 not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
15626 not std::is_same<ValueType, typename string_t::value_type>::value and
15628
15629 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
15630 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
15631 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914))
15632 and not std::is_same<ValueType, typename std::string_view>::value
15633 #endif
15634 #endif
15636 , int >::type = 0 >
15637 operator ValueType() const
15638 {
15639 // delegate the call to get<>() const
15640 return get<ValueType>();
15641 }
15642
15644
15645
15647 // element access //
15649
15653
15681 {
15682 // at only works for arrays
15683 if (JSON_LIKELY(is_array()))
15684 {
15685 JSON_TRY
15686 {
15687 return m_value.array->at(idx);
15688 }
15689 JSON_CATCH (std::out_of_range&)
15690 {
15691 // create better exception explanation
15692 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15693 }
15694 }
15695 else
15696 {
15697 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15698 }
15699 }
15700
15728 {
15729 // at only works for arrays
15730 if (JSON_LIKELY(is_array()))
15731 {
15732 JSON_TRY
15733 {
15734 return m_value.array->at(idx);
15735 }
15736 JSON_CATCH (std::out_of_range&)
15737 {
15738 // create better exception explanation
15739 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15740 }
15741 }
15742 else
15743 {
15744 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15745 }
15746 }
15747
15778 reference at(const typename object_t::key_type& key)
15779 {
15780 // at only works for objects
15781 if (JSON_LIKELY(is_object()))
15782 {
15783 JSON_TRY
15784 {
15785 return m_value.object->at(key);
15786 }
15787 JSON_CATCH (std::out_of_range&)
15788 {
15789 // create better exception explanation
15790 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15791 }
15792 }
15793 else
15794 {
15795 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15796 }
15797 }
15798
15829 const_reference at(const typename object_t::key_type& key) const
15830 {
15831 // at only works for objects
15832 if (JSON_LIKELY(is_object()))
15833 {
15834 JSON_TRY
15835 {
15836 return m_value.object->at(key);
15837 }
15838 JSON_CATCH (std::out_of_range&)
15839 {
15840 // create better exception explanation
15841 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15842 }
15843 }
15844 else
15845 {
15846 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15847 }
15848 }
15849
15876 {
15877 // implicitly convert null value to an empty array
15878 if (is_null())
15879 {
15881 m_value.array = create<array_t>();
15883 }
15884
15885 // operator[] only works for arrays
15886 if (JSON_LIKELY(is_array()))
15887 {
15888 // fill up array with null values if given idx is outside range
15889 if (idx >= m_value.array->size())
15890 {
15891 m_value.array->insert(m_value.array->end(),
15892 idx - m_value.array->size() + 1,
15893 basic_json());
15894 }
15895
15896 return m_value.array->operator[](idx);
15897 }
15898
15899 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15900 }
15901
15922 {
15923 // const operator[] only works for arrays
15924 if (JSON_LIKELY(is_array()))
15925 {
15926 return m_value.array->operator[](idx);
15927 }
15928
15929 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15930 }
15931
15959 reference operator[](const typename object_t::key_type& key)
15960 {
15961 // implicitly convert null value to an empty object
15962 if (is_null())
15963 {
15965 m_value.object = create<object_t>();
15967 }
15968
15969 // operator[] only works for objects
15970 if (JSON_LIKELY(is_object()))
15971 {
15972 return m_value.object->operator[](key);
15973 }
15974
15975 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15976 }
15977
16008 const_reference operator[](const typename object_t::key_type& key) const
16009 {
16010 // const operator[] only works for objects
16011 if (JSON_LIKELY(is_object()))
16012 {
16013 assert(m_value.object->find(key) != m_value.object->end());
16014 return m_value.object->find(key)->second;
16015 }
16016
16017 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
16018 }
16019
16047 template<typename T>
16049 {
16050 // implicitly convert null to object
16051 if (is_null())
16052 {
16056 }
16057
16058 // at only works for objects
16059 if (JSON_LIKELY(is_object()))
16060 {
16061 return m_value.object->operator[](key);
16062 }
16063
16064 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
16065 }
16066
16097 template<typename T>
16099 {
16100 // at only works for objects
16101 if (JSON_LIKELY(is_object()))
16102 {
16103 assert(m_value.object->find(key) != m_value.object->end());
16104 return m_value.object->find(key)->second;
16105 }
16106
16107 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
16108 }
16109
16158 template<class ValueType, typename std::enable_if<
16159 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
16160 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
16161 {
16162 // at only works for objects
16163 if (JSON_LIKELY(is_object()))
16164 {
16165 // if key is found, return value and given default value otherwise
16166 const auto it = find(key);
16167 if (it != end())
16168 {
16169 return *it;
16170 }
16171
16172 return default_value;
16173 }
16174
16175 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
16176 }
16177
16182 string_t value(const typename object_t::key_type& key, const char* default_value) const
16183 {
16184 return value(key, string_t(default_value));
16185 }
16186
16228 template<class ValueType, typename std::enable_if<
16229 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
16230 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
16231 {
16232 // at only works for objects
16233 if (JSON_LIKELY(is_object()))
16234 {
16235 // if pointer resolves a value, return it or use default value
16236 JSON_TRY
16237 {
16238 return ptr.get_checked(this);
16239 }
16241 {
16242 return default_value;
16243 }
16244 }
16245
16246 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
16247 }
16248
16253 string_t value(const json_pointer& ptr, const char* default_value) const
16254 {
16255 return value(ptr, string_t(default_value));
16256 }
16257
16284 {
16285 return *begin();
16286 }
16287
16292 {
16293 return *cbegin();
16294 }
16295
16328 {
16329 auto tmp = end();
16330 --tmp;
16331 return *tmp;
16332 }
16333
16338 {
16339 auto tmp = cend();
16340 --tmp;
16341 return *tmp;
16342 }
16343
16390 template<class IteratorType, typename std::enable_if<
16391 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
16392 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
16393 = 0>
16394 IteratorType erase(IteratorType pos)
16395 {
16396 // make sure iterator fits the current value
16397 if (JSON_UNLIKELY(this != pos.m_object))
16398 {
16399 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16400 }
16401
16402 IteratorType result = end();
16403
16404 switch (m_type)
16405 {
16406 case value_t::boolean:
16410 case value_t::string:
16411 {
16412 if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
16413 {
16414 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
16415 }
16416
16417 if (is_string())
16418 {
16419 AllocatorType<string_t> alloc;
16420 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
16421 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
16422 m_value.string = nullptr;
16423 }
16424
16427 break;
16428 }
16429
16430 case value_t::object:
16431 {
16432 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
16433 break;
16434 }
16435
16436 case value_t::array:
16437 {
16438 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
16439 break;
16440 }
16441
16442 default:
16443 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16444 }
16445
16446 return result;
16447 }
16448
16495 template<class IteratorType, typename std::enable_if<
16496 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
16497 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
16498 = 0>
16499 IteratorType erase(IteratorType first, IteratorType last)
16500 {
16501 // make sure iterator fits the current value
16502 if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
16503 {
16504 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
16505 }
16506
16507 IteratorType result = end();
16508
16509 switch (m_type)
16510 {
16511 case value_t::boolean:
16515 case value_t::string:
16516 {
16517 if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
16518 or not last.m_it.primitive_iterator.is_end()))
16519 {
16520 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
16521 }
16522
16523 if (is_string())
16524 {
16525 AllocatorType<string_t> alloc;
16526 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
16527 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
16528 m_value.string = nullptr;
16529 }
16530
16533 break;
16534 }
16535
16536 case value_t::object:
16537 {
16538 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
16539 last.m_it.object_iterator);
16540 break;
16541 }
16542
16543 case value_t::array:
16544 {
16545 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
16546 last.m_it.array_iterator);
16547 break;
16548 }
16549
16550 default:
16551 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16552 }
16553
16554 return result;
16555 }
16556
16586 size_type erase(const typename object_t::key_type& key)
16587 {
16588 // this erase only works for objects
16589 if (JSON_LIKELY(is_object()))
16590 {
16591 return m_value.object->erase(key);
16592 }
16593
16594 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16595 }
16596
16621 void erase(const size_type idx)
16622 {
16623 // this erase only works for arrays
16624 if (JSON_LIKELY(is_array()))
16625 {
16626 if (JSON_UNLIKELY(idx >= size()))
16627 {
16628 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
16629 }
16630
16631 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
16632 }
16633 else
16634 {
16635 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16636 }
16637 }
16638
16640
16641
16643 // lookup //
16645
16648
16673 template<typename KeyT>
16674 iterator find(KeyT&& key)
16675 {
16676 auto result = end();
16677
16678 if (is_object())
16679 {
16680 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16681 }
16682
16683 return result;
16684 }
16685
16690 template<typename KeyT>
16691 const_iterator find(KeyT&& key) const
16692 {
16693 auto result = cend();
16694
16695 if (is_object())
16696 {
16697 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16698 }
16699
16700 return result;
16701 }
16702
16724 template<typename KeyT>
16725 size_type count(KeyT&& key) const
16726 {
16727 // return 0 for all nonobject types
16728 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
16729 }
16730
16755 template<typename KeyT>
16756 bool contains(KeyT&& key) const
16757 {
16758 return is_object() and m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
16759 }
16760
16762
16763
16765 // iterators //
16767
16770
16795 iterator begin() noexcept
16796 {
16797 iterator result(this);
16798 result.set_begin();
16799 return result;
16800 }
16801
16805 const_iterator begin() const noexcept
16806 {
16807 return cbegin();
16808 }
16809
16835 const_iterator cbegin() const noexcept
16836 {
16837 const_iterator result(this);
16838 result.set_begin();
16839 return result;
16840 }
16841
16866 iterator end() noexcept
16867 {
16868 iterator result(this);
16869 result.set_end();
16870 return result;
16871 }
16872
16876 const_iterator end() const noexcept
16877 {
16878 return cend();
16879 }
16880
16906 const_iterator cend() const noexcept
16907 {
16908 const_iterator result(this);
16909 result.set_end();
16910 return result;
16911 }
16912
16937 {
16938 return reverse_iterator(end());
16939 }
16940
16945 {
16946 return crbegin();
16947 }
16948
16974 {
16975 return reverse_iterator(begin());
16976 }
16977
16982 {
16983 return crend();
16984 }
16985
17011 {
17012 return const_reverse_iterator(cend());
17013 }
17014
17040 {
17042 }
17043
17044 public:
17104 {
17105 return ref.items();
17106 }
17107
17113 {
17114 return ref.items();
17115 }
17116
17181 {
17182 return iteration_proxy<iterator>(*this);
17183 }
17184
17189 {
17190 return iteration_proxy<const_iterator>(*this);
17191 }
17192
17194
17195
17197 // capacity //
17199
17202
17244 bool empty() const noexcept
17245 {
17246 switch (m_type)
17247 {
17248 case value_t::null:
17249 {
17250 // null values are empty
17251 return true;
17252 }
17253
17254 case value_t::array:
17255 {
17256 // delegate call to array_t::empty()
17257 return m_value.array->empty();
17258 }
17259
17260 case value_t::object:
17261 {
17262 // delegate call to object_t::empty()
17263 return m_value.object->empty();
17264 }
17265
17266 default:
17267 {
17268 // all other types are nonempty
17269 return false;
17270 }
17271 }
17272 }
17273
17316 size_type size() const noexcept
17317 {
17318 switch (m_type)
17319 {
17320 case value_t::null:
17321 {
17322 // null values are empty
17323 return 0;
17324 }
17325
17326 case value_t::array:
17327 {
17328 // delegate call to array_t::size()
17329 return m_value.array->size();
17330 }
17331
17332 case value_t::object:
17333 {
17334 // delegate call to object_t::size()
17335 return m_value.object->size();
17336 }
17337
17338 default:
17339 {
17340 // all other types have size 1
17341 return 1;
17342 }
17343 }
17344 }
17345
17386 size_type max_size() const noexcept
17387 {
17388 switch (m_type)
17389 {
17390 case value_t::array:
17391 {
17392 // delegate call to array_t::max_size()
17393 return m_value.array->max_size();
17394 }
17395
17396 case value_t::object:
17397 {
17398 // delegate call to object_t::max_size()
17399 return m_value.object->max_size();
17400 }
17401
17402 default:
17403 {
17404 // all other types have max_size() == size()
17405 return size();
17406 }
17407 }
17408 }
17409
17411
17412
17414 // modifiers //
17416
17419
17456 void clear() noexcept
17457 {
17458 switch (m_type)
17459 {
17461 {
17463 break;
17464 }
17465
17467 {
17469 break;
17470 }
17471
17473 {
17474 m_value.number_float = 0.0;
17475 break;
17476 }
17477
17478 case value_t::boolean:
17479 {
17480 m_value.boolean = false;
17481 break;
17482 }
17483
17484 case value_t::string:
17485 {
17486 m_value.string->clear();
17487 break;
17488 }
17489
17490 case value_t::array:
17491 {
17492 m_value.array->clear();
17493 break;
17494 }
17495
17496 case value_t::object:
17497 {
17498 m_value.object->clear();
17499 break;
17500 }
17501
17502 default:
17503 break;
17504 }
17505 }
17506
17528 {
17529 // push_back only works for null objects or arrays
17530 if (JSON_UNLIKELY(not(is_null() or is_array())))
17531 {
17532 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17533 }
17534
17535 // transform null object into an array
17536 if (is_null())
17537 {
17541 }
17542
17543 // add element to array (move semantics)
17544 m_value.array->push_back(std::move(val));
17545 // invalidate object: mark it null so we do not call the destructor
17546 // cppcheck-suppress accessMoved
17547 val.m_type = value_t::null;
17548 }
17549
17555 {
17556 push_back(std::move(val));
17557 return *this;
17558 }
17559
17564 void push_back(const basic_json& val)
17565 {
17566 // push_back only works for null objects or arrays
17567 if (JSON_UNLIKELY(not(is_null() or is_array())))
17568 {
17569 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17570 }
17571
17572 // transform null object into an array
17573 if (is_null())
17574 {
17578 }
17579
17580 // add element to array
17581 m_value.array->push_back(val);
17582 }
17583
17589 {
17590 push_back(val);
17591 return *this;
17592 }
17593
17614 void push_back(const typename object_t::value_type& val)
17615 {
17616 // push_back only works for null objects or objects
17617 if (JSON_UNLIKELY(not(is_null() or is_object())))
17618 {
17619 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17620 }
17621
17622 // transform null object into an object
17623 if (is_null())
17624 {
17628 }
17629
17630 // add element to array
17631 m_value.object->insert(val);
17632 }
17633
17638 reference operator+=(const typename object_t::value_type& val)
17639 {
17640 push_back(val);
17641 return *this;
17642 }
17643
17670 {
17671 if (is_object() and init.size() == 2 and (*init.begin())->is_string())
17672 {
17673 basic_json&& key = init.begin()->moved_or_copied();
17674 push_back(typename object_t::value_type(
17675 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
17676 }
17677 else
17678 {
17679 push_back(basic_json(init));
17680 }
17681 }
17682
17688 {
17689 push_back(init);
17690 return *this;
17691 }
17692
17714 template<class... Args>
17715 void emplace_back(Args&& ... args)
17716 {
17717 // emplace_back only works for null objects or arrays
17718 if (JSON_UNLIKELY(not(is_null() or is_array())))
17719 {
17720 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
17721 }
17722
17723 // transform null object into an array
17724 if (is_null())
17725 {
17729 }
17730
17731 // add element to array (perfect forwarding)
17732 m_value.array->emplace_back(std::forward<Args>(args)...);
17733 }
17734
17762 template<class... Args>
17763 std::pair<iterator, bool> emplace(Args&& ... args)
17764 {
17765 // emplace only works for null objects or arrays
17766 if (JSON_UNLIKELY(not(is_null() or is_object())))
17767 {
17768 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
17769 }
17770
17771 // transform null object into an object
17772 if (is_null())
17773 {
17777 }
17778
17779 // add element to array (perfect forwarding)
17780 auto res = m_value.object->emplace(std::forward<Args>(args)...);
17781 // create result iterator and set iterator to the result of emplace
17782 auto it = begin();
17783 it.m_it.object_iterator = res.first;
17784
17785 // return pair of iterator and boolean
17786 return {it, res.second};
17787 }
17788
17792 template<typename... Args>
17794 {
17795 iterator result(this);
17796 assert(m_value.array != nullptr);
17797
17798 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
17799 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
17800 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
17801
17802 // This could have been written as:
17803 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
17804 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
17805
17806 return result;
17807 }
17808
17832 {
17833 // insert only works for arrays
17834 if (JSON_LIKELY(is_array()))
17835 {
17836 // check if iterator pos fits to this JSON value
17837 if (JSON_UNLIKELY(pos.m_object != this))
17838 {
17839 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17840 }
17841
17842 // insert to array and return iterator
17843 return insert_iterator(pos, val);
17844 }
17845
17846 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17847 }
17848
17854 {
17855 return insert(pos, val);
17856 }
17857
17883 {
17884 // insert only works for arrays
17885 if (JSON_LIKELY(is_array()))
17886 {
17887 // check if iterator pos fits to this JSON value
17888 if (JSON_UNLIKELY(pos.m_object != this))
17889 {
17890 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17891 }
17892
17893 // insert to array and return iterator
17894 return insert_iterator(pos, cnt, val);
17895 }
17896
17897 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17898 }
17899
17931 {
17932 // insert only works for arrays
17933 if (JSON_UNLIKELY(not is_array()))
17934 {
17935 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17936 }
17937
17938 // check if iterator pos fits to this JSON value
17939 if (JSON_UNLIKELY(pos.m_object != this))
17940 {
17941 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17942 }
17943
17944 // check if range iterators belong to the same JSON object
17945 if (JSON_UNLIKELY(first.m_object != last.m_object))
17946 {
17947 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17948 }
17949
17950 if (JSON_UNLIKELY(first.m_object == this))
17951 {
17952 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
17953 }
17954
17955 // insert to array and return iterator
17957 }
17958
17984 {
17985 // insert only works for arrays
17986 if (JSON_UNLIKELY(not is_array()))
17987 {
17988 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17989 }
17990
17991 // check if iterator pos fits to this JSON value
17992 if (JSON_UNLIKELY(pos.m_object != this))
17993 {
17994 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17995 }
17996
17997 // insert to array and return iterator
17998 return insert_iterator(pos, ilist.begin(), ilist.end());
17999 }
18000
18025 {
18026 // insert only works for objects
18027 if (JSON_UNLIKELY(not is_object()))
18028 {
18029 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
18030 }
18031
18032 // check if range iterators belong to the same JSON object
18033 if (JSON_UNLIKELY(first.m_object != last.m_object))
18034 {
18035 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
18036 }
18037
18038 // passed iterators must belong to objects
18039 if (JSON_UNLIKELY(not first.m_object->is_object()))
18040 {
18041 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
18042 }
18043
18045 }
18046
18067 {
18068 // implicitly convert null value to an empty object
18069 if (is_null())
18070 {
18072 m_value.object = create<object_t>();
18074 }
18075
18076 if (JSON_UNLIKELY(not is_object()))
18077 {
18078 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
18079 }
18080 if (JSON_UNLIKELY(not j.is_object()))
18081 {
18082 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
18083 }
18084
18085 for (auto it = j.cbegin(); it != j.cend(); ++it)
18086 {
18087 m_value.object->operator[](it.key()) = it.value();
18088 }
18089 }
18090
18118 {
18119 // implicitly convert null value to an empty object
18120 if (is_null())
18121 {
18123 m_value.object = create<object_t>();
18125 }
18126
18127 if (JSON_UNLIKELY(not is_object()))
18128 {
18129 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
18130 }
18131
18132 // check if range iterators belong to the same JSON object
18133 if (JSON_UNLIKELY(first.m_object != last.m_object))
18134 {
18135 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
18136 }
18137
18138 // passed iterators must belong to objects
18139 if (JSON_UNLIKELY(not first.m_object->is_object()
18140 or not last.m_object->is_object()))
18141 {
18142 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
18143 }
18144
18145 for (auto it = first; it != last; ++it)
18146 {
18147 m_value.object->operator[](it.key()) = it.value();
18148 }
18149 }
18150
18168 void swap(reference other) noexcept (
18169 std::is_nothrow_move_constructible<value_t>::value and
18170 std::is_nothrow_move_assignable<value_t>::value and
18171 std::is_nothrow_move_constructible<json_value>::value and
18172 std::is_nothrow_move_assignable<json_value>::value
18173 )
18174 {
18175 std::swap(m_type, other.m_type);
18176 std::swap(m_value, other.m_value);
18178 }
18179
18200 void swap(array_t& other)
18201 {
18202 // swap only works for arrays
18203 if (JSON_LIKELY(is_array()))
18204 {
18205 std::swap(*(m_value.array), other);
18206 }
18207 else
18208 {
18209 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
18210 }
18211 }
18212
18233 void swap(object_t& other)
18234 {
18235 // swap only works for objects
18236 if (JSON_LIKELY(is_object()))
18237 {
18238 std::swap(*(m_value.object), other);
18239 }
18240 else
18241 {
18242 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
18243 }
18244 }
18245
18266 void swap(string_t& other)
18267 {
18268 // swap only works for strings
18269 if (JSON_LIKELY(is_string()))
18270 {
18271 std::swap(*(m_value.string), other);
18272 }
18273 else
18274 {
18275 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
18276 }
18277 }
18278
18280
18281 public:
18283 // lexicographical comparison operators //
18285
18288
18328 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
18329 {
18330 const auto lhs_type = lhs.type();
18331 const auto rhs_type = rhs.type();
18332
18333 if (lhs_type == rhs_type)
18334 {
18335 switch (lhs_type)
18336 {
18337 case value_t::array:
18338 return *lhs.m_value.array == *rhs.m_value.array;
18339
18340 case value_t::object:
18341 return *lhs.m_value.object == *rhs.m_value.object;
18342
18343 case value_t::null:
18344 return true;
18345
18346 case value_t::string:
18347 return *lhs.m_value.string == *rhs.m_value.string;
18348
18349 case value_t::boolean:
18350 return lhs.m_value.boolean == rhs.m_value.boolean;
18351
18353 return lhs.m_value.number_integer == rhs.m_value.number_integer;
18354
18356 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
18357
18359 return lhs.m_value.number_float == rhs.m_value.number_float;
18360
18361 default:
18362 return false;
18363 }
18364 }
18365 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
18366 {
18367 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
18368 }
18369 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
18370 {
18371 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
18372 }
18373 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
18374 {
18375 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
18376 }
18377 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
18378 {
18379 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
18380 }
18381 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
18382 {
18383 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
18384 }
18385 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
18386 {
18387 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
18388 }
18389
18390 return false;
18391 }
18392
18397 template<typename ScalarType, typename std::enable_if<
18398 std::is_scalar<ScalarType>::value, int>::type = 0>
18399 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
18400 {
18401 return lhs == basic_json(rhs);
18402 }
18403
18408 template<typename ScalarType, typename std::enable_if<
18409 std::is_scalar<ScalarType>::value, int>::type = 0>
18410 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
18411 {
18412 return basic_json(lhs) == rhs;
18413 }
18414
18433 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
18434 {
18435 return not (lhs == rhs);
18436 }
18437
18442 template<typename ScalarType, typename std::enable_if<
18443 std::is_scalar<ScalarType>::value, int>::type = 0>
18444 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
18445 {
18446 return lhs != basic_json(rhs);
18447 }
18448
18453 template<typename ScalarType, typename std::enable_if<
18454 std::is_scalar<ScalarType>::value, int>::type = 0>
18455 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
18456 {
18457 return basic_json(lhs) != rhs;
18458 }
18459
18486 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
18487 {
18488 const auto lhs_type = lhs.type();
18489 const auto rhs_type = rhs.type();
18490
18491 if (lhs_type == rhs_type)
18492 {
18493 switch (lhs_type)
18494 {
18495 case value_t::array:
18496 // note parentheses are necessary, see
18497 // https://github.com/nlohmann/json/issues/1530
18498 return (*lhs.m_value.array) < (*rhs.m_value.array);
18499
18500 case value_t::object:
18501 return *lhs.m_value.object < *rhs.m_value.object;
18502
18503 case value_t::null:
18504 return false;
18505
18506 case value_t::string:
18507 return *lhs.m_value.string < *rhs.m_value.string;
18508
18509 case value_t::boolean:
18510 return lhs.m_value.boolean < rhs.m_value.boolean;
18511
18513 return lhs.m_value.number_integer < rhs.m_value.number_integer;
18514
18516 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
18517
18519 return lhs.m_value.number_float < rhs.m_value.number_float;
18520
18521 default:
18522 return false;
18523 }
18524 }
18525 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
18526 {
18527 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
18528 }
18529 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
18530 {
18531 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
18532 }
18533 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
18534 {
18535 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
18536 }
18537 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
18538 {
18539 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
18540 }
18541 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
18542 {
18543 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
18544 }
18545 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
18546 {
18547 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
18548 }
18549
18550 // We only reach this line if we cannot compare values. In that case,
18551 // we compare types. Note we have to call the operator explicitly,
18552 // because MSVC has problems otherwise.
18553 return operator<(lhs_type, rhs_type);
18554 }
18555
18560 template<typename ScalarType, typename std::enable_if<
18561 std::is_scalar<ScalarType>::value, int>::type = 0>
18562 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
18563 {
18564 return lhs < basic_json(rhs);
18565 }
18566
18571 template<typename ScalarType, typename std::enable_if<
18572 std::is_scalar<ScalarType>::value, int>::type = 0>
18573 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
18574 {
18575 return basic_json(lhs) < rhs;
18576 }
18577
18597 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
18598 {
18599 return not (rhs < lhs);
18600 }
18601
18606 template<typename ScalarType, typename std::enable_if<
18607 std::is_scalar<ScalarType>::value, int>::type = 0>
18608 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
18609 {
18610 return lhs <= basic_json(rhs);
18611 }
18612
18617 template<typename ScalarType, typename std::enable_if<
18618 std::is_scalar<ScalarType>::value, int>::type = 0>
18619 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
18620 {
18621 return basic_json(lhs) <= rhs;
18622 }
18623
18643 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
18644 {
18645 return not (lhs <= rhs);
18646 }
18647
18652 template<typename ScalarType, typename std::enable_if<
18653 std::is_scalar<ScalarType>::value, int>::type = 0>
18654 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
18655 {
18656 return lhs > basic_json(rhs);
18657 }
18658
18663 template<typename ScalarType, typename std::enable_if<
18664 std::is_scalar<ScalarType>::value, int>::type = 0>
18665 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
18666 {
18667 return basic_json(lhs) > rhs;
18668 }
18669
18689 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
18690 {
18691 return not (lhs < rhs);
18692 }
18693
18698 template<typename ScalarType, typename std::enable_if<
18699 std::is_scalar<ScalarType>::value, int>::type = 0>
18700 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
18701 {
18702 return lhs >= basic_json(rhs);
18703 }
18704
18709 template<typename ScalarType, typename std::enable_if<
18710 std::is_scalar<ScalarType>::value, int>::type = 0>
18711 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
18712 {
18713 return basic_json(lhs) >= rhs;
18714 }
18715
18717
18719 // serialization //
18721
18724
18756 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
18757 {
18758 // read width member and use it as indentation parameter if nonzero
18759 const bool pretty_print = o.width() > 0;
18760 const auto indentation = pretty_print ? o.width() : 0;
18761
18762 // reset width to 0 for subsequent calls to this stream
18763 o.width(0);
18764
18765 // do the actual serialization
18767 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
18768 return o;
18769 }
18770
18780 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
18781 {
18782 return o << j;
18783 }
18784
18786
18787
18789 // deserialization //
18791
18794
18860 const parser_callback_t cb = nullptr,
18861 const bool allow_exceptions = true)
18862 {
18863 basic_json result;
18864 parser(i, cb, allow_exceptions).parse(true, result);
18865 return result;
18866 }
18867
18869 {
18870 return parser(i).accept(true);
18871 }
18872
18926 template <typename SAX>
18927 static bool sax_parse(detail::input_adapter&& i, SAX* sax,
18929 const bool strict = true)
18930 {
18931 assert(sax);
18932 return format == input_format_t::json
18933 ? parser(std::move(i)).sax_parse(sax, strict)
18934 : detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
18935 }
18936
18986 template<class IteratorType, typename std::enable_if<
18987 std::is_base_of<
18988 std::random_access_iterator_tag,
18989 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18990 static basic_json parse(IteratorType first, IteratorType last,
18991 const parser_callback_t cb = nullptr,
18992 const bool allow_exceptions = true)
18993 {
18994 basic_json result;
18995 parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
18996 return result;
18997 }
18998
18999 template<class IteratorType, typename std::enable_if<
19000 std::is_base_of<
19001 std::random_access_iterator_tag,
19002 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
19003 static bool accept(IteratorType first, IteratorType last)
19004 {
19005 return parser(detail::input_adapter(first, last)).accept(true);
19006 }
19007
19008 template<class IteratorType, class SAX, typename std::enable_if<
19009 std::is_base_of<
19010 std::random_access_iterator_tag,
19011 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
19012 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
19013 {
19014 return parser(detail::input_adapter(first, last)).sax_parse(sax);
19015 }
19016
19026 friend std::istream& operator<<(basic_json& j, std::istream& i)
19027 {
19028 return operator>>(i, j);
19029 }
19030
19056 friend std::istream& operator>>(std::istream& i, basic_json& j)
19057 {
19058 parser(detail::input_adapter(i)).parse(false, j);
19059 return i;
19060 }
19061
19063
19065 // convenience functions //
19067
19098 const char* type_name() const noexcept
19099 {
19100 {
19101 switch (m_type)
19102 {
19103 case value_t::null:
19104 return "null";
19105 case value_t::object:
19106 return "object";
19107 case value_t::array:
19108 return "array";
19109 case value_t::string:
19110 return "string";
19111 case value_t::boolean:
19112 return "boolean";
19113 case value_t::discarded:
19114 return "discarded";
19115 default:
19116 return "number";
19117 }
19118 }
19119 }
19120
19121
19122 private:
19124 // member variables //
19126
19129
19132
19134 // binary serialization/deserialization //
19136
19139
19140 public:
19230 {
19231 std::vector<uint8_t> result;
19232 to_cbor(j, result);
19233 return result;
19234 }
19235
19237 {
19239 }
19240
19242 {
19244 }
19245
19326 {
19327 std::vector<uint8_t> result;
19328 to_msgpack(j, result);
19329 return result;
19330 }
19331
19333 {
19335 }
19336
19338 {
19340 }
19341
19423 const bool use_size = false,
19424 const bool use_type = false)
19425 {
19426 std::vector<uint8_t> result;
19427 to_ubjson(j, result, use_size, use_type);
19428 return result;
19429 }
19430
19432 const bool use_size = false, const bool use_type = false)
19433 {
19434 binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
19435 }
19436
19438 const bool use_size = false, const bool use_type = false)
19439 {
19440 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
19441 }
19442
19443
19500 {
19501 std::vector<uint8_t> result;
19502 to_bson(j, result);
19503 return result;
19504 }
19505
19515 {
19517 }
19518
19523 {
19525 }
19526
19527
19629 const bool strict = true,
19630 const bool allow_exceptions = true)
19631 {
19632 basic_json result;
19633 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19634 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
19635 return res ? result : basic_json(value_t::discarded);
19636 }
19637
19641 template<typename A1, typename A2,
19644 static basic_json from_cbor(A1 && a1, A2 && a2,
19645 const bool strict = true,
19646 const bool allow_exceptions = true)
19647 {
19648 basic_json result;
19649 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19650 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
19651 return res ? result : basic_json(value_t::discarded);
19652 }
19653
19738 const bool strict = true,
19739 const bool allow_exceptions = true)
19740 {
19741 basic_json result;
19742 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19743 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
19744 return res ? result : basic_json(value_t::discarded);
19745 }
19746
19750 template<typename A1, typename A2,
19753 static basic_json from_msgpack(A1 && a1, A2 && a2,
19754 const bool strict = true,
19755 const bool allow_exceptions = true)
19756 {
19757 basic_json result;
19758 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19759 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
19760 return res ? result : basic_json(value_t::discarded);
19761 }
19762
19826 const bool strict = true,
19827 const bool allow_exceptions = true)
19828 {
19829 basic_json result;
19830 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19831 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
19832 return res ? result : basic_json(value_t::discarded);
19833 }
19834
19838 template<typename A1, typename A2,
19841 static basic_json from_ubjson(A1 && a1, A2 && a2,
19842 const bool strict = true,
19843 const bool allow_exceptions = true)
19844 {
19845 basic_json result;
19846 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19847 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
19848 return res ? result : basic_json(value_t::discarded);
19849 }
19850
19913 const bool strict = true,
19914 const bool allow_exceptions = true)
19915 {
19916 basic_json result;
19917 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19918 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);
19919 return res ? result : basic_json(value_t::discarded);
19920 }
19921
19925 template<typename A1, typename A2,
19928 static basic_json from_bson(A1 && a1, A2 && a2,
19929 const bool strict = true,
19930 const bool allow_exceptions = true)
19931 {
19932 basic_json result;
19933 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19934 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);
19935 return res ? result : basic_json(value_t::discarded);
19936 }
19937
19938
19939
19941
19943 // JSON Pointer support //
19945
19948
19983 {
19984 return ptr.get_unchecked(this);
19985 }
19986
20011 {
20012 return ptr.get_unchecked(this);
20013 }
20014
20054 {
20055 return ptr.get_checked(this);
20056 }
20057
20097 {
20098 return ptr.get_checked(this);
20099 }
20100
20124 {
20126 json_pointer::flatten("", *this, result);
20127 return result;
20128 }
20129
20161 {
20162 return json_pointer::unflatten(*this);
20163 }
20164
20166
20168 // JSON Patch functions //
20170
20173
20221 basic_json patch(const basic_json& json_patch) const
20222 {
20223 // make a working copy to apply the patch to
20224 basic_json result = *this;
20225
20226 // the valid JSON Patch operations
20227 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
20228
20229 const auto get_op = [](const std::string & op)
20230 {
20231 if (op == "add")
20232 {
20233 return patch_operations::add;
20234 }
20235 if (op == "remove")
20236 {
20237 return patch_operations::remove;
20238 }
20239 if (op == "replace")
20240 {
20241 return patch_operations::replace;
20242 }
20243 if (op == "move")
20244 {
20245 return patch_operations::move;
20246 }
20247 if (op == "copy")
20248 {
20249 return patch_operations::copy;
20250 }
20251 if (op == "test")
20252 {
20253 return patch_operations::test;
20254 }
20255
20256 return patch_operations::invalid;
20257 };
20258
20259 // wrapper for "add" operation; add value at ptr
20260 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
20261 {
20262 // adding to the root of the target document means replacing it
20263 if (ptr.empty())
20264 {
20265 result = val;
20266 return;
20267 }
20268
20269 // make sure the top element of the pointer exists
20270 json_pointer top_pointer = ptr.top();
20271 if (top_pointer != ptr)
20272 {
20273 result.at(top_pointer);
20274 }
20275
20276 // get reference to parent of JSON pointer ptr
20277 const auto last_path = ptr.back();
20278 ptr.pop_back();
20279 basic_json& parent = result[ptr];
20280
20281 switch (parent.m_type)
20282 {
20283 case value_t::null:
20284 case value_t::object:
20285 {
20286 // use operator[] to add value
20287 parent[last_path] = val;
20288 break;
20289 }
20290
20291 case value_t::array:
20292 {
20293 if (last_path == "-")
20294 {
20295 // special case: append to back
20296 parent.push_back(val);
20297 }
20298 else
20299 {
20300 const auto idx = json_pointer::array_index(last_path);
20301 if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
20302 {
20303 // avoid undefined behavior
20304 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
20305 }
20306
20307 // default case: insert add offset
20308 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
20309 }
20310 break;
20311 }
20312
20313 // if there exists a parent it cannot be primitive
20314 default: // LCOV_EXCL_LINE
20315 assert(false); // LCOV_EXCL_LINE
20316 }
20317 };
20318
20319 // wrapper for "remove" operation; remove value at ptr
20320 const auto operation_remove = [&result](json_pointer & ptr)
20321 {
20322 // get reference to parent of JSON pointer ptr
20323 const auto last_path = ptr.back();
20324 ptr.pop_back();
20325 basic_json& parent = result.at(ptr);
20326
20327 // remove child
20328 if (parent.is_object())
20329 {
20330 // perform range check
20331 auto it = parent.find(last_path);
20332 if (JSON_LIKELY(it != parent.end()))
20333 {
20334 parent.erase(it);
20335 }
20336 else
20337 {
20338 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
20339 }
20340 }
20341 else if (parent.is_array())
20342 {
20343 // note erase performs range check
20344 parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
20345 }
20346 };
20347
20348 // type check: top level value must be an array
20349 if (JSON_UNLIKELY(not json_patch.is_array()))
20350 {
20351 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
20352 }
20353
20354 // iterate and apply the operations
20355 for (const auto& val : json_patch)
20356 {
20357 // wrapper to get a value for an operation
20358 const auto get_value = [&val](const std::string & op,
20359 const std::string & member,
20360 bool string_type) -> basic_json &
20361 {
20362 // find value
20363 auto it = val.m_value.object->find(member);
20364
20365 // context-sensitive error message
20366 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
20367
20368 // check if desired value is present
20369 if (JSON_UNLIKELY(it == val.m_value.object->end()))
20370 {
20371 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
20372 }
20373
20374 // check if result is of type string
20375 if (JSON_UNLIKELY(string_type and not it->second.is_string()))
20376 {
20377 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
20378 }
20379
20380 // no error: return value
20381 return it->second;
20382 };
20383
20384 // type check: every element of the array must be an object
20385 if (JSON_UNLIKELY(not val.is_object()))
20386 {
20387 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
20388 }
20389
20390 // collect mandatory members
20391 const std::string op = get_value("op", "op", true);
20392 const std::string path = get_value(op, "path", true);
20393 json_pointer ptr(path);
20394
20395 switch (get_op(op))
20396 {
20397 case patch_operations::add:
20398 {
20399 operation_add(ptr, get_value("add", "value", false));
20400 break;
20401 }
20402
20403 case patch_operations::remove:
20404 {
20405 operation_remove(ptr);
20406 break;
20407 }
20408
20409 case patch_operations::replace:
20410 {
20411 // the "path" location must exist - use at()
20412 result.at(ptr) = get_value("replace", "value", false);
20413 break;
20414 }
20415
20416 case patch_operations::move:
20417 {
20418 const std::string from_path = get_value("move", "from", true);
20419 json_pointer from_ptr(from_path);
20420
20421 // the "from" location must exist - use at()
20422 basic_json v = result.at(from_ptr);
20423
20424 // The move operation is functionally identical to a
20425 // "remove" operation on the "from" location, followed
20426 // immediately by an "add" operation at the target
20427 // location with the value that was just removed.
20428 operation_remove(from_ptr);
20429 operation_add(ptr, v);
20430 break;
20431 }
20432
20433 case patch_operations::copy:
20434 {
20435 const std::string from_path = get_value("copy", "from", true);
20436 const json_pointer from_ptr(from_path);
20437
20438 // the "from" location must exist - use at()
20439 basic_json v = result.at(from_ptr);
20440
20441 // The copy is functionally identical to an "add"
20442 // operation at the target location using the value
20443 // specified in the "from" member.
20444 operation_add(ptr, v);
20445 break;
20446 }
20447
20448 case patch_operations::test:
20449 {
20450 bool success = false;
20451 JSON_TRY
20452 {
20453 // check if "value" matches the one at "path"
20454 // the "path" location must exist - use at()
20455 success = (result.at(ptr) == get_value("test", "value", false));
20456 }
20458 {
20459 // ignore out of range errors: success remains false
20460 }
20461
20462 // throw an exception if test fails
20463 if (JSON_UNLIKELY(not success))
20464 {
20465 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
20466 }
20467
20468 break;
20469 }
20470
20471 default:
20472 {
20473 // op must be "add", "remove", "replace", "move", "copy", or
20474 // "test"
20475 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
20476 }
20477 }
20478 }
20479
20480 return result;
20481 }
20482
20517 static basic_json diff(const basic_json& source, const basic_json& target,
20518 const std::string& path = "")
20519 {
20520 // the patch
20521 basic_json result(value_t::array);
20522
20523 // if the values are the same, return empty patch
20524 if (source == target)
20525 {
20526 return result;
20527 }
20528
20529 if (source.type() != target.type())
20530 {
20531 // different types: replace value
20532 result.push_back(
20533 {
20534 {"op", "replace"}, {"path", path}, {"value", target}
20535 });
20536 return result;
20537 }
20538
20539 switch (source.type())
20540 {
20541 case value_t::array:
20542 {
20543 // first pass: traverse common elements
20544 std::size_t i = 0;
20545 while (i < source.size() and i < target.size())
20546 {
20547 // recursive call to compare array values at index i
20548 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
20549 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20550 ++i;
20551 }
20552
20553 // i now reached the end of at least one array
20554 // in a second pass, traverse the remaining elements
20555
20556 // remove my remaining elements
20557 const auto end_index = static_cast<difference_type>(result.size());
20558 while (i < source.size())
20559 {
20560 // add operations in reverse order to avoid invalid
20561 // indices
20562 result.insert(result.begin() + end_index, object(
20563 {
20564 {"op", "remove"},
20565 {"path", path + "/" + std::to_string(i)}
20566 }));
20567 ++i;
20568 }
20569
20570 // add other remaining elements
20571 while (i < target.size())
20572 {
20573 result.push_back(
20574 {
20575 {"op", "add"},
20576 {"path", path + "/" + std::to_string(i)},
20577 {"value", target[i]}
20578 });
20579 ++i;
20580 }
20581
20582 break;
20583 }
20584
20585 case value_t::object:
20586 {
20587 // first pass: traverse this object's elements
20588 for (auto it = source.cbegin(); it != source.cend(); ++it)
20589 {
20590 // escape the key name to be used in a JSON patch
20591 const auto key = json_pointer::escape(it.key());
20592
20593 if (target.find(it.key()) != target.end())
20594 {
20595 // recursive call to compare object values at key it
20596 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
20597 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20598 }
20599 else
20600 {
20601 // found a key that is not in o -> remove it
20602 result.push_back(object(
20603 {
20604 {"op", "remove"}, {"path", path + "/" + key}
20605 }));
20606 }
20607 }
20608
20609 // second pass: traverse other object's elements
20610 for (auto it = target.cbegin(); it != target.cend(); ++it)
20611 {
20612 if (source.find(it.key()) == source.end())
20613 {
20614 // found a key that is not in this -> add it
20615 const auto key = json_pointer::escape(it.key());
20616 result.push_back(
20617 {
20618 {"op", "add"}, {"path", path + "/" + key},
20619 {"value", it.value()}
20620 });
20621 }
20622 }
20623
20624 break;
20625 }
20626
20627 default:
20628 {
20629 // both primitive type: replace value
20630 result.push_back(
20631 {
20632 {"op", "replace"}, {"path", path}, {"value", target}
20633 });
20634 break;
20635 }
20636 }
20637
20638 return result;
20639 }
20640
20642
20644 // JSON Merge Patch functions //
20646
20649
20692 void merge_patch(const basic_json& apply_patch)
20693 {
20694 if (apply_patch.is_object())
20695 {
20696 if (not is_object())
20697 {
20698 *this = object();
20699 }
20700 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
20701 {
20702 if (it.value().is_null())
20703 {
20704 erase(it.key());
20705 }
20706 else
20707 {
20708 operator[](it.key()).merge_patch(it.value());
20709 }
20710 }
20711 }
20712 else
20713 {
20714 *this = apply_patch;
20715 }
20716 }
20717
20719 };
20720} // namespace nlohmann
20721
20723// nonmember support //
20725
20726// specialization of std::swap, and std::hash
20727namespace std
20728{
20729
20731 template<>
20732 struct hash<nlohmann::json>
20733 {
20739 std::size_t operator()(const nlohmann::json& j) const
20740 {
20741 // a naive hashing via the string representation
20742 const auto& h = hash<nlohmann::json::string_t>();
20743 return h(j.dump());
20744 }
20745 };
20746
20750 template<>
20752 {
20758 nlohmann::detail::value_t rhs) const noexcept
20759 {
20760 return nlohmann::detail::operator<(lhs, rhs);
20761 }
20762 };
20763
20769 template<>
20770 inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
20771 is_nothrow_move_constructible<nlohmann::json>::value and
20772 is_nothrow_move_assignable<nlohmann::json>::value
20773 )
20774 {
20775 j1.swap(j2);
20776 }
20777
20778} // namespace std
20779
20793inline nlohmann::json operator "" _json(const char* s, std::size_t n)
20794{
20795 return nlohmann::json::parse(s, s + n);
20796}
20797
20811inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
20812{
20813 return nlohmann::json::json_pointer(std::string(s, n));
20814}
20815
20816// #include <nlohmann/detail/macro_unscope.hpp>
20817
20818
20819// restore GCC/clang diagnostic settings
20820#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
20821#pragma GCC diagnostic pop
20822#endif
20823#if defined(__clang__)
20824#pragma GCC diagnostic pop
20825#endif
20826
20827// clean up
20828#undef JSON_INTERNAL_CATCH
20829#undef JSON_CATCH
20830#undef JSON_THROW
20831#undef JSON_TRY
20832#undef JSON_LIKELY
20833#undef JSON_UNLIKELY
20834#undef JSON_DEPRECATED
20835#undef JSON_NODISCARD
20836#undef JSON_HAS_CPP_14
20837#undef JSON_HAS_CPP_17
20838#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
20839#undef NLOHMANN_BASIC_JSON_TPL
20840
20841
20842#endif // INCLUDE_NLOHMANN_JSON_HPP_
MecaCell::Vec pos
Definition: CellBody.hpp:34
a class to store JSON values
Definition: json.hpp:12931
string_t * get_impl_ptr(string_t *) noexcept
get a pointer to the value (string)
Definition: json.hpp:15169
reference back()
access the last element
Definition: json.hpp:16327
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:17831
static T * create(Args &&... args)
helper for exception-safe object creation
Definition: json.hpp:13592
static JSON_NODISCARD basic_json from_cbor(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in CBOR format
Definition: json.hpp:19628
static ReferenceType get_ref_impl(ThisType &obj)
helper function to implement get_ref()
Definition: json.hpp:15240
static JSON_DEPRECATED iteration_proxy< const_iterator > iterator_wrapper(const_reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition: json.hpp:17112
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:16394
object_t * get_impl_ptr(object_t *) noexcept
get a pointer to the value (object)
Definition: json.hpp:15145
bool contains(KeyT &&key) const
check the existence of an element in a JSON object
Definition: json.hpp:16756
size_type count(KeyT &&key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:16725
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:16795
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:18328
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:18665
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:16866
boolean_t * get_impl_ptr(boolean_t *) noexcept
get a pointer to the value (boolean)
Definition: json.hpp:15181
static JSON_DEPRECATED iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition: json.hpp:17103
bool empty() const noexcept
checks whether the container is empty.
Definition: json.hpp:17244
void insert(const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:18024
void push_back(initializer_list_t init)
add an object to an object
Definition: json.hpp:17669
number_float_t * get_impl_ptr(number_float_t *) noexcept
get a pointer to the value (floating-point number)
Definition: json.hpp:15217
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:16876
void update(const_reference j)
updates a JSON object from another object, overwriting existing keys
Definition: json.hpp:18066
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:17010
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:17853
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:16936
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:15959
static JSON_NODISCARD basic_json from_ubjson(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition: json.hpp:19841
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:17316
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:16098
void update(const_iterator first, const_iterator last)
updates a JSON object from another object, overwriting existing keys
Definition: json.hpp:18117
static JSON_NODISCARD basic_json from_msgpack(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:19737
static JSON_NODISCARD basic_json from_bson(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition: json.hpp:19928
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:14786
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:14917
basic_json(const detail::json_ref< basic_json > &ref)
Definition: json.hpp:14494
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:17386
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:16586
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:17882
BasicJsonType get() const
get special-case overload
Definition: json.hpp:15298
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition: json.hpp:17793
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:15002
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition: json.hpp:15445
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:13031
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:17188
reference front()
access the first element
Definition: json.hpp:16283
constexpr const number_float_t * get_impl_ptr(const number_float_t *) const noexcept
get a pointer to the value (floating-point number)
Definition: json.hpp:15223
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:17930
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than
Definition: json.hpp:18654
static std::vector< uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition: json.hpp:19422
static JSON_NODISCARD basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition: json.hpp:20517
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition: json.hpp:15529
static void to_ubjson(const basic_json &j, detail::output_adapter< uint8_t > o, const bool use_size=false, const bool use_type=false)
Definition: json.hpp:19431
void assert_invariant() const noexcept
checks the class invariants
Definition: json.hpp:13808
const_reference front() const
access the first element
Definition: json.hpp:16291
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:16499
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:13373
static void to_msgpack(const basic_json &j, detail::output_adapter< uint8_t > o)
Definition: json.hpp:19332
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:16805
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:16981
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition: json.hpp:14734
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:16944
static void to_bson(const basic_json &j, detail::output_adapter< uint8_t > o)
Serializes the given JSON object j to BSON and forwards the corresponding BSON-representation to the ...
Definition: json.hpp:19514
const char * type_name() const noexcept
return the type as string
Definition: json.hpp:19098
number_unsigned_t * get_impl_ptr(number_unsigned_t *) noexcept
get a pointer to the value (unsigned number)
Definition: json.hpp:15205
static JSON_NODISCARD basic_json meta()
returns version information on the library
Definition: json.hpp:13088
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:17763
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:17039
ValueType get() const noexcept(noexcept(JSONSerializer< ValueTypeCV >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition: json.hpp:15399
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:18756
JSON_DEPRECATED friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:19026
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:18597
static void to_cbor(const basic_json &j, detail::output_adapter< uint8_t > o)
Definition: json.hpp:19236
ObjectType< StringType, basic_json, object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition: json.hpp:13248
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:18711
::nlohmann::detail::output_adapter_t< CharType > output_adapter_t
Definition: json.hpp:12965
StringType string_t
a type for a string
Definition: json.hpp:13347
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:14816
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition: json.hpp:15494
void swap(array_t &other)
exchanges the values
Definition: json.hpp:18200
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:16230
::nlohmann::json_pointer< basic_json > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition: json.hpp:12975
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:18700
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:15068
number_integer_t * get_impl_ptr(number_integer_t *) noexcept
get a pointer to the value (integer number)
Definition: json.hpp:15193
basic_json get() const
get special-case overload
Definition: json.hpp:15275
constexpr const boolean_t * get_impl_ptr(const boolean_t *) const noexcept
get a pointer to the value (boolean)
Definition: json.hpp:15187
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
Definition: json.hpp:19241
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:18433
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition: json.hpp:13048
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:15680
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:20096
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:18689
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:20160
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:19325
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:14017
JSONSerializer< T, SFINAE > json_serializer
Definition: json.hpp:12977
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than
Definition: json.hpp:18562
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition: json.hpp:20692
::nlohmann::detail::binary_reader< basic_json > binary_reader
Definition: json.hpp:12967
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than or equal
Definition: json.hpp:18608
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition: json.hpp:20221
const_reference back() const
access the last element
Definition: json.hpp:16337
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition: json.hpp:19229
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:16253
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:13034
static bool accept(detail::input_adapter &&i)
Definition: json.hpp:18868
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:18643
JSON_DEPRECATED friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:18780
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:16621
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:13584
static JSON_NODISCARD basic_json from_bson(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition: json.hpp:19912
iterator find(KeyT &&key)
find an element in a JSON object
Definition: json.hpp:16674
static bool sax_parse(detail::input_adapter &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true)
generate SAX events
Definition: json.hpp:18927
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:20053
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:18168
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:16906
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:14865
value_t m_type
the type of the current element
Definition: json.hpp:19128
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:15778
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:14887
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:13445
basic_json & 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:14643
constexpr const number_unsigned_t * get_impl_ptr(const number_unsigned_t *) const noexcept
get a pointer to the value (unsigned number)
Definition: json.hpp:15211
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
Definition: json.hpp:19337
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:14606
static JSON_NODISCARD basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition: json.hpp:14263
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:15921
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:20010
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:14843
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition: json.hpp:14054
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements
Definition: json.hpp:17983
ValueType get() const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition: json.hpp:15348
static bool sax_parse(IteratorType first, IteratorType last, SAX *sax)
Definition: json.hpp:19012
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:15095
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:18486
typename parser::parse_event_t parse_event_t
parser event types
Definition: json.hpp:13835
void emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:17715
static JSON_NODISCARD basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition: json.hpp:14307
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:18455
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:15727
static JSON_NODISCARD basic_json from_msgpack(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:19753
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:16008
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:18990
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:17564
typename parser::parser_callback_t parser_callback_t
per-element parser callback type
Definition: json.hpp:13886
constexpr const array_t * get_impl_ptr(const array_t *) const noexcept
get a pointer to the value (array)
Definition: json.hpp:15163
basic_json(initializer_list_t 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:14173
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:14334
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:20123
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:13516
~basic_json() noexcept
destructor
Definition: json.hpp:14676
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition: json.hpp:18399
::nlohmann::detail::parser< basic_json > parser
Definition: json.hpp:12953
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:14946
reference operator[](T *key)
access specified object element
Definition: json.hpp:16048
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:14974
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:14399
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:18573
std::less< StringType > object_comparator_t
Definition: json.hpp:13158
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition: json.hpp:15481
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:17638
void clear() noexcept
clears the contents
Definition: json.hpp:17456
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition: json.hpp:13046
void swap(object_t &other)
exchanges the values
Definition: json.hpp:18233
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:15588
boolean_t get_impl(boolean_t *) const
get a boolean (explicit)
Definition: json.hpp:15134
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:19982
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:16973
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:15875
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:17527
array_t * get_impl_ptr(array_t *) noexcept
get a pointer to the value (array)
Definition: json.hpp:15157
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:15829
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:16182
constexpr auto get() const noexcept -> decltype(std::declval< const basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition: json.hpp:15541
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition: json.hpp:12981
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:18619
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:16835
void swap(string_t &other)
exchanges the values
Definition: json.hpp:18266
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:17588
static JSON_NODISCARD basic_json from_cbor(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in CBOR format
Definition: json.hpp:19644
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition: json.hpp:16160
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:13294
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:17614
constexpr const object_t * get_impl_ptr(const object_t *) const noexcept
get a pointer to the value (object)
Definition: json.hpp:15151
const_iterator find(KeyT &&key) const
find an element in a JSON object
Definition: json.hpp:16691
static bool accept(IteratorType first, IteratorType last)
Definition: json.hpp:19003
static JSON_NODISCARD basic_json from_ubjson(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition: json.hpp:19825
detail::value_t value_t
Definition: json.hpp:12973
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:13950
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:19056
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:17554
json_value m_value
the value of the current element
Definition: json.hpp:19131
static std::vector< uint8_t > to_bson(const basic_json &j)
Serializes the given JSON object j to BSON and returns a vector containing the corresponding BSON-rep...
Definition: json.hpp:19499
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
Serializes the given JSON object j to BSON and forwards the corresponding BSON-representation to the ...
Definition: json.hpp:19522
basic_json(const value_t v)
create an empty value with a given type
Definition: json.hpp:13926
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:18410
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:15046
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:13037
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:17180
reference operator+=(initializer_list_t init)
add an object to an object
Definition: json.hpp:17687
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:13056
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:14523
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
Definition: json.hpp:19437
constexpr const number_integer_t * get_impl_ptr(const number_integer_t *) const noexcept
get a pointer to the value (integer number)
Definition: json.hpp:15199
constexpr const string_t * get_impl_ptr(const string_t *) const noexcept
get a pointer to the value (string)
Definition: json.hpp:15175
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:15024
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:15575
static JSON_NODISCARD basic_json parse(detail::input_adapter &&i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from a compatible input
Definition: json.hpp:18859
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:13029
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition: json.hpp:18444
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:13039
NLOHMANN_BASIC_JSON_TPL basic_json_t
workaround type for MSVC
Definition: json.hpp:12949
deserialization of CBOR, MessagePack, and UBJSON values
Definition: json.hpp:3544
bool get_bson_cstr(string_t &result)
Parses a C-style string from the BSON input.
Definition: json.hpp:3674
bool get_msgpack_array(const std::size_t len)
Definition: json.hpp:4828
binary_reader & operator=(const binary_reader &)=delete
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:3546
bool get_number(const input_format_t format, NumberType &result)
Definition: json.hpp:5355
static constexpr bool little_endianess(int num=1) noexcept
determine system byte order
Definition: json.hpp:3635
bool get_string(const input_format_t format, const NumberType len, string_t &result)
create a string by reading characters from the input
Definition: json.hpp:5398
input_adapter_t ia
input adapter
Definition: json.hpp:5479
binary_reader(binary_reader &&)=default
std::size_t chars_read
the number of characters read
Definition: json.hpp:5485
bool get_ubjson_string(string_t &result, const bool get_char=true)
reads a UBJSON string
Definition: json.hpp:4906
bool parse_cbor_internal(const bool get_char=true)
Definition: json.hpp:3864
bool get_cbor_object(const std::size_t len)
Definition: json.hpp:4331
bool parse_bson_element_internal(const int element_type, const std::size_t element_type_parse_position)
Read a BSON document element of the given element_type.
Definition: json.hpp:3727
bool get_ubjson_size_value(std::size_t &result)
Definition: json.hpp:4960
bool get_bson_string(const NumberType len, string_t &result)
Parses a zero-terminated string of length len from the BSON input.
Definition: json.hpp:3706
bool get_ubjson_size_type(std::pair< std::size_t, int > &result)
determine the type and size for a container
Definition: json.hpp:5037
bool get_msgpack_string(string_t &result)
reads a MessagePack string
Definition: json.hpp:4752
binary_reader & operator=(binary_reader &&)=default
bool get_ubjson_value(const int prefix)
Definition: json.hpp:5078
bool parse_bson_array()
Reads an array from the BSON input and passes it to the SAX-parser.
Definition: json.hpp:3835
bool parse_bson_element_list(const bool is_array)
Read a BSON element list (as specified in the BSON-spec)
Definition: json.hpp:3798
std::string exception_message(const input_format_t format, const std::string &detail, const std::string &context) const
Definition: json.hpp:5446
bool unexpect_eof(const input_format_t format, const char *context) const
Definition: json.hpp:5420
bool parse_bson_internal()
Reads in a BSON-object and passes it to the SAX-parser.
Definition: json.hpp:3649
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:3545
typename BasicJsonType::string_t string_t
Definition: json.hpp:3548
const bool is_little_endian
whether we can assume little endianess
Definition: json.hpp:5488
binary_reader(const binary_reader &)=delete
int current
the current character
Definition: json.hpp:5482
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true)
Definition: json.hpp:3577
bool get_cbor_array(const std::size_t len)
Definition: json.hpp:4295
json_sax_t * sax
the SAX parser
Definition: json.hpp:5491
bool get_cbor_string(string_t &result)
reads a CBOR string
Definition: json.hpp:4206
std::string get_token_string() const
Definition: json.hpp:5433
bool get_msgpack_object(const std::size_t len)
Definition: json.hpp:4850
binary_reader(input_adapter_t adapter)
create a binary reader
Definition: json.hpp:3557
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:3547
bool parse_ubjson_internal(const bool get_char=true)
Definition: json.hpp:4887
int get()
get next character from the input
Definition: json.hpp:5321
serialization to CBOR and MessagePack values
Definition: json.hpp:9576
void write_bson_array(const string_t &name, const typename BasicJsonType::array_t &value)
Writes a BSON element with key name and array value.
Definition: json.hpp:10427
const bool is_little_endian
whether we can assume little endianess
Definition: json.hpp:10879
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
Definition: json.hpp:10597
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true)
Definition: json.hpp:10100
static constexpr CharType get_ubjson_float_prefix(double)
Definition: json.hpp:10799
void write_bson_entry_header(const string_t &name, const std::uint8_t element_type)
Writes the given element_type and name to the output adapter.
Definition: json.hpp:10279
static std::size_t calc_bson_element_size(const string_t &name, const BasicJsonType &j)
Calculates the size necessary to serialize the JSON value j with its name.
Definition: json.hpp:10447
void write_bson_double(const string_t &name, const double value)
Writes a BSON element with key name and double value value.
Definition: json.hpp:10301
void write_bson_object(const typename BasicJsonType::object_t &value)
Definition: json.hpp:10550
typename BasicJsonType::string_t string_t
Definition: json.hpp:9577
static constexpr CharType get_cbor_float_prefix(float)
Definition: json.hpp:10566
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition: json.hpp:10872
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition: json.hpp:9585
static constexpr CharType get_msgpack_float_prefix(double)
Definition: json.hpp:10585
CharType ubjson_prefix(const BasicJsonType &j) const noexcept
determine the type prefix of container values
Definition: json.hpp:10723
void write_bson_integer(const string_t &name, const std::int64_t value)
Writes a BSON element with key name and integer value.
Definition: json.hpp:10351
static std::size_t calc_bson_entry_header_size(const string_t &name)
Definition: json.hpp:10264
void write_bson_unsigned(const string_t &name, const std::uint64_t value)
Writes a BSON element with key name and unsigned value.
Definition: json.hpp:10379
static CharType to_char_type(std::uint8_t x) noexcept
Definition: json.hpp:10850
void write_bson_string(const string_t &name, const string_t &value)
Writes a BSON element with key name and string value value.
Definition: json.hpp:10319
void write_bson_object_entry(const string_t &name, const typename BasicJsonType::object_t &value)
Writes a BSON element with key name and object value.
Definition: json.hpp:10401
static constexpr CharType get_ubjson_float_prefix(float)
Definition: json.hpp:10794
void write_number(const NumberType n)
Definition: json.hpp:10820
output_adapter_t< CharType > oa
the output
Definition: json.hpp:10882
void write_bson_element(const string_t &name, const BasicJsonType &j)
Serializes the JSON value j to BSON and associates it with the key name.
Definition: json.hpp:10492
void write_bson_null(const string_t &name)
Writes a BSON element with key name and null value.
Definition: json.hpp:10333
void write_bson(const BasicJsonType &j)
Definition: json.hpp:9594
void write_cbor(const BasicJsonType &j)
Definition: json.hpp:9614
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
Definition: json.hpp:10369
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition: json.hpp:10843
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t &value)
Calculates the size of the BSON serialization of the given JSON-object j.
Definition: json.hpp:10535
static constexpr CharType get_msgpack_float_prefix(float)
Definition: json.hpp:10580
void write_bson_boolean(const string_t &name, const bool value)
Writes a BSON element with key name and boolean value value.
Definition: json.hpp:10291
void write_msgpack(const BasicJsonType &j)
Definition: json.hpp:9858
static std::size_t calc_bson_string_size(const string_t &value)
Definition: json.hpp:10311
static std::size_t calc_bson_integer_size(const std::int64_t value)
Definition: json.hpp:10341
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t &value)
Definition: json.hpp:10411
static constexpr CharType get_cbor_float_prefix(double)
Definition: json.hpp:10571
general exception of the basic_json class
Definition: json.hpp:146
const int id
the id of the exception
Definition: json.hpp:155
static std::string name(const std::string &ename, int id_)
Definition: json.hpp:160
std::runtime_error m
an exception object as storage for error messages
Definition: json.hpp:167
const char * what() const noexcept override
returns the explanatory string
Definition: json.hpp:149
exception(int id_, const char *what_arg)
Definition: json.hpp:158
file_input_adapter(file_input_adapter &&)=default
std::FILE * m_file
the file pointer to read from
Definition: json.hpp:2311
file_input_adapter(const file_input_adapter &)=delete
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition: json.hpp:2304
file_input_adapter & operator=(file_input_adapter &&)=default
file_input_adapter & operator=(const file_input_adapter &)=delete
file_input_adapter(std::FILE *f) noexcept
Definition: json.hpp:2293
~file_input_adapter() override=default
input_adapter(std::FILE *file)
Definition: json.hpp:2571
input_adapter(const std::wstring &ws)
Definition: json.hpp:2581
input_adapter(CharT b, std::size_t l)
input adapter for buffer
Definition: json.hpp:2597
input_adapter(const std::u16string &ws)
Definition: json.hpp:2584
input_adapter(CharT b)
input adapter for string literal
Definition: json.hpp:2609
input_adapter(const ContiguousContainer &c)
input adapter for contiguous container
Definition: json.hpp:2661
input_adapter(T(&array)[N])
input adapter for array
Definition: json.hpp:2653
input_adapter(const std::u32string &ws)
Definition: json.hpp:2587
input_adapter_t ia
the actual adapter
Definition: json.hpp:2671
input_adapter(IteratorType first, IteratorType last)
input adapter for iterator range with contiguous storage
Definition: json.hpp:2618
input_adapter(std::istream &i)
input adapter for input stream
Definition: json.hpp:2574
input_adapter(std::istream &&i)
input adapter for input stream
Definition: json.hpp:2578
input adapter for buffer input
Definition: json.hpp:2366
input_buffer_adapter & operator=(input_buffer_adapter &&)=delete
const char * cursor
pointer to the current character
Definition: json.hpp:2391
input_buffer_adapter & operator=(input_buffer_adapter &)=delete
input_buffer_adapter(input_buffer_adapter &&)=delete
const char *const limit
pointer past the last character
Definition: json.hpp:2393
input_buffer_adapter(const char *b, const std::size_t l) noexcept
Definition: json.hpp:2368
input_buffer_adapter(const input_buffer_adapter &)=delete
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition: json.hpp:2379
input_stream_adapter(input_stream_adapter &&)=delete
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &&)=delete
std::istream & is
the associated input stream
Definition: json.hpp:2360
input_stream_adapter(std::istream &i)
Definition: json.hpp:2334
std::char_traits< char >::int_type get_character() override
get a character [0,255] or std::char_traits<char>::eof().
Definition: json.hpp:2347
exception indicating errors with iterators
Definition: json.hpp:301
static invalid_iterator create(int id_, const std::string &what_arg)
Definition: json.hpp:303
invalid_iterator(int id_, const char *what_arg)
Definition: json.hpp:310
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition: json.hpp:7708
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.hpp:8075
iter_impl operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:8189
iter_impl()=default
default constructor
Definition: json.hpp:7710
iter_impl const operator--(int)
post-decrement (it–)
Definition: json.hpp:7996
void set_end() noexcept
set the iterator past the last value
Definition: json.hpp:7851
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.hpp:8039
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:7733
iter_impl & operator--()
pre-decrement (–it)
Definition: json.hpp:8007
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.hpp:8200
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:7742
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7882
void set_begin() noexcept
set the iterator to the first value
Definition: json.hpp:7814
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.hpp:8120
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:7737
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition: json.hpp:7802
pointer operator->() const
dereference the iterator
Definition: json.hpp:7919
iter_impl const operator++(int)
post-increment (it++)
Definition: json.hpp:7953
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition: json.hpp:7793
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7753
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition: json.hpp:8277
iter_impl operator+(difference_type i) const
add to iterator
Definition: json.hpp:8167
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition: json.hpp:8178
const object_t::key_type & key() const
return the key of an object iterator
Definition: json.hpp:8252
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.hpp:8111
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:7731
reference value() const
return the value of an iterator
Definition: json.hpp:8268
typename BasicJsonType::object_t object_t
Definition: json.hpp:7715
iter_impl & operator++()
pre-increment (++it)
Definition: json.hpp:7964
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8221
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.hpp:8102
pointer m_object
associated JSON instance
Definition: json.hpp:8275
std::bidirectional_iterator_tag iterator_category
Definition: json.hpp:7728
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8129
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.hpp:8066
typename BasicJsonType::array_t array_t
Definition: json.hpp:7716
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:8158
IteratorType anchor
the iterator
Definition: json.hpp:1684
std::input_iterator_tag iterator_category
Definition: json.hpp:1680
std::string array_index_str
a string representation of the array index
Definition: json.hpp:1690
iteration_proxy_value(IteratorType it) noexcept
Definition: json.hpp:1695
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition: json.hpp:1719
const std::string & key() const
return key of the iterator
Definition: json.hpp:1725
std::size_t array_index_last
last stringified array index
Definition: json.hpp:1688
IteratorType::reference value() const
return value of the iterator
Definition: json.hpp:1753
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition: json.hpp:1704
std::size_t array_index
an index for arrays (used to create key names)
Definition: json.hpp:1686
iteration_proxy_value & operator*()
dereference operator (needed for range-based for)
Definition: json.hpp:1698
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition: json.hpp:1713
const std::string empty_str
an empty string (to return a reference for primitive values)
Definition: json.hpp:1692
proxy class for the items() function
Definition: json.hpp:1761
iteration_proxy_value< IteratorType > begin() noexcept
return iterator begin (needed for range-based for)
Definition: json.hpp:1772
iteration_proxy_value< IteratorType > end() noexcept
return iterator end (needed for range-based for)
Definition: json.hpp:1778
IteratorType::reference container
the container to iterate
Definition: json.hpp:1764
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition: json.hpp:1768
json_ref & operator=(const json_ref &)=delete
value_type * value_ref
Definition: json.hpp:9417
json_ref(const json_ref &)=delete
json_ref(json_ref &&)=default
value_type const & operator*() const
Definition: json.hpp:9405
BasicJsonType value_type
Definition: json.hpp:9368
json_ref(Args &&... args)
Definition: json.hpp:9385
json_ref(const value_type &value)
Definition: json.hpp:9374
value_type const * operator->() const
Definition: json.hpp:9410
json_ref & operator=(json_ref &&)=delete
json_ref(std::initializer_list< json_ref > init)
Definition: json.hpp:9378
json_ref(value_type &&value)
Definition: json.hpp:9370
value_type moved_or_copied() const
Definition: json.hpp:9396
a template for a reverse iterator class
Definition: json.hpp:8319
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:8328
json_reverse_iterator const operator--(int)
post-decrement (it–)
Definition: json.hpp:8347
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:8325
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:8371
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8359
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition: json.hpp:8323
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:8332
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8383
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:8377
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:8365
json_reverse_iterator const operator++(int)
post-increment (it++)
Definition: json.hpp:8335
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition: json.hpp:8389
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:8353
reference value() const
return the value of an iterator
Definition: json.hpp:8396
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:8341
typename BasicJsonType::string_t string_t
Definition: json.hpp:3314
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:3311
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:3313
bool start_object(std::size_t=std::size_t(-1))
Definition: json.hpp:3346
bool start_array(std::size_t=std::size_t(-1))
Definition: json.hpp:3361
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition: json.hpp:3371
bool number_integer(number_integer_t)
Definition: json.hpp:3326
bool number_unsigned(number_unsigned_t)
Definition: json.hpp:3331
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:3312
bool number_float(number_float_t, const string_t &)
Definition: json.hpp:3336
typename BasicJsonType::string_t string_t
Definition: json.hpp:3010
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition: json.hpp:3302
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:3008
BasicJsonType * object_element
helper to hold the reference for the next object element
Definition: json.hpp:3296
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:3007
std::pair< bool, BasicJsonType * > handle_value(Value &&v, const bool skip_callback=false)
Definition: json.hpp:3224
const parser_callback_t callback
callback function
Definition: json.hpp:3300
typename BasicJsonType::parser_callback_t parser_callback_t
Definition: json.hpp:3011
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
bool number_integer(number_integer_t val)
Definition: json.hpp:3041
BasicJsonType & root
the parsed JSON value
Definition: json.hpp:3288
std::vector< BasicJsonType * > ref_stack
stack to model hierarchy of values
Definition: json.hpp:3290
BasicJsonType discarded
a discarded value for the callback
Definition: json.hpp:3304
std::vector< bool > key_keep_stack
stack to manage which object keys to keep
Definition: json.hpp:3294
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:3009
typename BasicJsonType::parse_event_t parse_event_t
Definition: json.hpp:3012
bool parse_error(std::size_t, const std::string &, const detail::exception &ex)
Definition: json.hpp:3174
bool errored
whether a syntax error occurred
Definition: json.hpp:3298
std::vector< bool > keep_stack
stack to manage which values to keep
Definition: json.hpp:3292
bool number_unsigned(number_unsigned_t val)
Definition: json.hpp:3047
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_float(number_float_t val, const string_t &)
Definition: json.hpp:3053
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
json_sax_dom_callback_parser(BasicJsonType &r, const parser_callback_t cb, const bool allow_exceptions_=true)
Definition: json.hpp:3014
SAX implementation to create a JSON value from SAX events.
Definition: json.hpp:2824
bool start_array(std::size_t len)
Definition: json.hpp:2909
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_unsigned(number_unsigned_t val)
Definition: json.hpp:2865
bool errored
whether a syntax error occurred
Definition: json.hpp:2998
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:2826
bool parse_error(std::size_t, const std::string &, const detail::exception &ex)
Definition: json.hpp:2928
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:2827
bool start_object(std::size_t len)
Definition: json.hpp:2883
BasicJsonType * object_element
helper to hold the reference for the next object element
Definition: json.hpp:2996
std::vector< BasicJsonType * > ref_stack
stack to model hierarchy of values
Definition: json.hpp:2994
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition: json.hpp:3000
constexpr bool is_errored() const
Definition: json.hpp:2956
json_sax_dom_parser(json_sax_dom_parser &&)=default
BasicJsonType * handle_value(Value &&v)
Definition: json.hpp:2969
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:2828
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
BasicJsonType & root
the parsed JSON value
Definition: json.hpp:2992
bool number_float(number_float_t val, const string_t &)
Definition: json.hpp:2871
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition: json.hpp:2836
typename BasicJsonType::string_t string_t
Definition: json.hpp:2829
bool number_integer(number_integer_t val)
Definition: json.hpp:2859
lexical analysis
Definition: json.hpp:5533
static void strtof(long double &f, const char *str, char **endptr) noexcept
Definition: json.hpp:6329
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:5535
const char decimal_point_char
the decimal point
Definition: json.hpp:7002
static void strtof(float &f, const char *str, char **endptr) noexcept
Definition: json.hpp:6319
lexer & operator=(lexer &&)=delete
lexer(const lexer &)=delete
constexpr const char * get_error_message() const noexcept
return syntax error message
Definition: json.hpp:6876
bool next_byte_in_range(std::initializer_list< int > ranges)
check if the next byte(s) are inside a given range
Definition: json.hpp:5696
lexer & operator=(lexer &)=delete
number_integer_t value_integer
Definition: json.hpp:6997
token_type
token types for the parser
Definition: json.hpp:5542
@ value_float
an floating point number – use get_number_float() for actual value
@ begin_array
the character for array begin [
@ value_string
a string – use get_string() for actual value
@ end_array
the character for array end ]
@ uninitialized
indicating the scanner is uninitialized
@ parse_error
indicating a parse error
@ value_integer
a signed integer – use get_number_integer() for actual value
@ value_separator
the value separator ,
@ end_object
the character for object end }
@ begin_object
the character for object begin {
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
@ end_of_input
indicating the end of the input buffer
@ name_separator
the name separator :
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
std::char_traits< char >::int_type get()
Definition: json.hpp:6741
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition: json.hpp:6834
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:6979
std::string get_token_string() const
Definition: json.hpp:6852
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition: json.hpp:6822
void unget()
unget current character (read it again on next get)
Definition: json.hpp:6778
token_type scan_number()
scan a number literal
Definition: json.hpp:6374
token_type scan_literal(const char *literal_text, const std::size_t length, token_type return_type)
Definition: json.hpp:6704
bool skip_bom()
skip the UTF-8 byte order mark
Definition: json.hpp:6889
int get_codepoint()
get codepoint from 4 hex characters following \u
Definition: json.hpp:5648
number_float_t value_float
Definition: json.hpp:6999
static void strtof(double &f, const char *str, char **endptr) noexcept
Definition: json.hpp:6324
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition: json.hpp:6991
lexer(lexer &&)=delete
position_t position
the start position of the current token
Definition: json.hpp:6985
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:5534
static const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition: json.hpp:5563
detail::input_adapter_t ia
input adapter
Definition: json.hpp:6976
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:5536
token_type scan()
Definition: json.hpp:6903
typename BasicJsonType::string_t string_t
Definition: json.hpp:5537
lexer(detail::input_adapter_t &&adapter)
Definition: json.hpp:5606
constexpr position_t get_position() const noexcept
return position of last read token
Definition: json.hpp:6844
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition: json.hpp:6828
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition: json.hpp:6724
void add(int c)
add a character to token_buffer
Definition: json.hpp:6805
token_type scan_string()
scan a string literal
Definition: json.hpp:5733
std::vector< char > token_string
raw input token string (for error messages)
Definition: json.hpp:6988
const char * error_message
a description of occurred lexer errors
Definition: json.hpp:6994
static char get_decimal_point() noexcept
return the locale-dependent decimal point
Definition: json.hpp:5622
bool next_unget
whether the next get() call should just return current
Definition: json.hpp:6982
number_unsigned_t value_unsigned
Definition: json.hpp:6998
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition: json.hpp:6816
exception indicating other library errors
Definition: json.hpp:437
static other_error create(int id_, const std::string &what_arg)
Definition: json.hpp:439
other_error(int id_, const char *what_arg)
Definition: json.hpp:446
exception indicating access out of the defined range
Definition: json.hpp:400
static out_of_range create(int id_, const std::string &what_arg)
Definition: json.hpp:402
out_of_range(int id_, const char *what_arg)
Definition: json.hpp:409
output_adapter(std::vector< CharType > &vec)
Definition: json.hpp:9542
output_adapter(std::basic_ostream< CharType > &s)
Definition: json.hpp:9545
output_adapter(StringType &s)
Definition: json.hpp:9548
output adapter for output streams
Definition: json.hpp:9495
void write_character(CharType c) override
Definition: json.hpp:9501
std::basic_ostream< CharType > & stream
Definition: json.hpp:9512
void write_characters(const CharType *s, std::size_t length) override
Definition: json.hpp:9506
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition: json.hpp:9497
output adapter for basic_string
Definition: json.hpp:9518
void write_character(CharType c) override
Definition: json.hpp:9524
void write_characters(const CharType *s, std::size_t length) override
Definition: json.hpp:9529
output_string_adapter(StringType &s) noexcept
Definition: json.hpp:9520
output adapter for byte vectors
Definition: json.hpp:9472
std::vector< CharType > & v
Definition: json.hpp:9489
output_vector_adapter(std::vector< CharType > &vec) noexcept
Definition: json.hpp:9474
void write_characters(const CharType *s, std::size_t length) override
Definition: json.hpp:9483
void write_character(CharType c) override
Definition: json.hpp:9478
exception indicating a parse error
Definition: json.hpp:215
parse_error(int id_, std::size_t byte_, const char *what_arg)
Definition: json.hpp:253
static parse_error create(int id_, const position_t &pos, const std::string &what_arg)
create a parse error exception
Definition: json.hpp:226
const std::size_t byte
byte index of the parse error
Definition: json.hpp:250
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg)
Definition: json.hpp:233
static std::string position_string(const position_t &pos)
Definition: json.hpp:256
syntax analysis
Definition: json.hpp:7048
std::string exception_message(const token_type expected, const std::string &context)
Definition: json.hpp:7470
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition: json.hpp:7096
bool sax_parse(SAX *sax, const bool strict=true)
Definition: json.hpp:7164
parser(detail::input_adapter_t &&adapter, const parser_callback_t cb=nullptr, const bool allow_exceptions_=true)
a parser reading from an input adapter
Definition: json.hpp:7077
bool accept(const bool strict=true)
public accept interface
Definition: json.hpp:7157
typename lexer_t::token_type token_type
Definition: json.hpp:7054
lexer_t m_lexer
the lexer
Definition: json.hpp:7505
token_type get_token()
get next token from lexer
Definition: json.hpp:7465
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:7050
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition: json.hpp:7507
const parser_callback_t callback
callback function
Definition: json.hpp:7501
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:7051
token_type last_token
the type of the last read token
Definition: json.hpp:7503
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:7049
std::function< bool(int depth, parse_event_t event, BasicJsonType &parsed)> parser_callback_t
Definition: json.hpp:7074
bool sax_parse_internal(SAX *sax)
Definition: json.hpp:7183
typename BasicJsonType::string_t string_t
Definition: json.hpp:7052
primitive_iterator_t operator+(difference_type n) noexcept
Definition: json.hpp:7584
primitive_iterator_t & operator++() noexcept
Definition: json.hpp:7596
difference_type m_it
iterator as signed integer type
Definition: json.hpp:7542
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition: json.hpp:7569
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition: json.hpp:7628
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition: json.hpp:7563
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition: json.hpp:7579
void set_begin() noexcept
set iterator to a defined beginning
Definition: json.hpp:7551
primitive_iterator_t const operator++(int) noexcept
Definition: json.hpp:7602
static constexpr difference_type end_value
Definition: json.hpp:7539
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition: json.hpp:7574
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition: json.hpp:7591
primitive_iterator_t & operator--() noexcept
Definition: json.hpp:7609
void set_end() noexcept
set iterator to a defined past the end
Definition: json.hpp:7557
constexpr difference_type get_value() const noexcept
Definition: json.hpp:7545
primitive_iterator_t const operator--(int) noexcept
Definition: json.hpp:7615
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition: json.hpp:7622
static constexpr difference_type begin_value
Definition: json.hpp:7538
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition: json.hpp:12830
unsigned int count_digits(number_unsigned_t x) noexcept
count digits
Definition: json.hpp:12551
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:12040
const std::lconv * loc
the locale
Definition: json.hpp:12815
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition: json.hpp:12812
static constexpr std::uint8_t UTF8_ACCEPT
Definition: json.hpp:12041
void dump_float(number_float_t x, std::true_type)
Definition: json.hpp:12697
serializer(serializer &&)=delete
serializer & operator=(serializer &&)=delete
const char decimal_point
the locale's decimal point character
Definition: json.hpp:12819
void dump_float(number_float_t x, std::false_type)
Definition: json.hpp:12705
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:12038
void dump_float(number_float_t x)
dump a floating-point number
Definition: json.hpp:12676
const char thousands_sep
the locale's thousand separator character
Definition: json.hpp:12817
serializer & operator=(const serializer &)=delete
static constexpr std::uint8_t UTF8_REJECT
Definition: json.hpp:12042
void dump_integer(NumberType x)
dump an integer
Definition: json.hpp:12590
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition: json.hpp:12085
const char indent_char
the indentation character
Definition: json.hpp:12825
std::array< char, 512 > string_buffer
string buffer
Definition: json.hpp:12822
static std::uint8_t decode(std::uint8_t &state, std::uint32_t &codep, const std::uint8_t byte) noexcept
check whether a string is UTF-8 encoded
Definition: json.hpp:12775
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition: json.hpp:12050
void dump_escaped(const string_t &s, const bool ensure_ascii)
dump escaped string
Definition: json.hpp:12295
output_adapter_t< char > o
the output of the serializer
Definition: json.hpp:12809
typename BasicJsonType::string_t string_t
Definition: json.hpp:12037
serializer(const serializer &)=delete
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:12039
string_t indent_string
the indentation string
Definition: json.hpp:12827
exception indicating executing a member function with a wrong type
Definition: json.hpp:354
type_error(int id_, const char *what_arg)
Definition: json.hpp:363
static type_error create(int id_, const std::string &what_arg)
Definition: json.hpp:356
std::size_t current_wchar
index of the current wchar in str
Definition: json.hpp:2556
const WideStringType & str
the wstring to process
Definition: json.hpp:2553
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition: json.hpp:2528
std::size_t utf8_bytes_index
index to the utf8_codes array for the next valid byte
Definition: json.hpp:2562
wide_string_input_adapter(const WideStringType &w) noexcept
Definition: json.hpp:2524
std::size_t utf8_bytes_filled
number of valid bytes in the utf8_codes array
Definition: json.hpp:2564
std::array< std::char_traits< char >::int_type, 4 > utf8_bytes
a buffer for UTF-8 bytes
Definition: json.hpp:2559
JSON Pointer.
Definition: json.hpp:8428
json_pointer top() const
Definition: json.hpp:8753
std::vector< std::string > reference_tokens
the reference tokens
Definition: json.hpp:9347
json_pointer & operator/=(std::string token)
append an unescaped reference token at the end of this JSON pointer
Definition: json.hpp:8529
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition: json.hpp:8505
std::string to_string() const
return a string representation of the JSON pointer
Definition: json.hpp:8473
const BasicJsonType & get_unchecked(const BasicJsonType *ptr) const
return a const reference to the pointed to value
Definition: json.hpp:8994
friend bool operator==(json_pointer const &lhs, json_pointer const &rhs) noexcept
compares two JSON pointers for equality
Definition: json.hpp:9323
void pop_back()
remove last reference token
Definition: json.hpp:8655
const BasicJsonType & get_checked(const BasicJsonType *ptr) const
Definition: json.hpp:9053
bool empty() const noexcept
return whether pointer points to the root document
Definition: json.hpp:8726
friend bool operator!=(json_pointer const &lhs, json_pointer const &rhs) noexcept
compares two JSON pointers for inequality
Definition: json.hpp:9340
void push_back(const std::string &token)
append an unescaped token at the end of the reference pointer
Definition: json.hpp:8701
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8455
static std::string escape(std::string s)
escape "~" to "~0" and "/" to "~1"
Definition: json.hpp:9201
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition: json.hpp:8571
static BasicJsonType unflatten(const BasicJsonType &value)
Definition: json.hpp:9285
friend json_pointer operator/(const json_pointer &ptr, std::string token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition: json.hpp:8592
friend json_pointer operator/(const json_pointer &ptr, std::size_t array_index)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition: json.hpp:8612
const std::string & back()
return last reference token
Definition: json.hpp:8679
BasicJsonType & get_and_create(BasicJsonType &j) const
create and return a reference to the pointed to value
Definition: json.hpp:8773
static void replace_substring(std::string &s, const std::string &f, const std::string &t)
replace all occurrences of a substring by another string
Definition: json.hpp:9189
static void flatten(const std::string &reference_string, const BasicJsonType &value, BasicJsonType &result)
Definition: json.hpp:9222
static void unescape(std::string &s)
unescape "~1" to tilde and "~0" to slash (order is important!)
Definition: json.hpp:9209
void push_back(std::string &&token)
append an unescaped token at the end of the reference pointer
Definition: json.hpp:8707
static int array_index(const std::string &s)
Definition: json.hpp:8739
BasicJsonType & get_checked(BasicJsonType *ptr) const
Definition: json.hpp:8929
json_pointer & operator/=(std::size_t array_index)
append an array index at the end of this JSON pointer
Definition: json.hpp:8551
BasicJsonType & get_unchecked(BasicJsonType *ptr) const
return a reference to the pointed to value
Definition: json.hpp:8853
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition: json.hpp:8630
static std::vector< std::string > split(const std::string &reference_string)
split the string input to reference tokens
Definition: json.hpp:9114
decltype(get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition: json.hpp:1823
A simple vector class template.
Definition: std.hpp:290
void pop_back()
Removes the last element of the vector.
Definition: std.hpp:311
void push_back(const T &value)
Adds an element to the end of the vector.
Definition: std.hpp:304
iterator begin()
Returns an iterator to the first element.
Definition: std.hpp:409
void clear()
Clears the contents of the vector.
Definition: std.hpp:354
iterator end()
Returns an iterator to the last element.
Definition: std.hpp:418
size_t size() const
Returns the number of elements in the vector.
Definition: std.hpp:320
T & back()
Returns a reference to the last element.
Definition: std.hpp:338
void insert(iterator position, const T &value)
Inserts an element at the specified position.
Definition: std.hpp:391
bool empty() const
Checks if the vector is empty.
Definition: std.hpp:347
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition: json.hpp:591
#define NLOHMANN_JSON_VERSION_PATCH
Definition: json.hpp:35
#define JSON_NODISCARD
Definition: json.hpp:503
#define JSON_LIKELY(x)
Definition: json.hpp:545
#define JSON_INTERNAL_CATCH(exception)
Definition: json.hpp:517
#define JSON_DEPRECATED
Definition: json.hpp:490
#define JSON_CATCH(exception)
Definition: json.hpp:516
#define JSON_THROW(exception)
Definition: json.hpp:514
#define NLOHMANN_JSON_VERSION_MAJOR
Definition: json.hpp:33
#define NLOHMANN_BASIC_JSON_TPL
Definition: json.hpp:599
#define JSON_TRY
Definition: json.hpp:515
#define NLOHMANN_JSON_VERSION_MINOR
Definition: json.hpp:34
#define JSON_UNLIKELY(x)
Definition: json.hpp:546
T * ptr(T &obj)
returns a pointer (transforms reference into pointer)
Definition: utils.hpp:32
Vector3D operator-(const Vector3D &v1, const Vector3D &v2)
Definition: vector3D.h:557
Vector3D operator+(const Vector3D &v1, const Vector3D &v2)
Definition: vector3D.h:546
void swap(shared_lock< Mutex > &lhs, shared_lock< Mutex > &rhs) noexcept
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition: json.hpp:11727
Target reinterpret_bits(const Source source)
Definition: json.hpp:10946
boundaries compute_boundaries(FloatType value)
Definition: json.hpp:11087
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition: json.hpp:11390
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition: json.hpp:11446
char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition: json.hpp:11874
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition: json.hpp:11487
char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition: json.hpp:11824
cached_power get_cached_power_for_binary_exponent(int e)
Definition: json.hpp:11226
typename std::enable_if< B, T >::type enable_if_t
Definition: json.hpp:617
typename T::reference reference_t
Definition: json.hpp:927
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:1277
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition: json.hpp:939
void to_json(BasicJsonType &j, T b) noexcept
Definition: json.hpp:2019
value_t
the JSON type enumeration
Definition: json.hpp:1255
@ number_integer
number value (signed integer)
@ discarded
discarded by the the parser callback function
@ object
object (unordered set of name/value pairs)
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition: json.hpp:1298
decltype(std::declval< T & >().parse_error(std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition: json.hpp:3442
typename T::pointer pointer_t
Definition: json.hpp:924
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition: json.hpp:3419
void from_json_tuple_impl(const BasicJsonType &j, Tuple &t, index_sequence< Idx... >)
Definition: json.hpp:1573
typename T::difference_type difference_type_t
Definition: json.hpp:921
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition: json.hpp:793
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition: json.hpp:1431
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition: json.hpp:3427
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition: json.hpp:3403
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition: json.hpp:3407
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition: json.hpp:2136
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition: json.hpp:806
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition: json.hpp:620
error_handler_t
how to treat decoding errors
Definition: json.hpp:12028
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition: json.hpp:3423
typename T::key_type key_type_t
Definition: json.hpp:915
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition: json.hpp:3411
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition: json.hpp:802
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition: json.hpp:799
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition: json.hpp:3434
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition: json.hpp:1312
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition: json.hpp:790
typename make_void< Ts... >::type void_t
Definition: json.hpp:693
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition: json.hpp:9467
typename T::mapped_type mapped_type_t
Definition: json.hpp:912
typename T::iterator iterator_t
Definition: json.hpp:933
input_format_t
the supported input formats
Definition: json.hpp:2259
void to_json(BasicJsonType &j, const std::tuple< Args... > &t)
Definition: json.hpp:2142
decltype(std::declval< T >().template get< U >()) get_template_function
Definition: json.hpp:942
decltype(std::declval< T & >().null()) null_function_t
Definition: json.hpp:3399
char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition: json.hpp:11957
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:1787
typename T::iterator_category iterator_category_t
Definition: json.hpp:930
decltype(std::declval< T & >().number_float(std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition: json.hpp:3415
std::shared_ptr< input_adapter_protocol > input_adapter_t
a type to simplify interfaces
Definition: json.hpp:2284
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition: json.hpp:3437
void from_json(const BasicJsonType &j, std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > &m)
Definition: json.hpp:1606
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition: json.hpp:3430
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition: json.hpp:936
typename T::value_type value_type_t
Definition: json.hpp:918
namespace for Niels Lohmann
Definition: json.hpp:85
basic_json<> json
default JSON class
Definition: json.hpp:871
Provides common mathematical functions and vector operations.
Definition: std.hpp:4
int abs(int x)
Computes the absolute value of an integer.
Definition: std.hpp:83
double exp(double x)
Computes the exponential function of a number.
Definition: std.hpp:22
default JSONSerializer template argument
Definition: json.hpp:2171
static auto to_json(BasicJsonType &j, ValueType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< ValueType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< ValueType >(val)), void())
convert any value type to a JSON value
Definition: json.hpp:2199
static auto from_json(BasicJsonType &&j, ValueType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition: json.hpp:2182
std::false_type value_t
Definition: json.hpp:778
static constexpr int kPrecision
Definition: json.hpp:10957
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition: json.hpp:11045
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition: json.hpp:11062
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition: json.hpp:10980
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition: json.hpp:10962
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition: json.hpp:10968
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition: json.hpp:1947
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition: json.hpp:1971
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition: json.hpp:1957
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition: json.hpp:1937
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition: json.hpp:1929
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition: json.hpp:1851
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition: json.hpp:1893
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition: json.hpp:1917
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition: json.hpp:1905
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition: json.hpp:1993
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition: json.hpp:1985
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition: json.hpp:2002
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition: json.hpp:1871
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition: json.hpp:1881
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition: json.hpp:1863
auto operator()(const BasicJsonType &j, T &val) const noexcept(noexcept(from_json(j, val))) -> decltype(from_json(j, val), void())
Definition: json.hpp:1625
typename BasicJsonType::template json_serializer< T, void > serializer
Definition: json.hpp:952
typename BasicJsonType::template json_serializer< T, void > serializer
Definition: json.hpp:982
static constexpr std::size_t size() noexcept
Definition: json.hpp:629
abstract input adapter interface
Definition: json.hpp:2277
virtual std::char_traits< char >::int_type get_character()=0
get a character [0,255] or std::char_traits<char>::eof().
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition: json.hpp:7655
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition: json.hpp:7653
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition: json.hpp:7651
typename BasicJsonType::string_t string_t
Definition: json.hpp:3486
typename BasicJsonType::exception exception_t
Definition: json.hpp:3487
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:3483
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:3485
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:3484
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:3453
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:3452
typename BasicJsonType::exception exception_t
Definition: json.hpp:3455
static constexpr bool value
Definition: json.hpp:3458
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:3451
typename BasicJsonType::string_t string_t
Definition: json.hpp:3454
nonesuch(nonesuch const &)=delete
void operator=(nonesuch &&)=delete
nonesuch(nonesuch const &&)=delete
void operator=(nonesuch const &)=delete
abstract output adapter interface
Definition: json.hpp:9459
virtual void write_characters(const CharType *s, std::size_t length)=0
virtual void write_character(CharType c)=0
struct to capture the start position of the current token
Definition: json.hpp:90
std::size_t lines_read
the number of lines read
Definition: json.hpp:96
std::size_t chars_read_current_line
the number of characters read in the current line
Definition: json.hpp:94
std::size_t chars_read_total
the total number of characters read
Definition: json.hpp:92
static constexpr T value
Definition: json.hpp:661
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition: json.hpp:2150
static void fill_buffer(const WideStringType &str, size_t &current_wchar, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition: json.hpp:2459
static void fill_buffer(const WideStringType &str, size_t &current_wchar, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition: json.hpp:2400
SAX interface.
Definition: json.hpp:2703
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool string(string_t &val)=0
a string was read
virtual bool null()=0
a null value was read
typename BasicJsonType::number_integer_t number_integer_t
type for (signed) integers
Definition: json.hpp:2705
virtual bool end_array()=0
the end of an array was read
virtual bool key(string_t &val)=0
an object key was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
type for unsigned integers
Definition: json.hpp:2707
typename BasicJsonType::number_float_t number_float_t
type for floating-point numbers
Definition: json.hpp:2709
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
typename BasicJsonType::string_t string_t
type for strings
Definition: json.hpp:2711
virtual bool number_float(number_float_t val, const string_t &s)=0
an floating-point number was read
virtual ~json_sax()=default
virtual bool number_integer(number_integer_t val)=0
an integer number was read
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:20739
bool operator()(nlohmann::detail::value_t lhs, nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition: json.hpp:20757
number_unsigned_t number_unsigned
number (unsigned integer)
Definition: json.hpp:13648
json_value(number_unsigned_t v) noexcept
constructor for numbers (unsigned)
Definition: json.hpp:13659
json_value(const array_t &value)
constructor for arrays
Definition: json.hpp:13752
json_value(boolean_t v) noexcept
constructor for booleans
Definition: json.hpp:13655
json_value(value_t t)
constructor for empty values of a given type
Definition: json.hpp:13663
json_value()=default
default constructor (for null values)
json_value(number_float_t v) noexcept
constructor for numbers (floating-point)
Definition: json.hpp:13661
object_t * object
object (stored with pointer to save storage)
Definition: json.hpp:13638
json_value(number_integer_t v) noexcept
constructor for numbers (integer)
Definition: json.hpp:13657
json_value(array_t &&value)
constructor for rvalue arrays
Definition: json.hpp:13758
json_value(const object_t &value)
constructor for objects
Definition: json.hpp:13740
array_t * array
array (stored with pointer to save storage)
Definition: json.hpp:13640
json_value(object_t &&value)
constructor for rvalue objects
Definition: json.hpp:13746
json_value(const string_t &value)
constructor for strings
Definition: json.hpp:13728
string_t * string
string (stored with pointer to save storage)
Definition: json.hpp:13642
json_value(string_t &&value)
constructor for rvalue strings
Definition: json.hpp:13734
number_float_t number_float
number (floating-point)
Definition: json.hpp:13650
void destroy(value_t t) noexcept
Definition: json.hpp:13763
number_integer_t number_integer
number (integer)
Definition: json.hpp:13646