Dump the entire json library in
This commit is contained in:
		
							
								
								
									
										100
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/abi_macros.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/abi_macros.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| // This file contains all macro definitions affecting or depending on the ABI | ||||
|  | ||||
| #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK | ||||
|     #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) | ||||
|         #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 | ||||
|             #warning "Already included a different version of the library!" | ||||
|         #endif | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
| #define NLOHMANN_JSON_VERSION_MAJOR 3   // NOLINT(modernize-macro-to-enum) | ||||
| #define NLOHMANN_JSON_VERSION_MINOR 11  // NOLINT(modernize-macro-to-enum) | ||||
| #define NLOHMANN_JSON_VERSION_PATCH 2   // NOLINT(modernize-macro-to-enum) | ||||
|  | ||||
| #ifndef JSON_DIAGNOSTICS | ||||
|     #define JSON_DIAGNOSTICS 0 | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | ||||
|     #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 | ||||
| #endif | ||||
|  | ||||
| #if JSON_DIAGNOSTICS | ||||
|     #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag | ||||
| #else | ||||
|     #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS | ||||
| #endif | ||||
|  | ||||
| #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | ||||
|     #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp | ||||
| #else | ||||
|     #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON | ||||
| #endif | ||||
|  | ||||
| #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION | ||||
|     #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 | ||||
| #endif | ||||
|  | ||||
| // Construct the namespace ABI tags component | ||||
| #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b | ||||
| #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ | ||||
|     NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) | ||||
|  | ||||
| #define NLOHMANN_JSON_ABI_TAGS                                       \ | ||||
|     NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \ | ||||
|             NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \ | ||||
|             NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) | ||||
|  | ||||
| // Construct the namespace version component | ||||
| #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ | ||||
|     _v ## major ## _ ## minor ## _ ## patch | ||||
| #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ | ||||
|     NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) | ||||
|  | ||||
| #if NLOHMANN_JSON_NAMESPACE_NO_VERSION | ||||
| #define NLOHMANN_JSON_NAMESPACE_VERSION | ||||
| #else | ||||
| #define NLOHMANN_JSON_NAMESPACE_VERSION                                 \ | ||||
|     NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ | ||||
|                                            NLOHMANN_JSON_VERSION_MINOR, \ | ||||
|                                            NLOHMANN_JSON_VERSION_PATCH) | ||||
| #endif | ||||
|  | ||||
| // Combine namespace components | ||||
| #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b | ||||
| #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ | ||||
|     NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) | ||||
|  | ||||
| #ifndef NLOHMANN_JSON_NAMESPACE | ||||
| #define NLOHMANN_JSON_NAMESPACE               \ | ||||
|     nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ | ||||
|             NLOHMANN_JSON_ABI_TAGS,           \ | ||||
|             NLOHMANN_JSON_NAMESPACE_VERSION) | ||||
| #endif | ||||
|  | ||||
| #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| #define NLOHMANN_JSON_NAMESPACE_BEGIN                \ | ||||
|     namespace nlohmann                               \ | ||||
|     {                                                \ | ||||
|     inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ | ||||
|                 NLOHMANN_JSON_ABI_TAGS,              \ | ||||
|                 NLOHMANN_JSON_NAMESPACE_VERSION)     \ | ||||
|     { | ||||
| #endif | ||||
|  | ||||
| #ifndef NLOHMANN_JSON_NAMESPACE_END | ||||
| #define NLOHMANN_JSON_NAMESPACE_END                                     \ | ||||
|     }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \ | ||||
|     }  // namespace nlohmann | ||||
| #endif | ||||
| @@ -0,0 +1,497 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <algorithm> // transform | ||||
| #include <array> // array | ||||
| #include <forward_list> // forward_list | ||||
| #include <iterator> // inserter, front_inserter, end | ||||
| #include <map> // map | ||||
| #include <string> // string | ||||
| #include <tuple> // tuple, make_tuple | ||||
| #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible | ||||
| #include <unordered_map> // unordered_map | ||||
| #include <utility> // pair, declval | ||||
| #include <valarray> // valarray | ||||
|  | ||||
| #include <nlohmann/detail/exceptions.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
| #include <nlohmann/detail/meta/identity_tag.hpp> | ||||
| #include <nlohmann/detail/meta/std_fs.hpp> | ||||
| #include <nlohmann/detail/meta/type_traits.hpp> | ||||
| #include <nlohmann/detail/string_concat.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_null())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     n = nullptr; | ||||
| } | ||||
|  | ||||
| // overloads for basic_json template parameters | ||||
| template < typename BasicJsonType, typename ArithmeticType, | ||||
|            enable_if_t < std::is_arithmetic<ArithmeticType>::value&& | ||||
|                          !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, | ||||
|                          int > = 0 > | ||||
| void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) | ||||
| { | ||||
|     switch (static_cast<value_t>(j)) | ||||
|     { | ||||
|         case value_t::number_unsigned: | ||||
|         { | ||||
|             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); | ||||
|             break; | ||||
|         } | ||||
|         case value_t::number_integer: | ||||
|         { | ||||
|             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); | ||||
|             break; | ||||
|         } | ||||
|         case value_t::number_float: | ||||
|         { | ||||
|             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         case value_t::null: | ||||
|         case value_t::object: | ||||
|         case value_t::array: | ||||
|         case value_t::string: | ||||
|         case value_t::boolean: | ||||
|         case value_t::binary: | ||||
|         case value_t::discarded: | ||||
|         default: | ||||
|             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_string())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); | ||||
| } | ||||
|  | ||||
| template < | ||||
|     typename BasicJsonType, typename StringType, | ||||
|     enable_if_t < | ||||
|         std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value | ||||
|         && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value | ||||
|         && !std::is_same<typename BasicJsonType::string_t, StringType>::value | ||||
|         && !is_json_ref<StringType>::value, int > = 0 > | ||||
| inline void from_json(const BasicJsonType& j, StringType& s) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_string())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|  | ||||
|     s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) | ||||
| { | ||||
|     get_arithmetic_value(j, val); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) | ||||
| { | ||||
|     get_arithmetic_value(j, val); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) | ||||
| { | ||||
|     get_arithmetic_value(j, val); | ||||
| } | ||||
|  | ||||
| #if !JSON_DISABLE_ENUM_SERIALIZATION | ||||
| template<typename BasicJsonType, typename EnumType, | ||||
|          enable_if_t<std::is_enum<EnumType>::value, int> = 0> | ||||
| inline void from_json(const BasicJsonType& j, EnumType& e) | ||||
| { | ||||
|     typename std::underlying_type<EnumType>::type val; | ||||
|     get_arithmetic_value(j, val); | ||||
|     e = static_cast<EnumType>(val); | ||||
| } | ||||
| #endif  // JSON_DISABLE_ENUM_SERIALIZATION | ||||
|  | ||||
| // forward_list doesn't have an insert method | ||||
| template<typename BasicJsonType, typename T, typename Allocator, | ||||
|          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> | ||||
| inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     l.clear(); | ||||
|     std::transform(j.rbegin(), j.rend(), | ||||
|                    std::front_inserter(l), [](const BasicJsonType & i) | ||||
|     { | ||||
|         return i.template get<T>(); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| // valarray doesn't have an insert method | ||||
| template<typename BasicJsonType, typename T, | ||||
|          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> | ||||
| inline void from_json(const BasicJsonType& j, std::valarray<T>& l) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     l.resize(j.size()); | ||||
|     std::transform(j.begin(), j.end(), std::begin(l), | ||||
|                    [](const BasicJsonType & elem) | ||||
|     { | ||||
|         return elem.template get<T>(); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename T, std::size_t N> | ||||
| auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | ||||
| -> decltype(j.template get<T>(), void()) | ||||
| { | ||||
|     for (std::size_t i = 0; i < N; ++i) | ||||
|     { | ||||
|         arr[i] = j.at(i).template get<T>(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) | ||||
| { | ||||
|     arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename T, std::size_t N> | ||||
| auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, | ||||
|                           priority_tag<2> /*unused*/) | ||||
| -> decltype(j.template get<T>(), void()) | ||||
| { | ||||
|     for (std::size_t i = 0; i < N; ++i) | ||||
|     { | ||||
|         arr[i] = j.at(i).template get<T>(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleArrayType, | ||||
|          enable_if_t< | ||||
|              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, | ||||
|              int> = 0> | ||||
| auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) | ||||
| -> decltype( | ||||
|     arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), | ||||
|     j.template get<typename ConstructibleArrayType::value_type>(), | ||||
|     void()) | ||||
| { | ||||
|     using std::end; | ||||
|  | ||||
|     ConstructibleArrayType ret; | ||||
|     ret.reserve(j.size()); | ||||
|     std::transform(j.begin(), j.end(), | ||||
|                    std::inserter(ret, end(ret)), [](const BasicJsonType & i) | ||||
|     { | ||||
|         // get<BasicJsonType>() returns *this, this won't call a from_json | ||||
|         // method when value_type is BasicJsonType | ||||
|         return i.template get<typename ConstructibleArrayType::value_type>(); | ||||
|     }); | ||||
|     arr = std::move(ret); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleArrayType, | ||||
|          enable_if_t< | ||||
|              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, | ||||
|              int> = 0> | ||||
| inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, | ||||
|                                  priority_tag<0> /*unused*/) | ||||
| { | ||||
|     using std::end; | ||||
|  | ||||
|     ConstructibleArrayType ret; | ||||
|     std::transform( | ||||
|         j.begin(), j.end(), std::inserter(ret, end(ret)), | ||||
|         [](const BasicJsonType & i) | ||||
|     { | ||||
|         // get<BasicJsonType>() returns *this, this won't call a from_json | ||||
|         // method when value_type is BasicJsonType | ||||
|         return i.template get<typename ConstructibleArrayType::value_type>(); | ||||
|     }); | ||||
|     arr = std::move(ret); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename ConstructibleArrayType, | ||||
|            enable_if_t < | ||||
|                is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&& | ||||
|                !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&& | ||||
|                !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&& | ||||
|                !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&& | ||||
|                !is_basic_json<ConstructibleArrayType>::value, | ||||
|                int > = 0 > | ||||
| auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) | ||||
| -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), | ||||
| j.template get<typename ConstructibleArrayType::value_type>(), | ||||
| void()) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|  | ||||
|     from_json_array_impl(j, arr, priority_tag<3> {}); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename T, std::size_t... Idx > | ||||
| std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j, | ||||
|         identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) | ||||
| { | ||||
|     return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } }; | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename T, std::size_t N > | ||||
| auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag) | ||||
| -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|  | ||||
|     return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|  | ||||
|     bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleObjectType, | ||||
|          enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0> | ||||
| inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_object())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|  | ||||
|     ConstructibleObjectType ret; | ||||
|     const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); | ||||
|     using value_type = typename ConstructibleObjectType::value_type; | ||||
|     std::transform( | ||||
|         inner_object->begin(), inner_object->end(), | ||||
|         std::inserter(ret, ret.begin()), | ||||
|         [](typename BasicJsonType::object_t::value_type const & p) | ||||
|     { | ||||
|         return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); | ||||
|     }); | ||||
|     obj = std::move(ret); | ||||
| } | ||||
|  | ||||
| // overload for arithmetic types, not chosen for basic_json template arguments | ||||
| // (BooleanType, etc..); note: Is it really necessary to provide explicit | ||||
| // overloads for boolean_t etc. in case of a custom BooleanType which is not | ||||
| // an arithmetic type? | ||||
| template < typename BasicJsonType, typename ArithmeticType, | ||||
|            enable_if_t < | ||||
|                std::is_arithmetic<ArithmeticType>::value&& | ||||
|                !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&& | ||||
|                !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&& | ||||
|                !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&& | ||||
|                !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, | ||||
|                int > = 0 > | ||||
| inline void from_json(const BasicJsonType& j, ArithmeticType& val) | ||||
| { | ||||
|     switch (static_cast<value_t>(j)) | ||||
|     { | ||||
|         case value_t::number_unsigned: | ||||
|         { | ||||
|             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); | ||||
|             break; | ||||
|         } | ||||
|         case value_t::number_integer: | ||||
|         { | ||||
|             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); | ||||
|             break; | ||||
|         } | ||||
|         case value_t::number_float: | ||||
|         { | ||||
|             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); | ||||
|             break; | ||||
|         } | ||||
|         case value_t::boolean: | ||||
|         { | ||||
|             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         case value_t::null: | ||||
|         case value_t::object: | ||||
|         case value_t::array: | ||||
|         case value_t::string: | ||||
|         case value_t::binary: | ||||
|         case value_t::discarded: | ||||
|         default: | ||||
|             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename... Args, std::size_t... Idx> | ||||
| std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) | ||||
| { | ||||
|     return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, class A1, class A2 > | ||||
| std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) | ||||
| { | ||||
|     return {std::forward<BasicJsonType>(j).at(0).template get<A1>(), | ||||
|             std::forward<BasicJsonType>(j).at(1).template get<A2>()}; | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename A1, typename A2> | ||||
| inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) | ||||
| { | ||||
|     p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {}); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename... Args> | ||||
| std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) | ||||
| { | ||||
|     return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename... Args> | ||||
| inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) | ||||
| { | ||||
|     t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename TupleRelated> | ||||
| auto from_json(BasicJsonType&& j, TupleRelated&& t) | ||||
| -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|  | ||||
|     return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, | ||||
|            typename = enable_if_t < !std::is_constructible < | ||||
|                                         typename BasicJsonType::string_t, Key >::value >> | ||||
| inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     m.clear(); | ||||
|     for (const auto& p : j) | ||||
|     { | ||||
|         if (JSON_HEDLEY_UNLIKELY(!p.is_array())) | ||||
|         { | ||||
|             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); | ||||
|         } | ||||
|         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, | ||||
|            typename = enable_if_t < !std::is_constructible < | ||||
|                                         typename BasicJsonType::string_t, Key >::value >> | ||||
| inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     m.clear(); | ||||
|     for (const auto& p : j) | ||||
|     { | ||||
|         if (JSON_HEDLEY_UNLIKELY(!p.is_array())) | ||||
|         { | ||||
|             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); | ||||
|         } | ||||
|         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
| template<typename BasicJsonType> | ||||
| inline void from_json(const BasicJsonType& j, std_fs::path& p) | ||||
| { | ||||
|     if (JSON_HEDLEY_UNLIKELY(!j.is_string())) | ||||
|     { | ||||
|         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); | ||||
|     } | ||||
|     p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| struct from_json_fn | ||||
| { | ||||
|     template<typename BasicJsonType, typename T> | ||||
|     auto operator()(const BasicJsonType& j, T&& val) const | ||||
|     noexcept(noexcept(from_json(j, std::forward<T>(val)))) | ||||
|     -> decltype(from_json(j, std::forward<T>(val))) | ||||
|     { | ||||
|         return from_json(j, std::forward<T>(val)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
|  | ||||
| #ifndef JSON_HAS_CPP_17 | ||||
| /// namespace to hold default `from_json` function | ||||
| /// to see why this is required: | ||||
| /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html | ||||
| namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) | ||||
| { | ||||
| #endif | ||||
| JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) | ||||
|     detail::static_const<detail::from_json_fn>::value; | ||||
| #ifndef JSON_HAS_CPP_17 | ||||
| }  // namespace | ||||
| #endif | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,446 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <algorithm> // copy | ||||
| #include <iterator> // begin, end | ||||
| #include <string> // string | ||||
| #include <tuple> // tuple, get | ||||
| #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type | ||||
| #include <utility> // move, forward, declval, pair | ||||
| #include <valarray> // valarray | ||||
| #include <vector> // vector | ||||
|  | ||||
| #include <nlohmann/detail/iterators/iteration_proxy.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
| #include <nlohmann/detail/meta/std_fs.hpp> | ||||
| #include <nlohmann/detail/meta/type_traits.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| ////////////////// | ||||
| // constructors // | ||||
| ////////////////// | ||||
|  | ||||
| /* | ||||
|  * Note all external_constructor<>::construct functions need to call | ||||
|  * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an | ||||
|  * allocated value (e.g., a string). See bug issue | ||||
|  * https://github.com/nlohmann/json/issues/2865 for more information. | ||||
|  */ | ||||
|  | ||||
| template<value_t> struct external_constructor; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::boolean> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::boolean; | ||||
|         j.m_data.m_value = b; | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::string> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::string; | ||||
|         j.m_data.m_value = s; | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::string; | ||||
|         j.m_data.m_value = std::move(s); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template < typename BasicJsonType, typename CompatibleStringType, | ||||
|                enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, | ||||
|                              int > = 0 > | ||||
|     static void construct(BasicJsonType& j, const CompatibleStringType& str) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::string; | ||||
|         j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::binary> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::binary; | ||||
|         j.m_data.m_value = typename BasicJsonType::binary_t(b); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::binary; | ||||
|         j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::number_float> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::number_float; | ||||
|         j.m_data.m_value = val; | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::number_unsigned> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::number_unsigned; | ||||
|         j.m_data.m_value = val; | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::number_integer> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::number_integer; | ||||
|         j.m_data.m_value = val; | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::array> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::array; | ||||
|         j.m_data.m_value = arr; | ||||
|         j.set_parents(); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::array; | ||||
|         j.m_data.m_value = std::move(arr); | ||||
|         j.set_parents(); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template < typename BasicJsonType, typename CompatibleArrayType, | ||||
|                enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, | ||||
|                              int > = 0 > | ||||
|     static void construct(BasicJsonType& j, const CompatibleArrayType& arr) | ||||
|     { | ||||
|         using std::begin; | ||||
|         using std::end; | ||||
|  | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::array; | ||||
|         j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); | ||||
|         j.set_parents(); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, const std::vector<bool>& arr) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::array; | ||||
|         j.m_data.m_value = value_t::array; | ||||
|         j.m_data.m_value.array->reserve(arr.size()); | ||||
|         for (const bool x : arr) | ||||
|         { | ||||
|             j.m_data.m_value.array->push_back(x); | ||||
|             j.set_parent(j.m_data.m_value.array->back()); | ||||
|         } | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonType, typename T, | ||||
|              enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> | ||||
|     static void construct(BasicJsonType& j, const std::valarray<T>& arr) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::array; | ||||
|         j.m_data.m_value = value_t::array; | ||||
|         j.m_data.m_value.array->resize(arr.size()); | ||||
|         if (arr.size() > 0) | ||||
|         { | ||||
|             std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); | ||||
|         } | ||||
|         j.set_parents(); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> | ||||
| struct external_constructor<value_t::object> | ||||
| { | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::object; | ||||
|         j.m_data.m_value = obj; | ||||
|         j.set_parents(); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonType> | ||||
|     static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) | ||||
|     { | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::object; | ||||
|         j.m_data.m_value = std::move(obj); | ||||
|         j.set_parents(); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     template < typename BasicJsonType, typename CompatibleObjectType, | ||||
|                enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 > | ||||
|     static void construct(BasicJsonType& j, const CompatibleObjectType& obj) | ||||
|     { | ||||
|         using std::begin; | ||||
|         using std::end; | ||||
|  | ||||
|         j.m_data.m_value.destroy(j.m_data.m_type); | ||||
|         j.m_data.m_type = value_t::object; | ||||
|         j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); | ||||
|         j.set_parents(); | ||||
|         j.assert_invariant(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| ///////////// | ||||
| // to_json // | ||||
| ///////////// | ||||
|  | ||||
| template<typename BasicJsonType, typename T, | ||||
|          enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, T b) noexcept | ||||
| { | ||||
|     external_constructor<value_t::boolean>::construct(j, b); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename BoolRef, | ||||
|            enable_if_t < | ||||
|                ((std::is_same<std::vector<bool>::reference, BoolRef>::value | ||||
|                  && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) | ||||
|                 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value | ||||
|                     && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>, | ||||
|                                       typename BasicJsonType::boolean_t >::value)) | ||||
|                && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 > | ||||
| inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept | ||||
| { | ||||
|     external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b)); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleString, | ||||
|          enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, const CompatibleString& s) | ||||
| { | ||||
|     external_constructor<value_t::string>::construct(j, s); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) | ||||
| { | ||||
|     external_constructor<value_t::string>::construct(j, std::move(s)); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename FloatType, | ||||
|          enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, FloatType val) noexcept | ||||
| { | ||||
|     external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleNumberUnsignedType, | ||||
|          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept | ||||
| { | ||||
|     external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleNumberIntegerType, | ||||
|          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept | ||||
| { | ||||
|     external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); | ||||
| } | ||||
|  | ||||
| #if !JSON_DISABLE_ENUM_SERIALIZATION | ||||
| template<typename BasicJsonType, typename EnumType, | ||||
|          enable_if_t<std::is_enum<EnumType>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, EnumType e) noexcept | ||||
| { | ||||
|     using underlying_type = typename std::underlying_type<EnumType>::type; | ||||
|     external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); | ||||
| } | ||||
| #endif  // JSON_DISABLE_ENUM_SERIALIZATION | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void to_json(BasicJsonType& j, const std::vector<bool>& e) | ||||
| { | ||||
|     external_constructor<value_t::array>::construct(j, e); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename CompatibleArrayType, | ||||
|            enable_if_t < is_compatible_array_type<BasicJsonType, | ||||
|                          CompatibleArrayType>::value&& | ||||
|                          !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&& | ||||
|                          !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&& | ||||
|                          !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&& | ||||
|                          !is_basic_json<CompatibleArrayType>::value, | ||||
|                          int > = 0 > | ||||
| inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) | ||||
| { | ||||
|     external_constructor<value_t::array>::construct(j, arr); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) | ||||
| { | ||||
|     external_constructor<value_t::binary>::construct(j, bin); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename T, | ||||
|          enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) | ||||
| { | ||||
|     external_constructor<value_t::array>::construct(j, std::move(arr)); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) | ||||
| { | ||||
|     external_constructor<value_t::array>::construct(j, std::move(arr)); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename CompatibleObjectType, | ||||
|            enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 > | ||||
| inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) | ||||
| { | ||||
|     external_constructor<value_t::object>::construct(j, obj); | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) | ||||
| { | ||||
|     external_constructor<value_t::object>::construct(j, std::move(obj)); | ||||
| } | ||||
|  | ||||
| template < | ||||
|     typename BasicJsonType, typename T, std::size_t N, | ||||
|     enable_if_t < !std::is_constructible<typename BasicJsonType::string_t, | ||||
|                   const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | ||||
|                   int > = 0 > | ||||
| inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | ||||
| { | ||||
|     external_constructor<value_t::array>::construct(j, arr); | ||||
| } | ||||
|  | ||||
| template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 > | ||||
| inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) | ||||
| { | ||||
|     j = { p.first, p.second }; | ||||
| } | ||||
|  | ||||
| // for https://github.com/nlohmann/json/pull/1134 | ||||
| template<typename BasicJsonType, typename T, | ||||
|          enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0> | ||||
| inline void to_json(BasicJsonType& j, const T& b) | ||||
| { | ||||
|     j = { {b.key(), b.value()} }; | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename Tuple, std::size_t... Idx> | ||||
| inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) | ||||
| { | ||||
|     j = { std::get<Idx>(t)... }; | ||||
| } | ||||
|  | ||||
| template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> | ||||
| inline void to_json(BasicJsonType& j, const T& t) | ||||
| { | ||||
|     to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); | ||||
| } | ||||
|  | ||||
| #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
| template<typename BasicJsonType> | ||||
| inline void to_json(BasicJsonType& j, const std_fs::path& p) | ||||
| { | ||||
|     j = p.string(); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| struct to_json_fn | ||||
| { | ||||
|     template<typename BasicJsonType, typename T> | ||||
|     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()) | ||||
|     { | ||||
|         return to_json(j, std::forward<T>(val)); | ||||
|     } | ||||
| }; | ||||
| }  // namespace detail | ||||
|  | ||||
| #ifndef JSON_HAS_CPP_17 | ||||
| /// namespace to hold default `to_json` function | ||||
| /// to see why this is required: | ||||
| /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html | ||||
| namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) | ||||
| { | ||||
| #endif | ||||
| JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) | ||||
|     detail::static_const<detail::to_json_fn>::value; | ||||
| #ifndef JSON_HAS_CPP_17 | ||||
| }  // namespace | ||||
| #endif | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
							
								
								
									
										257
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/exceptions.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/exceptions.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,257 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstddef> // nullptr_t | ||||
| #include <exception> // exception | ||||
| #if JSON_DIAGNOSTICS | ||||
|     #include <numeric> // accumulate | ||||
| #endif | ||||
| #include <stdexcept> // runtime_error | ||||
| #include <string> // to_string | ||||
| #include <vector> // vector | ||||
|  | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
| #include <nlohmann/detail/string_escape.hpp> | ||||
| #include <nlohmann/detail/input/position_t.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
| #include <nlohmann/detail/meta/type_traits.hpp> | ||||
| #include <nlohmann/detail/string_concat.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| //////////////// | ||||
| // exceptions // | ||||
| //////////////// | ||||
|  | ||||
| /// @brief general exception of the @ref basic_json class | ||||
| /// @sa https://json.nlohmann.me/api/basic_json/exception/ | ||||
| class exception : public std::exception | ||||
| { | ||||
|   public: | ||||
|     /// returns the explanatory string | ||||
|     const char* what() const noexcept override | ||||
|     { | ||||
|         return m.what(); | ||||
|     } | ||||
|  | ||||
|     /// the id of the exception | ||||
|     const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) | ||||
|  | ||||
|   protected: | ||||
|     JSON_HEDLEY_NON_NULL(3) | ||||
|     exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) | ||||
|  | ||||
|     static std::string name(const std::string& ename, int id_) | ||||
|     { | ||||
|         return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); | ||||
|     } | ||||
|  | ||||
|     static std::string diagnostics(std::nullptr_t /*leaf_element*/) | ||||
|     { | ||||
|         return ""; | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonType> | ||||
|     static std::string diagnostics(const BasicJsonType* leaf_element) | ||||
|     { | ||||
| #if JSON_DIAGNOSTICS | ||||
|         std::vector<std::string> tokens; | ||||
|         for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) | ||||
|         { | ||||
|             switch (current->m_parent->type()) | ||||
|             { | ||||
|                 case value_t::array: | ||||
|                 { | ||||
|                     for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) | ||||
|                     { | ||||
|                         if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) | ||||
|                         { | ||||
|                             tokens.emplace_back(std::to_string(i)); | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case value_t::object: | ||||
|                 { | ||||
|                     for (const auto& element : *current->m_parent->m_data.m_value.object) | ||||
|                     { | ||||
|                         if (&element.second == current) | ||||
|                         { | ||||
|                             tokens.emplace_back(element.first.c_str()); | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case value_t::null: // LCOV_EXCL_LINE | ||||
|                 case value_t::string: // LCOV_EXCL_LINE | ||||
|                 case value_t::boolean: // LCOV_EXCL_LINE | ||||
|                 case value_t::number_integer: // LCOV_EXCL_LINE | ||||
|                 case value_t::number_unsigned: // LCOV_EXCL_LINE | ||||
|                 case value_t::number_float: // LCOV_EXCL_LINE | ||||
|                 case value_t::binary: // LCOV_EXCL_LINE | ||||
|                 case value_t::discarded: // LCOV_EXCL_LINE | ||||
|                 default:   // LCOV_EXCL_LINE | ||||
|                     break; // LCOV_EXCL_LINE | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (tokens.empty()) | ||||
|         { | ||||
|             return ""; | ||||
|         } | ||||
|  | ||||
|         auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, | ||||
|                                    [](const std::string & a, const std::string & b) | ||||
|         { | ||||
|             return concat(a, '/', detail::escape(b)); | ||||
|         }); | ||||
|         return concat('(', str, ") "); | ||||
| #else | ||||
|         static_cast<void>(leaf_element); | ||||
|         return ""; | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /// an exception object as storage for error messages | ||||
|     std::runtime_error m; | ||||
| }; | ||||
|  | ||||
| /// @brief exception indicating a parse error | ||||
| /// @sa https://json.nlohmann.me/api/basic_json/parse_error/ | ||||
| class parse_error : public exception | ||||
| { | ||||
|   public: | ||||
|     /*! | ||||
|     @brief create a parse error exception | ||||
|     @param[in] id_       the id of the exception | ||||
|     @param[in] pos       the position where the error occurred (or with | ||||
|                          chars_read_total=0 if the position cannot be | ||||
|                          determined) | ||||
|     @param[in] what_arg  the explanatory string | ||||
|     @return parse_error object | ||||
|     */ | ||||
|     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | ||||
|     static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) | ||||
|     { | ||||
|         const std::string w = concat(exception::name("parse_error", id_), "parse error", | ||||
|                                      position_string(pos), ": ", exception::diagnostics(context), what_arg); | ||||
|         return {id_, pos.chars_read_total, w.c_str()}; | ||||
|     } | ||||
|  | ||||
|     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | ||||
|     static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) | ||||
|     { | ||||
|         const std::string w = concat(exception::name("parse_error", id_), "parse error", | ||||
|                                      (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), | ||||
|                                      ": ", exception::diagnostics(context), what_arg); | ||||
|         return {id_, byte_, w.c_str()}; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief byte index of the parse error | ||||
|  | ||||
|     The byte index of the last read character in the input file. | ||||
|  | ||||
|     @note For an input with n bytes, 1 is the index of the first character and | ||||
|           n+1 is the index of the terminating null byte or the end of file. | ||||
|           This also holds true when reading a byte vector (CBOR or MessagePack). | ||||
|     */ | ||||
|     const std::size_t byte; | ||||
|  | ||||
|   private: | ||||
|     parse_error(int id_, std::size_t byte_, const char* what_arg) | ||||
|         : exception(id_, what_arg), byte(byte_) {} | ||||
|  | ||||
|     static std::string position_string(const position_t& pos) | ||||
|     { | ||||
|         return concat(" at line ", std::to_string(pos.lines_read + 1), | ||||
|                       ", column ", std::to_string(pos.chars_read_current_line)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /// @brief exception indicating errors with iterators | ||||
| /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ | ||||
| class invalid_iterator : public exception | ||||
| { | ||||
|   public: | ||||
|     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | ||||
|     static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) | ||||
|     { | ||||
|         const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); | ||||
|         return {id_, w.c_str()}; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     JSON_HEDLEY_NON_NULL(3) | ||||
|     invalid_iterator(int id_, const char* what_arg) | ||||
|         : exception(id_, what_arg) {} | ||||
| }; | ||||
|  | ||||
| /// @brief exception indicating executing a member function with a wrong type | ||||
| /// @sa https://json.nlohmann.me/api/basic_json/type_error/ | ||||
| class type_error : public exception | ||||
| { | ||||
|   public: | ||||
|     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | ||||
|     static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) | ||||
|     { | ||||
|         const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); | ||||
|         return {id_, w.c_str()}; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     JSON_HEDLEY_NON_NULL(3) | ||||
|     type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} | ||||
| }; | ||||
|  | ||||
| /// @brief exception indicating access out of the defined range | ||||
| /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ | ||||
| class out_of_range : public exception | ||||
| { | ||||
|   public: | ||||
|     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | ||||
|     static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) | ||||
|     { | ||||
|         const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); | ||||
|         return {id_, w.c_str()}; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     JSON_HEDLEY_NON_NULL(3) | ||||
|     out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} | ||||
| }; | ||||
|  | ||||
| /// @brief exception indicating other library errors | ||||
| /// @sa https://json.nlohmann.me/api/basic_json/other_error/ | ||||
| class other_error : public exception | ||||
| { | ||||
|   public: | ||||
|     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | ||||
|     static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) | ||||
|     { | ||||
|         const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); | ||||
|         return {id_, w.c_str()}; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     JSON_HEDLEY_NON_NULL(3) | ||||
|     other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
							
								
								
									
										129
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/hash.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/hash.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstdint> // uint8_t | ||||
| #include <cstddef> // size_t | ||||
| #include <functional> // hash | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| // boost::hash_combine | ||||
| inline std::size_t combine(std::size_t seed, std::size_t h) noexcept | ||||
| { | ||||
|     seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); | ||||
|     return seed; | ||||
| } | ||||
|  | ||||
| /*! | ||||
| @brief hash a JSON value | ||||
|  | ||||
| The hash function tries to rely on std::hash where possible. Furthermore, the | ||||
| type of the JSON value is taken into account to have different hash values for | ||||
| null, 0, 0U, and false, etc. | ||||
|  | ||||
| @tparam BasicJsonType basic_json specialization | ||||
| @param j JSON value to hash | ||||
| @return hash value of j | ||||
| */ | ||||
| template<typename BasicJsonType> | ||||
| std::size_t hash(const BasicJsonType& j) | ||||
| { | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|  | ||||
|     const auto type = static_cast<std::size_t>(j.type()); | ||||
|     switch (j.type()) | ||||
|     { | ||||
|         case BasicJsonType::value_t::null: | ||||
|         case BasicJsonType::value_t::discarded: | ||||
|         { | ||||
|             return combine(type, 0); | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::object: | ||||
|         { | ||||
|             auto seed = combine(type, j.size()); | ||||
|             for (const auto& element : j.items()) | ||||
|             { | ||||
|                 const auto h = std::hash<string_t> {}(element.key()); | ||||
|                 seed = combine(seed, h); | ||||
|                 seed = combine(seed, hash(element.value())); | ||||
|             } | ||||
|             return seed; | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::array: | ||||
|         { | ||||
|             auto seed = combine(type, j.size()); | ||||
|             for (const auto& element : j) | ||||
|             { | ||||
|                 seed = combine(seed, hash(element)); | ||||
|             } | ||||
|             return seed; | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::string: | ||||
|         { | ||||
|             const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>()); | ||||
|             return combine(type, h); | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::boolean: | ||||
|         { | ||||
|             const auto h = std::hash<bool> {}(j.template get<bool>()); | ||||
|             return combine(type, h); | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::number_integer: | ||||
|         { | ||||
|             const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>()); | ||||
|             return combine(type, h); | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::number_unsigned: | ||||
|         { | ||||
|             const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>()); | ||||
|             return combine(type, h); | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::number_float: | ||||
|         { | ||||
|             const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>()); | ||||
|             return combine(type, h); | ||||
|         } | ||||
|  | ||||
|         case BasicJsonType::value_t::binary: | ||||
|         { | ||||
|             auto seed = combine(type, j.get_binary().size()); | ||||
|             const auto h = std::hash<bool> {}(j.get_binary().has_subtype()); | ||||
|             seed = combine(seed, h); | ||||
|             seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype())); | ||||
|             for (const auto byte : j.get_binary()) | ||||
|             { | ||||
|                 seed = combine(seed, std::hash<std::uint8_t> {}(byte)); | ||||
|             } | ||||
|             return seed; | ||||
|         } | ||||
|  | ||||
|         default:                   // LCOV_EXCL_LINE | ||||
|             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | ||||
|             return 0;              // LCOV_EXCL_LINE | ||||
|     } | ||||
| } | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,491 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <array> // array | ||||
| #include <cstddef> // size_t | ||||
| #include <cstring> // strlen | ||||
| #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next | ||||
| #include <memory> // shared_ptr, make_shared, addressof | ||||
| #include <numeric> // accumulate | ||||
| #include <string> // string, char_traits | ||||
| #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer | ||||
| #include <utility> // pair, declval | ||||
|  | ||||
| #ifndef JSON_NO_IO | ||||
|     #include <cstdio>   // FILE * | ||||
|     #include <istream>  // istream | ||||
| #endif                  // JSON_NO_IO | ||||
|  | ||||
| #include <nlohmann/detail/iterators/iterator_traits.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /// the supported input formats | ||||
| enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; | ||||
|  | ||||
| //////////////////// | ||||
| // input adapters // | ||||
| //////////////////// | ||||
|  | ||||
| #ifndef JSON_NO_IO | ||||
| /*! | ||||
| Input adapter for stdio file access. This adapter read only 1 byte and do not use any | ||||
|  buffer. This adapter is a very low level adapter. | ||||
| */ | ||||
| class file_input_adapter | ||||
| { | ||||
|   public: | ||||
|     using char_type = char; | ||||
|  | ||||
|     JSON_HEDLEY_NON_NULL(2) | ||||
|     explicit file_input_adapter(std::FILE* f) noexcept | ||||
|         : m_file(f) | ||||
|     { | ||||
|         JSON_ASSERT(m_file != nullptr); | ||||
|     } | ||||
|  | ||||
|     // make class move-only | ||||
|     file_input_adapter(const file_input_adapter&) = delete; | ||||
|     file_input_adapter(file_input_adapter&&) noexcept = default; | ||||
|     file_input_adapter& operator=(const file_input_adapter&) = delete; | ||||
|     file_input_adapter& operator=(file_input_adapter&&) = delete; | ||||
|     ~file_input_adapter() = default; | ||||
|  | ||||
|     std::char_traits<char>::int_type get_character() noexcept | ||||
|     { | ||||
|         return std::fgetc(m_file); | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /// the file pointer to read from | ||||
|     std::FILE* m_file; | ||||
| }; | ||||
|  | ||||
| /*! | ||||
| Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at | ||||
| beginning of input. Does not support changing the underlying std::streambuf | ||||
| in mid-input. Maintains underlying std::istream and std::streambuf to support | ||||
| subsequent use of standard std::istream operations to process any input | ||||
| characters following those used in parsing the JSON input.  Clears the | ||||
| std::istream flags; any input errors (e.g., EOF) will be detected by the first | ||||
| subsequent call for input from the std::istream. | ||||
| */ | ||||
| class input_stream_adapter | ||||
| { | ||||
|   public: | ||||
|     using char_type = char; | ||||
|  | ||||
|     ~input_stream_adapter() | ||||
|     { | ||||
|         // clear stream flags; we use underlying streambuf I/O, do not | ||||
|         // maintain ifstream flags, except eof | ||||
|         if (is != nullptr) | ||||
|         { | ||||
|             is->clear(is->rdstate() & std::ios::eofbit); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     explicit input_stream_adapter(std::istream& i) | ||||
|         : is(&i), sb(i.rdbuf()) | ||||
|     {} | ||||
|  | ||||
|     // delete because of pointer members | ||||
|     input_stream_adapter(const input_stream_adapter&) = delete; | ||||
|     input_stream_adapter& operator=(input_stream_adapter&) = delete; | ||||
|     input_stream_adapter& operator=(input_stream_adapter&&) = delete; | ||||
|  | ||||
|     input_stream_adapter(input_stream_adapter&& rhs) noexcept | ||||
|         : is(rhs.is), sb(rhs.sb) | ||||
|     { | ||||
|         rhs.is = nullptr; | ||||
|         rhs.sb = nullptr; | ||||
|     } | ||||
|  | ||||
|     // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to | ||||
|     // ensure that std::char_traits<char>::eof() and the character 0xFF do not | ||||
|     // end up as the same value, e.g. 0xFFFFFFFF. | ||||
|     std::char_traits<char>::int_type get_character() | ||||
|     { | ||||
|         auto res = sb->sbumpc(); | ||||
|         // set eof manually, as we don't use the istream interface. | ||||
|         if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) | ||||
|         { | ||||
|             is->clear(is->rdstate() | std::ios::eofbit); | ||||
|         } | ||||
|         return res; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /// the associated input stream | ||||
|     std::istream* is = nullptr; | ||||
|     std::streambuf* sb = nullptr; | ||||
| }; | ||||
| #endif  // JSON_NO_IO | ||||
|  | ||||
| // General-purpose iterator-based adapter. It might not be as fast as | ||||
| // theoretically possible for some containers, but it is extremely versatile. | ||||
| template<typename IteratorType> | ||||
| class iterator_input_adapter | ||||
| { | ||||
|   public: | ||||
|     using char_type = typename std::iterator_traits<IteratorType>::value_type; | ||||
|  | ||||
|     iterator_input_adapter(IteratorType first, IteratorType last) | ||||
|         : current(std::move(first)), end(std::move(last)) | ||||
|     {} | ||||
|  | ||||
|     typename std::char_traits<char_type>::int_type get_character() | ||||
|     { | ||||
|         if (JSON_HEDLEY_LIKELY(current != end)) | ||||
|         { | ||||
|             auto result = std::char_traits<char_type>::to_int_type(*current); | ||||
|             std::advance(current, 1); | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         return std::char_traits<char_type>::eof(); | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     IteratorType current; | ||||
|     IteratorType end; | ||||
|  | ||||
|     template<typename BaseInputAdapter, size_t T> | ||||
|     friend struct wide_string_input_helper; | ||||
|  | ||||
|     bool empty() const | ||||
|     { | ||||
|         return current == end; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename BaseInputAdapter, size_t T> | ||||
| struct wide_string_input_helper; | ||||
|  | ||||
| template<typename BaseInputAdapter> | ||||
| struct wide_string_input_helper<BaseInputAdapter, 4> | ||||
| { | ||||
|     // UTF-32 | ||||
|     static void fill_buffer(BaseInputAdapter& input, | ||||
|                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, | ||||
|                             size_t& utf8_bytes_index, | ||||
|                             size_t& utf8_bytes_filled) | ||||
|     { | ||||
|         utf8_bytes_index = 0; | ||||
|  | ||||
|         if (JSON_HEDLEY_UNLIKELY(input.empty())) | ||||
|         { | ||||
|             utf8_bytes[0] = std::char_traits<char>::eof(); | ||||
|             utf8_bytes_filled = 1; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // get the current character | ||||
|             const auto wc = input.get_character(); | ||||
|  | ||||
|             // UTF-32 to UTF-8 encoding | ||||
|             if (wc < 0x80) | ||||
|             { | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | ||||
|                 utf8_bytes_filled = 1; | ||||
|             } | ||||
|             else if (wc <= 0x7FF) | ||||
|             { | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu)); | ||||
|                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | ||||
|                 utf8_bytes_filled = 2; | ||||
|             } | ||||
|             else if (wc <= 0xFFFF) | ||||
|             { | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu)); | ||||
|                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); | ||||
|                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | ||||
|                 utf8_bytes_filled = 3; | ||||
|             } | ||||
|             else if (wc <= 0x10FFFF) | ||||
|             { | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u)); | ||||
|                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu)); | ||||
|                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); | ||||
|                 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | ||||
|                 utf8_bytes_filled = 4; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // unknown character | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | ||||
|                 utf8_bytes_filled = 1; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename BaseInputAdapter> | ||||
| struct wide_string_input_helper<BaseInputAdapter, 2> | ||||
| { | ||||
|     // UTF-16 | ||||
|     static void fill_buffer(BaseInputAdapter& input, | ||||
|                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, | ||||
|                             size_t& utf8_bytes_index, | ||||
|                             size_t& utf8_bytes_filled) | ||||
|     { | ||||
|         utf8_bytes_index = 0; | ||||
|  | ||||
|         if (JSON_HEDLEY_UNLIKELY(input.empty())) | ||||
|         { | ||||
|             utf8_bytes[0] = std::char_traits<char>::eof(); | ||||
|             utf8_bytes_filled = 1; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // get the current character | ||||
|             const auto wc = input.get_character(); | ||||
|  | ||||
|             // UTF-16 to UTF-8 encoding | ||||
|             if (wc < 0x80) | ||||
|             { | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | ||||
|                 utf8_bytes_filled = 1; | ||||
|             } | ||||
|             else if (wc <= 0x7FF) | ||||
|             { | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u))); | ||||
|                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | ||||
|                 utf8_bytes_filled = 2; | ||||
|             } | ||||
|             else if (0xD800 > wc || wc >= 0xE000) | ||||
|             { | ||||
|                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u))); | ||||
|                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); | ||||
|                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | ||||
|                 utf8_bytes_filled = 3; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (JSON_HEDLEY_UNLIKELY(!input.empty())) | ||||
|                 { | ||||
|                     const auto wc2 = static_cast<unsigned int>(input.get_character()); | ||||
|                     const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); | ||||
|                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u)); | ||||
|                     utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); | ||||
|                     utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); | ||||
|                     utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu)); | ||||
|                     utf8_bytes_filled = 4; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | ||||
|                     utf8_bytes_filled = 1; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // Wraps another input adapter to convert wide character types into individual bytes. | ||||
| template<typename BaseInputAdapter, typename WideCharType> | ||||
| class wide_string_input_adapter | ||||
| { | ||||
|   public: | ||||
|     using char_type = char; | ||||
|  | ||||
|     wide_string_input_adapter(BaseInputAdapter base) | ||||
|         : base_adapter(base) {} | ||||
|  | ||||
|     typename std::char_traits<char>::int_type get_character() noexcept | ||||
|     { | ||||
|         // check if buffer needs to be filled | ||||
|         if (utf8_bytes_index == utf8_bytes_filled) | ||||
|         { | ||||
|             fill_buffer<sizeof(WideCharType)>(); | ||||
|  | ||||
|             JSON_ASSERT(utf8_bytes_filled > 0); | ||||
|             JSON_ASSERT(utf8_bytes_index == 0); | ||||
|         } | ||||
|  | ||||
|         // use buffer | ||||
|         JSON_ASSERT(utf8_bytes_filled > 0); | ||||
|         JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); | ||||
|         return utf8_bytes[utf8_bytes_index++]; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     BaseInputAdapter base_adapter; | ||||
|  | ||||
|     template<size_t T> | ||||
|     void fill_buffer() | ||||
|     { | ||||
|         wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); | ||||
|     } | ||||
|  | ||||
|     /// a buffer for UTF-8 bytes | ||||
|     std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; | ||||
|  | ||||
|     /// index to the utf8_codes array for the next valid byte | ||||
|     std::size_t utf8_bytes_index = 0; | ||||
|     /// number of valid bytes in the utf8_codes array | ||||
|     std::size_t utf8_bytes_filled = 0; | ||||
| }; | ||||
|  | ||||
| template<typename IteratorType, typename Enable = void> | ||||
| struct iterator_input_adapter_factory | ||||
| { | ||||
|     using iterator_type = IteratorType; | ||||
|     using char_type = typename std::iterator_traits<iterator_type>::value_type; | ||||
|     using adapter_type = iterator_input_adapter<iterator_type>; | ||||
|  | ||||
|     static adapter_type create(IteratorType first, IteratorType last) | ||||
|     { | ||||
|         return adapter_type(std::move(first), std::move(last)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct is_iterator_of_multibyte | ||||
| { | ||||
|     using value_type = typename std::iterator_traits<T>::value_type; | ||||
|     enum | ||||
|     { | ||||
|         value = sizeof(value_type) > 1 | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template<typename IteratorType> | ||||
| struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> | ||||
| { | ||||
|     using iterator_type = IteratorType; | ||||
|     using char_type = typename std::iterator_traits<iterator_type>::value_type; | ||||
|     using base_adapter_type = iterator_input_adapter<iterator_type>; | ||||
|     using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>; | ||||
|  | ||||
|     static adapter_type create(IteratorType first, IteratorType last) | ||||
|     { | ||||
|         return adapter_type(base_adapter_type(std::move(first), std::move(last))); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // General purpose iterator-based input | ||||
| template<typename IteratorType> | ||||
| typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) | ||||
| { | ||||
|     using factory_type = iterator_input_adapter_factory<IteratorType>; | ||||
|     return factory_type::create(first, last); | ||||
| } | ||||
|  | ||||
| // Convenience shorthand from container to iterator | ||||
| // Enables ADL on begin(container) and end(container) | ||||
| // Encloses the using declarations in namespace for not to leak them to outside scope | ||||
|  | ||||
| namespace container_input_adapter_factory_impl | ||||
| { | ||||
|  | ||||
| using std::begin; | ||||
| using std::end; | ||||
|  | ||||
| template<typename ContainerType, typename Enable = void> | ||||
| struct container_input_adapter_factory {}; | ||||
|  | ||||
| template<typename ContainerType> | ||||
| struct container_input_adapter_factory< ContainerType, | ||||
|        void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> | ||||
|        { | ||||
|            using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); | ||||
|  | ||||
|            static adapter_type create(const ContainerType& container) | ||||
| { | ||||
|     return input_adapter(begin(container), end(container)); | ||||
| } | ||||
|        }; | ||||
|  | ||||
| }  // namespace container_input_adapter_factory_impl | ||||
|  | ||||
| template<typename ContainerType> | ||||
| typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container) | ||||
| { | ||||
|     return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); | ||||
| } | ||||
|  | ||||
| #ifndef JSON_NO_IO | ||||
| // Special cases with fast paths | ||||
| inline file_input_adapter input_adapter(std::FILE* file) | ||||
| { | ||||
|     return file_input_adapter(file); | ||||
| } | ||||
|  | ||||
| inline input_stream_adapter input_adapter(std::istream& stream) | ||||
| { | ||||
|     return input_stream_adapter(stream); | ||||
| } | ||||
|  | ||||
| inline input_stream_adapter input_adapter(std::istream&& stream) | ||||
| { | ||||
|     return input_stream_adapter(stream); | ||||
| } | ||||
| #endif  // JSON_NO_IO | ||||
|  | ||||
| using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>())); | ||||
|  | ||||
| // Null-delimited strings, and the like. | ||||
| template < typename CharT, | ||||
|            typename std::enable_if < | ||||
|                std::is_pointer<CharT>::value&& | ||||
|                !std::is_array<CharT>::value&& | ||||
|                std::is_integral<typename std::remove_pointer<CharT>::type>::value&& | ||||
|                sizeof(typename std::remove_pointer<CharT>::type) == 1, | ||||
|                int >::type = 0 > | ||||
| contiguous_bytes_input_adapter input_adapter(CharT b) | ||||
| { | ||||
|     auto length = std::strlen(reinterpret_cast<const char*>(b)); | ||||
|     const auto* ptr = reinterpret_cast<const char*>(b); | ||||
|     return input_adapter(ptr, ptr + length); | ||||
| } | ||||
|  | ||||
| template<typename T, std::size_t N> | ||||
| auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | ||||
| { | ||||
|     return input_adapter(array, array + N); | ||||
| } | ||||
|  | ||||
| // This class only handles inputs of input_buffer_adapter type. | ||||
| // It's required so that expressions like {ptr, len} can be implicitly cast | ||||
| // to the correct adapter. | ||||
| class span_input_adapter | ||||
| { | ||||
|   public: | ||||
|     template < typename CharT, | ||||
|                typename std::enable_if < | ||||
|                    std::is_pointer<CharT>::value&& | ||||
|                    std::is_integral<typename std::remove_pointer<CharT>::type>::value&& | ||||
|                    sizeof(typename std::remove_pointer<CharT>::type) == 1, | ||||
|                    int >::type = 0 > | ||||
|     span_input_adapter(CharT b, std::size_t l) | ||||
|         : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {} | ||||
|  | ||||
|     template<class IteratorType, | ||||
|              typename std::enable_if< | ||||
|                  std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, | ||||
|                  int>::type = 0> | ||||
|     span_input_adapter(IteratorType first, IteratorType last) | ||||
|         : ia(input_adapter(first, last)) {} | ||||
|  | ||||
|     contiguous_bytes_input_adapter&& get() | ||||
|     { | ||||
|         return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     contiguous_bytes_input_adapter ia; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,727 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstddef> | ||||
| #include <string> // string | ||||
| #include <utility> // move | ||||
| #include <vector> // vector | ||||
|  | ||||
| #include <nlohmann/detail/exceptions.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/string_concat.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
|  | ||||
| /*! | ||||
| @brief SAX interface | ||||
|  | ||||
| This class describes the SAX interface used by @ref nlohmann::json::sax_parse. | ||||
| Each function is called in different situations while the input is parsed. The | ||||
| boolean return value informs the parser whether to continue processing the | ||||
| input. | ||||
| */ | ||||
| template<typename BasicJsonType> | ||||
| struct json_sax | ||||
| { | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using binary_t = typename BasicJsonType::binary_t; | ||||
|  | ||||
|     /*! | ||||
|     @brief a null value was read | ||||
|     @return whether parsing should proceed | ||||
|     */ | ||||
|     virtual bool null() = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief a boolean value was read | ||||
|     @param[in] val  boolean value | ||||
|     @return whether parsing should proceed | ||||
|     */ | ||||
|     virtual bool boolean(bool val) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief an integer number was read | ||||
|     @param[in] val  integer value | ||||
|     @return whether parsing should proceed | ||||
|     */ | ||||
|     virtual bool number_integer(number_integer_t val) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief an unsigned integer number was read | ||||
|     @param[in] val  unsigned integer value | ||||
|     @return whether parsing should proceed | ||||
|     */ | ||||
|     virtual bool number_unsigned(number_unsigned_t val) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief a floating-point number was read | ||||
|     @param[in] val  floating-point value | ||||
|     @param[in] s    raw token value | ||||
|     @return whether parsing should proceed | ||||
|     */ | ||||
|     virtual bool number_float(number_float_t val, const string_t& s) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief a string value was read | ||||
|     @param[in] val  string value | ||||
|     @return whether parsing should proceed | ||||
|     @note It is safe to move the passed string value. | ||||
|     */ | ||||
|     virtual bool string(string_t& val) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief a binary value was read | ||||
|     @param[in] val  binary value | ||||
|     @return whether parsing should proceed | ||||
|     @note It is safe to move the passed binary value. | ||||
|     */ | ||||
|     virtual bool binary(binary_t& val) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief the beginning of an object was read | ||||
|     @param[in] elements  number of object elements or -1 if unknown | ||||
|     @return whether parsing should proceed | ||||
|     @note binary formats may report the number of elements | ||||
|     */ | ||||
|     virtual bool start_object(std::size_t elements) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief an object key was read | ||||
|     @param[in] val  object key | ||||
|     @return whether parsing should proceed | ||||
|     @note It is safe to move the passed string. | ||||
|     */ | ||||
|     virtual bool key(string_t& val) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief the end of an object was read | ||||
|     @return whether parsing should proceed | ||||
|     */ | ||||
|     virtual bool end_object() = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief the beginning of an array was read | ||||
|     @param[in] elements  number of array elements or -1 if unknown | ||||
|     @return whether parsing should proceed | ||||
|     @note binary formats may report the number of elements | ||||
|     */ | ||||
|     virtual bool start_array(std::size_t elements) = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief the end of an array was read | ||||
|     @return whether parsing should proceed | ||||
|     */ | ||||
|     virtual bool end_array() = 0; | ||||
|  | ||||
|     /*! | ||||
|     @brief a parse error occurred | ||||
|     @param[in] position    the position in the input where the error occurs | ||||
|     @param[in] last_token  the last read token | ||||
|     @param[in] ex          an exception object describing the error | ||||
|     @return whether parsing should proceed (must return false) | ||||
|     */ | ||||
|     virtual bool parse_error(std::size_t position, | ||||
|                              const std::string& last_token, | ||||
|                              const detail::exception& ex) = 0; | ||||
|  | ||||
|     json_sax() = default; | ||||
|     json_sax(const json_sax&) = default; | ||||
|     json_sax(json_sax&&) noexcept = default; | ||||
|     json_sax& operator=(const json_sax&) = default; | ||||
|     json_sax& operator=(json_sax&&) noexcept = default; | ||||
|     virtual ~json_sax() = default; | ||||
| }; | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
| /*! | ||||
| @brief SAX implementation to create a JSON value from SAX events | ||||
|  | ||||
| This class implements the @ref json_sax interface and processes the SAX events | ||||
| to create a JSON value which makes it basically a DOM parser. The structure or | ||||
| hierarchy of the JSON value is managed by the stack `ref_stack` which contains | ||||
| a pointer to the respective array or object for each recursion depth. | ||||
|  | ||||
| After successful parsing, the value that is passed by reference to the | ||||
| constructor contains the parsed value. | ||||
|  | ||||
| @tparam BasicJsonType  the JSON type | ||||
| */ | ||||
| template<typename BasicJsonType> | ||||
| class json_sax_dom_parser | ||||
| { | ||||
|   public: | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using binary_t = typename BasicJsonType::binary_t; | ||||
|  | ||||
|     /*! | ||||
|     @param[in,out] r  reference to a JSON value that is manipulated while | ||||
|                        parsing | ||||
|     @param[in] allow_exceptions_  whether parse errors yield exceptions | ||||
|     */ | ||||
|     explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) | ||||
|         : root(r), allow_exceptions(allow_exceptions_) | ||||
|     {} | ||||
|  | ||||
|     // make class move-only | ||||
|     json_sax_dom_parser(const json_sax_dom_parser&) = delete; | ||||
|     json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | ||||
|     json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; | ||||
|     json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | ||||
|     ~json_sax_dom_parser() = default; | ||||
|  | ||||
|     bool null() | ||||
|     { | ||||
|         handle_value(nullptr); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool boolean(bool val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_integer(number_integer_t val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_unsigned(number_unsigned_t val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_float(number_float_t val, const string_t& /*unused*/) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool string(string_t& val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool binary(binary_t& val) | ||||
|     { | ||||
|         handle_value(std::move(val)); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool start_object(std::size_t len) | ||||
|     { | ||||
|         ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); | ||||
|  | ||||
|         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | ||||
|         { | ||||
|             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool key(string_t& val) | ||||
|     { | ||||
|         JSON_ASSERT(!ref_stack.empty()); | ||||
|         JSON_ASSERT(ref_stack.back()->is_object()); | ||||
|  | ||||
|         // add null at given key and store the reference for later | ||||
|         object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool end_object() | ||||
|     { | ||||
|         JSON_ASSERT(!ref_stack.empty()); | ||||
|         JSON_ASSERT(ref_stack.back()->is_object()); | ||||
|  | ||||
|         ref_stack.back()->set_parents(); | ||||
|         ref_stack.pop_back(); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool start_array(std::size_t len) | ||||
|     { | ||||
|         ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); | ||||
|  | ||||
|         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | ||||
|         { | ||||
|             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool end_array() | ||||
|     { | ||||
|         JSON_ASSERT(!ref_stack.empty()); | ||||
|         JSON_ASSERT(ref_stack.back()->is_array()); | ||||
|  | ||||
|         ref_stack.back()->set_parents(); | ||||
|         ref_stack.pop_back(); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     template<class Exception> | ||||
|     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, | ||||
|                      const Exception& ex) | ||||
|     { | ||||
|         errored = true; | ||||
|         static_cast<void>(ex); | ||||
|         if (allow_exceptions) | ||||
|         { | ||||
|             JSON_THROW(ex); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     constexpr bool is_errored() const | ||||
|     { | ||||
|         return errored; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /*! | ||||
|     @invariant If the ref stack is empty, then the passed value will be the new | ||||
|                root. | ||||
|     @invariant If the ref stack contains a value, then it is an array or an | ||||
|                object to which we can add elements | ||||
|     */ | ||||
|     template<typename Value> | ||||
|     JSON_HEDLEY_RETURNS_NON_NULL | ||||
|     BasicJsonType* handle_value(Value&& v) | ||||
|     { | ||||
|         if (ref_stack.empty()) | ||||
|         { | ||||
|             root = BasicJsonType(std::forward<Value>(v)); | ||||
|             return &root; | ||||
|         } | ||||
|  | ||||
|         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); | ||||
|  | ||||
|         if (ref_stack.back()->is_array()) | ||||
|         { | ||||
|             ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v)); | ||||
|             return &(ref_stack.back()->m_data.m_value.array->back()); | ||||
|         } | ||||
|  | ||||
|         JSON_ASSERT(ref_stack.back()->is_object()); | ||||
|         JSON_ASSERT(object_element); | ||||
|         *object_element = BasicJsonType(std::forward<Value>(v)); | ||||
|         return object_element; | ||||
|     } | ||||
|  | ||||
|     /// the parsed JSON value | ||||
|     BasicJsonType& root; | ||||
|     /// stack to model hierarchy of values | ||||
|     std::vector<BasicJsonType*> ref_stack {}; | ||||
|     /// helper to hold the reference for the next object element | ||||
|     BasicJsonType* object_element = nullptr; | ||||
|     /// whether a syntax error occurred | ||||
|     bool errored = false; | ||||
|     /// whether to throw exceptions in case of errors | ||||
|     const bool allow_exceptions = true; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| class json_sax_dom_callback_parser | ||||
| { | ||||
|   public: | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using binary_t = typename BasicJsonType::binary_t; | ||||
|     using parser_callback_t = typename BasicJsonType::parser_callback_t; | ||||
|     using parse_event_t = typename BasicJsonType::parse_event_t; | ||||
|  | ||||
|     json_sax_dom_callback_parser(BasicJsonType& r, | ||||
|                                  const parser_callback_t cb, | ||||
|                                  const bool allow_exceptions_ = true) | ||||
|         : root(r), callback(cb), allow_exceptions(allow_exceptions_) | ||||
|     { | ||||
|         keep_stack.push_back(true); | ||||
|     } | ||||
|  | ||||
|     // make class move-only | ||||
|     json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; | ||||
|     json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | ||||
|     json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; | ||||
|     json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | ||||
|     ~json_sax_dom_callback_parser() = default; | ||||
|  | ||||
|     bool null() | ||||
|     { | ||||
|         handle_value(nullptr); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool boolean(bool val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_integer(number_integer_t val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_unsigned(number_unsigned_t val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_float(number_float_t val, const string_t& /*unused*/) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool string(string_t& val) | ||||
|     { | ||||
|         handle_value(val); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool binary(binary_t& val) | ||||
|     { | ||||
|         handle_value(std::move(val)); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool start_object(std::size_t len) | ||||
|     { | ||||
|         // check callback for object start | ||||
|         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded); | ||||
|         keep_stack.push_back(keep); | ||||
|  | ||||
|         auto val = handle_value(BasicJsonType::value_t::object, true); | ||||
|         ref_stack.push_back(val.second); | ||||
|  | ||||
|         // check object limit | ||||
|         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | ||||
|         { | ||||
|             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool key(string_t& val) | ||||
|     { | ||||
|         BasicJsonType k = BasicJsonType(val); | ||||
|  | ||||
|         // check callback for key | ||||
|         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k); | ||||
|         key_keep_stack.push_back(keep); | ||||
|  | ||||
|         // add discarded value at given key and store the reference for later | ||||
|         if (keep && ref_stack.back()) | ||||
|         { | ||||
|             object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool end_object() | ||||
|     { | ||||
|         if (ref_stack.back()) | ||||
|         { | ||||
|             if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) | ||||
|             { | ||||
|                 // discard object | ||||
|                 *ref_stack.back() = discarded; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ref_stack.back()->set_parents(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         JSON_ASSERT(!ref_stack.empty()); | ||||
|         JSON_ASSERT(!keep_stack.empty()); | ||||
|         ref_stack.pop_back(); | ||||
|         keep_stack.pop_back(); | ||||
|  | ||||
|         if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) | ||||
|         { | ||||
|             // remove discarded value | ||||
|             for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) | ||||
|             { | ||||
|                 if (it->is_discarded()) | ||||
|                 { | ||||
|                     ref_stack.back()->erase(it); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool start_array(std::size_t len) | ||||
|     { | ||||
|         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded); | ||||
|         keep_stack.push_back(keep); | ||||
|  | ||||
|         auto val = handle_value(BasicJsonType::value_t::array, true); | ||||
|         ref_stack.push_back(val.second); | ||||
|  | ||||
|         // check array limit | ||||
|         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | ||||
|         { | ||||
|             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool end_array() | ||||
|     { | ||||
|         bool keep = true; | ||||
|  | ||||
|         if (ref_stack.back()) | ||||
|         { | ||||
|             keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); | ||||
|             if (keep) | ||||
|             { | ||||
|                 ref_stack.back()->set_parents(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // discard array | ||||
|                 *ref_stack.back() = discarded; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         JSON_ASSERT(!ref_stack.empty()); | ||||
|         JSON_ASSERT(!keep_stack.empty()); | ||||
|         ref_stack.pop_back(); | ||||
|         keep_stack.pop_back(); | ||||
|  | ||||
|         // remove discarded value | ||||
|         if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) | ||||
|         { | ||||
|             ref_stack.back()->m_data.m_value.array->pop_back(); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     template<class Exception> | ||||
|     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, | ||||
|                      const Exception& ex) | ||||
|     { | ||||
|         errored = true; | ||||
|         static_cast<void>(ex); | ||||
|         if (allow_exceptions) | ||||
|         { | ||||
|             JSON_THROW(ex); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     constexpr bool is_errored() const | ||||
|     { | ||||
|         return errored; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /*! | ||||
|     @param[in] v  value to add to the JSON value we build during parsing | ||||
|     @param[in] skip_callback  whether we should skip calling the callback | ||||
|                function; this is required after start_array() and | ||||
|                start_object() SAX events, because otherwise we would call the | ||||
|                callback function with an empty array or object, respectively. | ||||
|  | ||||
|     @invariant If the ref stack is empty, then the passed value will be the new | ||||
|                root. | ||||
|     @invariant If the ref stack contains a value, then it is an array or an | ||||
|                object to which we can add elements | ||||
|  | ||||
|     @return pair of boolean (whether value should be kept) and pointer (to the | ||||
|             passed value in the ref_stack hierarchy; nullptr if not kept) | ||||
|     */ | ||||
|     template<typename Value> | ||||
|     std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) | ||||
|     { | ||||
|         JSON_ASSERT(!keep_stack.empty()); | ||||
|  | ||||
|         // do not handle this value if we know it would be added to a discarded | ||||
|         // container | ||||
|         if (!keep_stack.back()) | ||||
|         { | ||||
|             return {false, nullptr}; | ||||
|         } | ||||
|  | ||||
|         // create value | ||||
|         auto value = BasicJsonType(std::forward<Value>(v)); | ||||
|  | ||||
|         // check callback | ||||
|         const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); | ||||
|  | ||||
|         // do not handle this value if we just learnt it shall be discarded | ||||
|         if (!keep) | ||||
|         { | ||||
|             return {false, nullptr}; | ||||
|         } | ||||
|  | ||||
|         if (ref_stack.empty()) | ||||
|         { | ||||
|             root = std::move(value); | ||||
|             return {true, & root}; | ||||
|         } | ||||
|  | ||||
|         // skip this value if we already decided to skip the parent | ||||
|         // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) | ||||
|         if (!ref_stack.back()) | ||||
|         { | ||||
|             return {false, nullptr}; | ||||
|         } | ||||
|  | ||||
|         // we now only expect arrays and objects | ||||
|         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); | ||||
|  | ||||
|         // array | ||||
|         if (ref_stack.back()->is_array()) | ||||
|         { | ||||
|             ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); | ||||
|             return {true, & (ref_stack.back()->m_data.m_value.array->back())}; | ||||
|         } | ||||
|  | ||||
|         // object | ||||
|         JSON_ASSERT(ref_stack.back()->is_object()); | ||||
|         // check if we should store an element for the current key | ||||
|         JSON_ASSERT(!key_keep_stack.empty()); | ||||
|         const bool store_element = key_keep_stack.back(); | ||||
|         key_keep_stack.pop_back(); | ||||
|  | ||||
|         if (!store_element) | ||||
|         { | ||||
|             return {false, nullptr}; | ||||
|         } | ||||
|  | ||||
|         JSON_ASSERT(object_element); | ||||
|         *object_element = std::move(value); | ||||
|         return {true, object_element}; | ||||
|     } | ||||
|  | ||||
|     /// the parsed JSON value | ||||
|     BasicJsonType& root; | ||||
|     /// stack to model hierarchy of values | ||||
|     std::vector<BasicJsonType*> ref_stack {}; | ||||
|     /// stack to manage which values to keep | ||||
|     std::vector<bool> keep_stack {}; | ||||
|     /// stack to manage which object keys to keep | ||||
|     std::vector<bool> key_keep_stack {}; | ||||
|     /// helper to hold the reference for the next object element | ||||
|     BasicJsonType* object_element = nullptr; | ||||
|     /// whether a syntax error occurred | ||||
|     bool errored = false; | ||||
|     /// callback function | ||||
|     const parser_callback_t callback = nullptr; | ||||
|     /// whether to throw exceptions in case of errors | ||||
|     const bool allow_exceptions = true; | ||||
|     /// a discarded value for the callback | ||||
|     BasicJsonType discarded = BasicJsonType::value_t::discarded; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| class json_sax_acceptor | ||||
| { | ||||
|   public: | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using binary_t = typename BasicJsonType::binary_t; | ||||
|  | ||||
|     bool null() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool boolean(bool /*unused*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_integer(number_integer_t /*unused*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_unsigned(number_unsigned_t /*unused*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool string(string_t& /*unused*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool binary(binary_t& /*unused*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool key(string_t& /*unused*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool end_object() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool end_array() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
							
								
								
									
										1632
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/input/lexer.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1632
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/input/lexer.hpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,519 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cmath> // isfinite | ||||
| #include <cstdint> // uint8_t | ||||
| #include <functional> // function | ||||
| #include <string> // string | ||||
| #include <utility> // move | ||||
| #include <vector> // vector | ||||
|  | ||||
| #include <nlohmann/detail/exceptions.hpp> | ||||
| #include <nlohmann/detail/input/input_adapters.hpp> | ||||
| #include <nlohmann/detail/input/json_sax.hpp> | ||||
| #include <nlohmann/detail/input/lexer.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/meta/is_sax.hpp> | ||||
| #include <nlohmann/detail/string_concat.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
| //////////// | ||||
| // parser // | ||||
| //////////// | ||||
|  | ||||
| enum class parse_event_t : std::uint8_t | ||||
| { | ||||
|     /// the parser read `{` and started to process a JSON object | ||||
|     object_start, | ||||
|     /// the parser read `}` and finished processing a JSON object | ||||
|     object_end, | ||||
|     /// the parser read `[` and started to process a JSON array | ||||
|     array_start, | ||||
|     /// the parser read `]` and finished processing a JSON array | ||||
|     array_end, | ||||
|     /// the parser read a key of a value in an object | ||||
|     key, | ||||
|     /// the parser finished reading a JSON value | ||||
|     value | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| using parser_callback_t = | ||||
|     std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; | ||||
|  | ||||
| /*! | ||||
| @brief syntax analysis | ||||
|  | ||||
| This class implements a recursive descent parser. | ||||
| */ | ||||
| template<typename BasicJsonType, typename InputAdapterType> | ||||
| class parser | ||||
| { | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using lexer_t = lexer<BasicJsonType, InputAdapterType>; | ||||
|     using token_type = typename lexer_t::token_type; | ||||
|  | ||||
|   public: | ||||
|     /// a parser reading from an input adapter | ||||
|     explicit parser(InputAdapterType&& adapter, | ||||
|                     const parser_callback_t<BasicJsonType> cb = nullptr, | ||||
|                     const bool allow_exceptions_ = true, | ||||
|                     const bool skip_comments = false) | ||||
|         : callback(cb) | ||||
|         , m_lexer(std::move(adapter), skip_comments) | ||||
|         , allow_exceptions(allow_exceptions_) | ||||
|     { | ||||
|         // read first token | ||||
|         get_token(); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief public parser interface | ||||
|  | ||||
|     @param[in] strict      whether to expect the last token to be EOF | ||||
|     @param[in,out] result  parsed JSON value | ||||
|  | ||||
|     @throw parse_error.101 in case of an unexpected token | ||||
|     @throw parse_error.102 if to_unicode fails or surrogate error | ||||
|     @throw parse_error.103 if to_unicode fails | ||||
|     */ | ||||
|     void parse(const bool strict, BasicJsonType& result) | ||||
|     { | ||||
|         if (callback) | ||||
|         { | ||||
|             json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); | ||||
|             sax_parse_internal(&sdp); | ||||
|  | ||||
|             // in strict mode, input must be completely read | ||||
|             if (strict && (get_token() != token_type::end_of_input)) | ||||
|             { | ||||
|                 sdp.parse_error(m_lexer.get_position(), | ||||
|                                 m_lexer.get_token_string(), | ||||
|                                 parse_error::create(101, m_lexer.get_position(), | ||||
|                                                     exception_message(token_type::end_of_input, "value"), nullptr)); | ||||
|             } | ||||
|  | ||||
|             // in case of an error, return discarded value | ||||
|             if (sdp.is_errored()) | ||||
|             { | ||||
|                 result = value_t::discarded; | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // set top-level value to null if it was discarded by the callback | ||||
|             // function | ||||
|             if (result.is_discarded()) | ||||
|             { | ||||
|                 result = nullptr; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); | ||||
|             sax_parse_internal(&sdp); | ||||
|  | ||||
|             // in strict mode, input must be completely read | ||||
|             if (strict && (get_token() != token_type::end_of_input)) | ||||
|             { | ||||
|                 sdp.parse_error(m_lexer.get_position(), | ||||
|                                 m_lexer.get_token_string(), | ||||
|                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); | ||||
|             } | ||||
|  | ||||
|             // in case of an error, return discarded value | ||||
|             if (sdp.is_errored()) | ||||
|             { | ||||
|                 result = value_t::discarded; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         result.assert_invariant(); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief public accept interface | ||||
|  | ||||
|     @param[in] strict  whether to expect the last token to be EOF | ||||
|     @return whether the input is a proper JSON text | ||||
|     */ | ||||
|     bool accept(const bool strict = true) | ||||
|     { | ||||
|         json_sax_acceptor<BasicJsonType> sax_acceptor; | ||||
|         return sax_parse(&sax_acceptor, strict); | ||||
|     } | ||||
|  | ||||
|     template<typename SAX> | ||||
|     JSON_HEDLEY_NON_NULL(2) | ||||
|     bool sax_parse(SAX* sax, const bool strict = true) | ||||
|     { | ||||
|         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; | ||||
|         const bool result = sax_parse_internal(sax); | ||||
|  | ||||
|         // strict mode: next byte must be EOF | ||||
|         if (result && strict && (get_token() != token_type::end_of_input)) | ||||
|         { | ||||
|             return sax->parse_error(m_lexer.get_position(), | ||||
|                                     m_lexer.get_token_string(), | ||||
|                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     template<typename SAX> | ||||
|     JSON_HEDLEY_NON_NULL(2) | ||||
|     bool sax_parse_internal(SAX* sax) | ||||
|     { | ||||
|         // stack to remember the hierarchy of structured values we are parsing | ||||
|         // true = array; false = object | ||||
|         std::vector<bool> states; | ||||
|         // value to avoid a goto (see comment where set to true) | ||||
|         bool skip_to_state_evaluation = false; | ||||
|  | ||||
|         while (true) | ||||
|         { | ||||
|             if (!skip_to_state_evaluation) | ||||
|             { | ||||
|                 // invariant: get_token() was called before each iteration | ||||
|                 switch (last_token) | ||||
|                 { | ||||
|                     case token_type::begin_object: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|  | ||||
|                         // closing } -> we are done | ||||
|                         if (get_token() == token_type::end_object) | ||||
|                         { | ||||
|                             if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) | ||||
|                             { | ||||
|                                 return false; | ||||
|                             } | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         // parse key | ||||
|                         if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) | ||||
|                         { | ||||
|                             return sax->parse_error(m_lexer.get_position(), | ||||
|                                                     m_lexer.get_token_string(), | ||||
|                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); | ||||
|                         } | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|  | ||||
|                         // parse separator (:) | ||||
|                         if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) | ||||
|                         { | ||||
|                             return sax->parse_error(m_lexer.get_position(), | ||||
|                                                     m_lexer.get_token_string(), | ||||
|                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); | ||||
|                         } | ||||
|  | ||||
|                         // remember we are now inside an object | ||||
|                         states.push_back(false); | ||||
|  | ||||
|                         // parse values | ||||
|                         get_token(); | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::begin_array: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|  | ||||
|                         // closing ] -> we are done | ||||
|                         if (get_token() == token_type::end_array) | ||||
|                         { | ||||
|                             if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) | ||||
|                             { | ||||
|                                 return false; | ||||
|                             } | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         // remember we are now inside an array | ||||
|                         states.push_back(true); | ||||
|  | ||||
|                         // parse values (no need to call get_token) | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::value_float: | ||||
|                     { | ||||
|                         const auto res = m_lexer.get_number_float(); | ||||
|  | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) | ||||
|                         { | ||||
|                             return sax->parse_error(m_lexer.get_position(), | ||||
|                                                     m_lexer.get_token_string(), | ||||
|                                                     out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); | ||||
|                         } | ||||
|  | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|  | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::literal_false: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::literal_null: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->null())) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::literal_true: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::value_integer: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::value_string: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::value_unsigned: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     case token_type::parse_error: | ||||
|                     { | ||||
|                         // using "uninitialized" to avoid "expected" message | ||||
|                         return sax->parse_error(m_lexer.get_position(), | ||||
|                                                 m_lexer.get_token_string(), | ||||
|                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); | ||||
|                     } | ||||
|                     case token_type::end_of_input: | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) | ||||
|                         { | ||||
|                             return sax->parse_error(m_lexer.get_position(), | ||||
|                                                     m_lexer.get_token_string(), | ||||
|                                                     parse_error::create(101, m_lexer.get_position(), | ||||
|                                                             "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); | ||||
|                         } | ||||
|  | ||||
|                         return sax->parse_error(m_lexer.get_position(), | ||||
|                                                 m_lexer.get_token_string(), | ||||
|                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); | ||||
|                     } | ||||
|                     case token_type::uninitialized: | ||||
|                     case token_type::end_array: | ||||
|                     case token_type::end_object: | ||||
|                     case token_type::name_separator: | ||||
|                     case token_type::value_separator: | ||||
|                     case token_type::literal_or_value: | ||||
|                     default: // the last token was unexpected | ||||
|                     { | ||||
|                         return sax->parse_error(m_lexer.get_position(), | ||||
|                                                 m_lexer.get_token_string(), | ||||
|                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 skip_to_state_evaluation = false; | ||||
|             } | ||||
|  | ||||
|             // we reached this line after we successfully parsed a value | ||||
|             if (states.empty()) | ||||
|             { | ||||
|                 // empty stack: we reached the end of the hierarchy: done | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             if (states.back())  // array | ||||
|             { | ||||
|                 // comma -> next value | ||||
|                 if (get_token() == token_type::value_separator) | ||||
|                 { | ||||
|                     // parse a new value | ||||
|                     get_token(); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // closing ] | ||||
|                 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) | ||||
|                 { | ||||
|                     if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) | ||||
|                     { | ||||
|                         return false; | ||||
|                     } | ||||
|  | ||||
|                     // We are done with this array. Before we can parse a | ||||
|                     // new value, we need to evaluate the new state first. | ||||
|                     // By setting skip_to_state_evaluation to false, we | ||||
|                     // are effectively jumping to the beginning of this if. | ||||
|                     JSON_ASSERT(!states.empty()); | ||||
|                     states.pop_back(); | ||||
|                     skip_to_state_evaluation = true; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 return sax->parse_error(m_lexer.get_position(), | ||||
|                                         m_lexer.get_token_string(), | ||||
|                                         parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); | ||||
|             } | ||||
|  | ||||
|             // states.back() is false -> object | ||||
|  | ||||
|             // comma -> next value | ||||
|             if (get_token() == token_type::value_separator) | ||||
|             { | ||||
|                 // parse key | ||||
|                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) | ||||
|                 { | ||||
|                     return sax->parse_error(m_lexer.get_position(), | ||||
|                                             m_lexer.get_token_string(), | ||||
|                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); | ||||
|                 } | ||||
|  | ||||
|                 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) | ||||
|                 { | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 // parse separator (:) | ||||
|                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) | ||||
|                 { | ||||
|                     return sax->parse_error(m_lexer.get_position(), | ||||
|                                             m_lexer.get_token_string(), | ||||
|                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); | ||||
|                 } | ||||
|  | ||||
|                 // parse values | ||||
|                 get_token(); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // closing } | ||||
|             if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) | ||||
|             { | ||||
|                 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) | ||||
|                 { | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 // We are done with this object. Before we can parse a | ||||
|                 // new value, we need to evaluate the new state first. | ||||
|                 // By setting skip_to_state_evaluation to false, we | ||||
|                 // are effectively jumping to the beginning of this if. | ||||
|                 JSON_ASSERT(!states.empty()); | ||||
|                 states.pop_back(); | ||||
|                 skip_to_state_evaluation = true; | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             return sax->parse_error(m_lexer.get_position(), | ||||
|                                     m_lexer.get_token_string(), | ||||
|                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// get next token from lexer | ||||
|     token_type get_token() | ||||
|     { | ||||
|         return last_token = m_lexer.scan(); | ||||
|     } | ||||
|  | ||||
|     std::string exception_message(const token_type expected, const std::string& context) | ||||
|     { | ||||
|         std::string error_msg = "syntax error "; | ||||
|  | ||||
|         if (!context.empty()) | ||||
|         { | ||||
|             error_msg += concat("while parsing ", context, ' '); | ||||
|         } | ||||
|  | ||||
|         error_msg += "- "; | ||||
|  | ||||
|         if (last_token == token_type::parse_error) | ||||
|         { | ||||
|             error_msg += concat(m_lexer.get_error_message(), "; last read: '", | ||||
|                                 m_lexer.get_token_string(), '\''); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); | ||||
|         } | ||||
|  | ||||
|         if (expected != token_type::uninitialized) | ||||
|         { | ||||
|             error_msg += concat("; expected ", lexer_t::token_type_name(expected)); | ||||
|         } | ||||
|  | ||||
|         return error_msg; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /// callback function | ||||
|     const parser_callback_t<BasicJsonType> callback = nullptr; | ||||
|     /// the type of the last read token | ||||
|     token_type last_token = token_type::uninitialized; | ||||
|     /// the lexer | ||||
|     lexer_t m_lexer; | ||||
|     /// whether to throw exceptions in case of errors | ||||
|     const bool allow_exceptions = true; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,37 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstddef> // size_t | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /// struct to capture the start position of the current token | ||||
| struct position_t | ||||
| { | ||||
|     /// the total number of characters read | ||||
|     std::size_t chars_read_total = 0; | ||||
|     /// the number of characters read in the current line | ||||
|     std::size_t chars_read_current_line = 0; | ||||
|     /// the number of lines read | ||||
|     std::size_t lines_read = 0; | ||||
|  | ||||
|     /// conversion to size_t to preserve SAX interface | ||||
|     constexpr operator size_t() const | ||||
|     { | ||||
|         return chars_read_total; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,35 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
| #include <nlohmann/detail/iterators/primitive_iterator.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /*! | ||||
| @brief an iterator value | ||||
|  | ||||
| @note This structure could easily be a union, but MSVC currently does not allow | ||||
| unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. | ||||
| */ | ||||
| template<typename BasicJsonType> struct internal_iterator | ||||
| { | ||||
|     /// iterator for JSON objects | ||||
|     typename BasicJsonType::object_t::iterator object_iterator {}; | ||||
|     /// iterator for JSON arrays | ||||
|     typename BasicJsonType::array_t::iterator array_iterator {}; | ||||
|     /// generic iterator for all other types | ||||
|     primitive_iterator_t primitive_iterator {}; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,751 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next | ||||
| #include <type_traits> // conditional, is_const, remove_const | ||||
|  | ||||
| #include <nlohmann/detail/exceptions.hpp> | ||||
| #include <nlohmann/detail/iterators/internal_iterator.hpp> | ||||
| #include <nlohmann/detail/iterators/primitive_iterator.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
| #include <nlohmann/detail/meta/type_traits.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| // forward declare, to be able to friend it later on | ||||
| template<typename IteratorType> class iteration_proxy; | ||||
| template<typename IteratorType> class iteration_proxy_value; | ||||
|  | ||||
| /*! | ||||
| @brief a template for a bidirectional iterator for the @ref basic_json class | ||||
| This class implements a both iterators (iterator and const_iterator) for the | ||||
| @ref basic_json class. | ||||
| @note An iterator is called *initialized* when a pointer to a JSON value has | ||||
|       been set (e.g., by a constructor or a copy assignment). If the iterator is | ||||
|       default-constructed, it is *uninitialized* and most methods are undefined. | ||||
|       **The library uses assertions to detect calls on uninitialized iterators.** | ||||
| @requirement The class satisfies the following concept requirements: | ||||
| - | ||||
| [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): | ||||
|   The iterator that can be moved can be moved in both directions (i.e. | ||||
|   incremented and decremented). | ||||
| @since version 1.0.0, simplified in version 2.0.9, change to bidirectional | ||||
|        iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) | ||||
| */ | ||||
| template<typename BasicJsonType> | ||||
| class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) | ||||
| { | ||||
|     /// the iterator with BasicJsonType of different const-ness | ||||
|     using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; | ||||
|     /// allow basic_json to access private members | ||||
|     friend other_iter_impl; | ||||
|     friend BasicJsonType; | ||||
|     friend iteration_proxy<iter_impl>; | ||||
|     friend iteration_proxy_value<iter_impl>; | ||||
|  | ||||
|     using object_t = typename BasicJsonType::object_t; | ||||
|     using array_t = typename BasicJsonType::array_t; | ||||
|     // make sure BasicJsonType is basic_json or const basic_json | ||||
|     static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, | ||||
|                   "iter_impl only accepts (const) basic_json"); | ||||
|     // superficial check for the LegacyBidirectionalIterator named requirement | ||||
|     static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value | ||||
|                   &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value, | ||||
|                   "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); | ||||
|  | ||||
|   public: | ||||
|     /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. | ||||
|     /// The C++ Standard has never required user-defined iterators to derive from std::iterator. | ||||
|     /// A user-defined iterator should provide publicly accessible typedefs named | ||||
|     /// iterator_category, value_type, difference_type, pointer, and reference. | ||||
|     /// Note that value_type is required to be non-const, even for constant iterators. | ||||
|     using iterator_category = std::bidirectional_iterator_tag; | ||||
|  | ||||
|     /// the type of the values when the iterator is dereferenced | ||||
|     using value_type = typename BasicJsonType::value_type; | ||||
|     /// a type to represent differences between iterators | ||||
|     using difference_type = typename BasicJsonType::difference_type; | ||||
|     /// defines a pointer to the type iterated over (value_type) | ||||
|     using pointer = typename std::conditional<std::is_const<BasicJsonType>::value, | ||||
|           typename BasicJsonType::const_pointer, | ||||
|           typename BasicJsonType::pointer>::type; | ||||
|     /// defines a reference to the type iterated over (value_type) | ||||
|     using reference = | ||||
|         typename std::conditional<std::is_const<BasicJsonType>::value, | ||||
|         typename BasicJsonType::const_reference, | ||||
|         typename BasicJsonType::reference>::type; | ||||
|  | ||||
|     iter_impl() = default; | ||||
|     ~iter_impl() = default; | ||||
|     iter_impl(iter_impl&&) noexcept = default; | ||||
|     iter_impl& operator=(iter_impl&&) noexcept = default; | ||||
|  | ||||
|     /*! | ||||
|     @brief constructor for a given JSON instance | ||||
|     @param[in] object  pointer to a JSON object for this iterator | ||||
|     @pre object != nullptr | ||||
|     @post The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     explicit iter_impl(pointer object) noexcept : m_object(object) | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 m_it.object_iterator = typename object_t::iterator(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 m_it.array_iterator = typename array_t::iterator(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 m_it.primitive_iterator = primitive_iterator_t(); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @note The conventional copy constructor and copy assignment are implicitly | ||||
|           defined. Combined with the following converting constructor and | ||||
|           assignment, they support: (1) copy from iterator to iterator, (2) | ||||
|           copy from const iterator to const iterator, and (3) conversion from | ||||
|           iterator to const iterator. However conversion from const iterator | ||||
|           to iterator is not defined. | ||||
|     */ | ||||
|  | ||||
|     /*! | ||||
|     @brief const copy constructor | ||||
|     @param[in] other const iterator to copy from | ||||
|     @note This copy constructor had to be defined explicitly to circumvent a bug | ||||
|           occurring on msvc v19.0 compiler (VS 2015) debug build. For more | ||||
|           information refer to: https://github.com/nlohmann/json/issues/1608 | ||||
|     */ | ||||
|     iter_impl(const iter_impl<const BasicJsonType>& other) noexcept | ||||
|         : m_object(other.m_object), m_it(other.m_it) | ||||
|     {} | ||||
|  | ||||
|     /*! | ||||
|     @brief converting assignment | ||||
|     @param[in] other const iterator to copy from | ||||
|     @return const/non-const iterator | ||||
|     @note It is not checked whether @a other is initialized. | ||||
|     */ | ||||
|     iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept | ||||
|     { | ||||
|         if (&other != this) | ||||
|         { | ||||
|             m_object = other.m_object; | ||||
|             m_it = other.m_it; | ||||
|         } | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief converting constructor | ||||
|     @param[in] other  non-const iterator to copy from | ||||
|     @note It is not checked whether @a other is initialized. | ||||
|     */ | ||||
|     iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept | ||||
|         : m_object(other.m_object), m_it(other.m_it) | ||||
|     {} | ||||
|  | ||||
|     /*! | ||||
|     @brief converting assignment | ||||
|     @param[in] other  non-const iterator to copy from | ||||
|     @return const/non-const iterator | ||||
|     @note It is not checked whether @a other is initialized. | ||||
|     */ | ||||
|     iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp) | ||||
|     { | ||||
|         m_object = other.m_object; | ||||
|         m_it = other.m_it; | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|   JSON_PRIVATE_UNLESS_TESTED: | ||||
|     /*! | ||||
|     @brief set the iterator to the first value | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     void set_begin() noexcept | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 m_it.object_iterator = m_object->m_data.m_value.object->begin(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 m_it.array_iterator = m_object->m_data.m_value.array->begin(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             { | ||||
|                 // set to end so begin()==end() is true: null is empty | ||||
|                 m_it.primitive_iterator.set_end(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 m_it.primitive_iterator.set_begin(); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief set the iterator past the last value | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     void set_end() noexcept | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 m_it.object_iterator = m_object->m_data.m_value.object->end(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 m_it.array_iterator = m_object->m_data.m_value.array->end(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 m_it.primitive_iterator.set_end(); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   public: | ||||
|     /*! | ||||
|     @brief return a reference to the value pointed to by the iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     reference operator*() const | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); | ||||
|                 return m_it.object_iterator->second; | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); | ||||
|                 return *m_it.array_iterator; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | ||||
|  | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) | ||||
|                 { | ||||
|                     return *m_object; | ||||
|                 } | ||||
|  | ||||
|                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief dereference the iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     pointer operator->() const | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); | ||||
|                 return &(m_it.object_iterator->second); | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); | ||||
|                 return &*m_it.array_iterator; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) | ||||
|                 { | ||||
|                     return m_object; | ||||
|                 } | ||||
|  | ||||
|                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief post-increment (it++) | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) | ||||
|     { | ||||
|         auto result = *this; | ||||
|         ++(*this); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief pre-increment (++it) | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl& operator++() | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 std::advance(m_it.object_iterator, 1); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 std::advance(m_it.array_iterator, 1); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 ++m_it.primitive_iterator; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief post-decrement (it--) | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) | ||||
|     { | ||||
|         auto result = *this; | ||||
|         --(*this); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief pre-decrement (--it) | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl& operator--() | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 std::advance(m_it.object_iterator, -1); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 std::advance(m_it.array_iterator, -1); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 --m_it.primitive_iterator; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief comparison: equal | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > | ||||
|     bool operator==(const IterImpl& other) const | ||||
|     { | ||||
|         // if objects are not the same, the comparison is undefined | ||||
|         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) | ||||
|         { | ||||
|             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); | ||||
|         } | ||||
|  | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|                 return (m_it.object_iterator == other.m_it.object_iterator); | ||||
|  | ||||
|             case value_t::array: | ||||
|                 return (m_it.array_iterator == other.m_it.array_iterator); | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|                 return (m_it.primitive_iterator == other.m_it.primitive_iterator); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief comparison: not equal | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > | ||||
|     bool operator!=(const IterImpl& other) const | ||||
|     { | ||||
|         return !operator==(other); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief comparison: smaller | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     bool operator<(const iter_impl& other) const | ||||
|     { | ||||
|         // if objects are not the same, the comparison is undefined | ||||
|         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) | ||||
|         { | ||||
|             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); | ||||
|         } | ||||
|  | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|                 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); | ||||
|  | ||||
|             case value_t::array: | ||||
|                 return (m_it.array_iterator < other.m_it.array_iterator); | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|                 return (m_it.primitive_iterator < other.m_it.primitive_iterator); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief comparison: less than or equal | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     bool operator<=(const iter_impl& other) const | ||||
|     { | ||||
|         return !other.operator < (*this); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief comparison: greater than | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     bool operator>(const iter_impl& other) const | ||||
|     { | ||||
|         return !operator<=(other); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief comparison: greater than or equal | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     bool operator>=(const iter_impl& other) const | ||||
|     { | ||||
|         return !operator<(other); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief add to iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl& operator+=(difference_type i) | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 std::advance(m_it.array_iterator, i); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 m_it.primitive_iterator += i; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief subtract from iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl& operator-=(difference_type i) | ||||
|     { | ||||
|         return operator+=(-i); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief add to iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl operator+(difference_type i) const | ||||
|     { | ||||
|         auto result = *this; | ||||
|         result += i; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief addition of distance and iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     friend iter_impl operator+(difference_type i, const iter_impl& it) | ||||
|     { | ||||
|         auto result = it; | ||||
|         result += i; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief subtract from iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     iter_impl operator-(difference_type i) const | ||||
|     { | ||||
|         auto result = *this; | ||||
|         result -= i; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief return difference | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     difference_type operator-(const iter_impl& other) const | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); | ||||
|  | ||||
|             case value_t::array: | ||||
|                 return m_it.array_iterator - other.m_it.array_iterator; | ||||
|  | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|                 return m_it.primitive_iterator - other.m_it.primitive_iterator; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief access to successor | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     reference operator[](difference_type n) const | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         switch (m_object->m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|                 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); | ||||
|  | ||||
|             case value_t::array: | ||||
|                 return *std::next(m_it.array_iterator, n); | ||||
|  | ||||
|             case value_t::null: | ||||
|                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | ||||
|  | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) | ||||
|                 { | ||||
|                     return *m_object; | ||||
|                 } | ||||
|  | ||||
|                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief return the key of an object iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     const typename object_t::key_type& key() const | ||||
|     { | ||||
|         JSON_ASSERT(m_object != nullptr); | ||||
|  | ||||
|         if (JSON_HEDLEY_LIKELY(m_object->is_object())) | ||||
|         { | ||||
|             return m_it.object_iterator->first; | ||||
|         } | ||||
|  | ||||
|         JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief return the value of an iterator | ||||
|     @pre The iterator is initialized; i.e. `m_object != nullptr`. | ||||
|     */ | ||||
|     reference value() const | ||||
|     { | ||||
|         return operator*(); | ||||
|     } | ||||
|  | ||||
|   JSON_PRIVATE_UNLESS_TESTED: | ||||
|     /// associated JSON instance | ||||
|     pointer m_object = nullptr; | ||||
|     /// the actual iterator of the associated instance | ||||
|     internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {}; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,242 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstddef> // size_t | ||||
| #include <iterator> // input_iterator_tag | ||||
| #include <string> // string, to_string | ||||
| #include <tuple> // tuple_size, get, tuple_element | ||||
| #include <utility> // move | ||||
|  | ||||
| #if JSON_HAS_RANGES | ||||
|     #include <ranges> // enable_borrowed_range | ||||
| #endif | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
| #include <nlohmann/detail/meta/type_traits.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<typename string_type> | ||||
| void int_to_string( string_type& target, std::size_t value ) | ||||
| { | ||||
|     // For ADL | ||||
|     using std::to_string; | ||||
|     target = to_string(value); | ||||
| } | ||||
| template<typename IteratorType> class iteration_proxy_value | ||||
| { | ||||
|   public: | ||||
|     using difference_type = std::ptrdiff_t; | ||||
|     using value_type = iteration_proxy_value; | ||||
|     using pointer = value_type *; | ||||
|     using reference = value_type &; | ||||
|     using iterator_category = std::input_iterator_tag; | ||||
|     using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type; | ||||
|  | ||||
|   private: | ||||
|     /// the iterator | ||||
|     IteratorType anchor{}; | ||||
|     /// an index for arrays (used to create key names) | ||||
|     std::size_t array_index = 0; | ||||
|     /// last stringified array index | ||||
|     mutable std::size_t array_index_last = 0; | ||||
|     /// a string representation of the array index | ||||
|     mutable string_type array_index_str = "0"; | ||||
|     /// an empty string (to return a reference for primitive values) | ||||
|     string_type empty_str{}; | ||||
|  | ||||
|   public: | ||||
|     explicit iteration_proxy_value() = default; | ||||
|     explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) | ||||
|     noexcept(std::is_nothrow_move_constructible<IteratorType>::value | ||||
|              && std::is_nothrow_default_constructible<string_type>::value) | ||||
|         : anchor(std::move(it)) | ||||
|         , array_index(array_index_) | ||||
|     {} | ||||
|  | ||||
|     iteration_proxy_value(iteration_proxy_value const&) = default; | ||||
|     iteration_proxy_value& operator=(iteration_proxy_value const&) = default; | ||||
|     // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions | ||||
|     iteration_proxy_value(iteration_proxy_value&&) | ||||
|     noexcept(std::is_nothrow_move_constructible<IteratorType>::value | ||||
|              && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) | ||||
|     iteration_proxy_value& operator=(iteration_proxy_value&&) | ||||
|     noexcept(std::is_nothrow_move_assignable<IteratorType>::value | ||||
|              && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) | ||||
|     ~iteration_proxy_value() = default; | ||||
|  | ||||
|     /// dereference operator (needed for range-based for) | ||||
|     const iteration_proxy_value& operator*() const | ||||
|     { | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     /// increment operator (needed for range-based for) | ||||
|     iteration_proxy_value& operator++() | ||||
|     { | ||||
|         ++anchor; | ||||
|         ++array_index; | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) | ||||
|     { | ||||
|         auto tmp = iteration_proxy_value(anchor, array_index); | ||||
|         ++anchor; | ||||
|         ++array_index; | ||||
|         return tmp; | ||||
|     } | ||||
|  | ||||
|     /// equality operator (needed for InputIterator) | ||||
|     bool operator==(const iteration_proxy_value& o) const | ||||
|     { | ||||
|         return anchor == o.anchor; | ||||
|     } | ||||
|  | ||||
|     /// inequality operator (needed for range-based for) | ||||
|     bool operator!=(const iteration_proxy_value& o) const | ||||
|     { | ||||
|         return anchor != o.anchor; | ||||
|     } | ||||
|  | ||||
|     /// return key of the iterator | ||||
|     const string_type& key() const | ||||
|     { | ||||
|         JSON_ASSERT(anchor.m_object != nullptr); | ||||
|  | ||||
|         switch (anchor.m_object->type()) | ||||
|         { | ||||
|             // use integer array index as key | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 if (array_index != array_index_last) | ||||
|                 { | ||||
|                     int_to_string( array_index_str, array_index ); | ||||
|                     array_index_last = array_index; | ||||
|                 } | ||||
|                 return array_index_str; | ||||
|             } | ||||
|  | ||||
|             // use key from the object | ||||
|             case value_t::object: | ||||
|                 return anchor.key(); | ||||
|  | ||||
|             // use an empty key for all primitive types | ||||
|             case value_t::null: | ||||
|             case value_t::string: | ||||
|             case value_t::boolean: | ||||
|             case value_t::number_integer: | ||||
|             case value_t::number_unsigned: | ||||
|             case value_t::number_float: | ||||
|             case value_t::binary: | ||||
|             case value_t::discarded: | ||||
|             default: | ||||
|                 return empty_str; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// return value of the iterator | ||||
|     typename IteratorType::reference value() const | ||||
|     { | ||||
|         return anchor.value(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /// proxy class for the items() function | ||||
| template<typename IteratorType> class iteration_proxy | ||||
| { | ||||
|   private: | ||||
|     /// the container to iterate | ||||
|     typename IteratorType::pointer container = nullptr; | ||||
|  | ||||
|   public: | ||||
|     explicit iteration_proxy() = default; | ||||
|  | ||||
|     /// construct iteration proxy from a container | ||||
|     explicit iteration_proxy(typename IteratorType::reference cont) noexcept | ||||
|         : container(&cont) {} | ||||
|  | ||||
|     iteration_proxy(iteration_proxy const&) = default; | ||||
|     iteration_proxy& operator=(iteration_proxy const&) = default; | ||||
|     iteration_proxy(iteration_proxy&&) noexcept = default; | ||||
|     iteration_proxy& operator=(iteration_proxy&&) noexcept = default; | ||||
|     ~iteration_proxy() = default; | ||||
|  | ||||
|     /// return iterator begin (needed for range-based for) | ||||
|     iteration_proxy_value<IteratorType> begin() const noexcept | ||||
|     { | ||||
|         return iteration_proxy_value<IteratorType>(container->begin()); | ||||
|     } | ||||
|  | ||||
|     /// return iterator end (needed for range-based for) | ||||
|     iteration_proxy_value<IteratorType> end() const noexcept | ||||
|     { | ||||
|         return iteration_proxy_value<IteratorType>(container->end()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // Structured Bindings Support | ||||
| // For further reference see https://blog.tartanllama.xyz/structured-bindings/ | ||||
| // And see https://github.com/nlohmann/json/pull/1391 | ||||
| template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0> | ||||
| auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) | ||||
| { | ||||
|     return i.key(); | ||||
| } | ||||
| // Structured Bindings Support | ||||
| // For further reference see https://blog.tartanllama.xyz/structured-bindings/ | ||||
| // And see https://github.com/nlohmann/json/pull/1391 | ||||
| template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0> | ||||
| auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) | ||||
| { | ||||
|     return i.value(); | ||||
| } | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
|  | ||||
| // The Addition to the STD Namespace is required to add | ||||
| // Structured Bindings Support to the iteration_proxy_value class | ||||
| // For further reference see https://blog.tartanllama.xyz/structured-bindings/ | ||||
| // And see https://github.com/nlohmann/json/pull/1391 | ||||
| namespace std | ||||
| { | ||||
|  | ||||
| #if defined(__clang__) | ||||
|     // Fix: https://github.com/nlohmann/json/issues/1401 | ||||
|     #pragma clang diagnostic push | ||||
|     #pragma clang diagnostic ignored "-Wmismatched-tags" | ||||
| #endif | ||||
| template<typename IteratorType> | ||||
| class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp) | ||||
|             : public std::integral_constant<std::size_t, 2> {}; | ||||
|  | ||||
| template<std::size_t N, typename IteratorType> | ||||
| class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp) | ||||
| { | ||||
|   public: | ||||
|     using type = decltype( | ||||
|                      get<N>(std::declval < | ||||
|                             ::nlohmann::detail::iteration_proxy_value<IteratorType >> ())); | ||||
| }; | ||||
| #if defined(__clang__) | ||||
|     #pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
| }  // namespace std | ||||
|  | ||||
| #if JSON_HAS_RANGES | ||||
|     template <typename IteratorType> | ||||
|     inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true; | ||||
| #endif | ||||
| @@ -0,0 +1,61 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <iterator> // random_access_iterator_tag | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
| #include <nlohmann/detail/meta/void_t.hpp> | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<typename It, typename = void> | ||||
| struct iterator_types {}; | ||||
|  | ||||
| template<typename It> | ||||
| struct iterator_types < | ||||
|     It, | ||||
|     void_t<typename It::difference_type, typename It::value_type, typename It::pointer, | ||||
|     typename It::reference, typename It::iterator_category >> | ||||
| { | ||||
|     using difference_type = typename It::difference_type; | ||||
|     using value_type = typename It::value_type; | ||||
|     using pointer = typename It::pointer; | ||||
|     using reference = typename It::reference; | ||||
|     using iterator_category = typename It::iterator_category; | ||||
| }; | ||||
|  | ||||
| // This is required as some compilers implement std::iterator_traits in a way that | ||||
| // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. | ||||
| template<typename T, typename = void> | ||||
| struct iterator_traits | ||||
| { | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >> | ||||
|             : iterator_types<T> | ||||
| { | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> | ||||
| { | ||||
|     using iterator_category = std::random_access_iterator_tag; | ||||
|     using value_type = T; | ||||
|     using difference_type = ptrdiff_t; | ||||
|     using pointer = T*; | ||||
|     using reference = T&; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,130 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstddef> // ptrdiff_t | ||||
| #include <iterator> // reverse_iterator | ||||
| #include <utility> // declval | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| ////////////////////// | ||||
| // reverse_iterator // | ||||
| ////////////////////// | ||||
|  | ||||
| /*! | ||||
| @brief a template for a reverse iterator class | ||||
|  | ||||
| @tparam Base the base iterator type to reverse. Valid types are @ref | ||||
| iterator (to create @ref reverse_iterator) and @ref const_iterator (to | ||||
| create @ref const_reverse_iterator). | ||||
|  | ||||
| @requirement The class satisfies the following concept requirements: | ||||
| - | ||||
| [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): | ||||
|   The iterator that can be moved can be moved in both directions (i.e. | ||||
|   incremented and decremented). | ||||
| - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): | ||||
|   It is possible to write to the pointed-to element (only if @a Base is | ||||
|   @ref iterator). | ||||
|  | ||||
| @since version 1.0.0 | ||||
| */ | ||||
| template<typename Base> | ||||
| class json_reverse_iterator : public std::reverse_iterator<Base> | ||||
| { | ||||
|   public: | ||||
|     using difference_type = std::ptrdiff_t; | ||||
|     /// shortcut to the reverse iterator adapter | ||||
|     using base_iterator = std::reverse_iterator<Base>; | ||||
|     /// the reference type for the pointed-to element | ||||
|     using reference = typename Base::reference; | ||||
|  | ||||
|     /// create reverse iterator from iterator | ||||
|     explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept | ||||
|         : base_iterator(it) {} | ||||
|  | ||||
|     /// create reverse iterator from base class | ||||
|     explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} | ||||
|  | ||||
|     /// post-increment (it++) | ||||
|     json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) | ||||
|     { | ||||
|         return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); | ||||
|     } | ||||
|  | ||||
|     /// pre-increment (++it) | ||||
|     json_reverse_iterator& operator++() | ||||
|     { | ||||
|         return static_cast<json_reverse_iterator&>(base_iterator::operator++()); | ||||
|     } | ||||
|  | ||||
|     /// post-decrement (it--) | ||||
|     json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) | ||||
|     { | ||||
|         return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); | ||||
|     } | ||||
|  | ||||
|     /// pre-decrement (--it) | ||||
|     json_reverse_iterator& operator--() | ||||
|     { | ||||
|         return static_cast<json_reverse_iterator&>(base_iterator::operator--()); | ||||
|     } | ||||
|  | ||||
|     /// add to iterator | ||||
|     json_reverse_iterator& operator+=(difference_type i) | ||||
|     { | ||||
|         return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i)); | ||||
|     } | ||||
|  | ||||
|     /// add to iterator | ||||
|     json_reverse_iterator operator+(difference_type i) const | ||||
|     { | ||||
|         return static_cast<json_reverse_iterator>(base_iterator::operator+(i)); | ||||
|     } | ||||
|  | ||||
|     /// subtract from iterator | ||||
|     json_reverse_iterator operator-(difference_type i) const | ||||
|     { | ||||
|         return static_cast<json_reverse_iterator>(base_iterator::operator-(i)); | ||||
|     } | ||||
|  | ||||
|     /// return difference | ||||
|     difference_type operator-(const json_reverse_iterator& other) const | ||||
|     { | ||||
|         return base_iterator(*this) - base_iterator(other); | ||||
|     } | ||||
|  | ||||
|     /// access to successor | ||||
|     reference operator[](difference_type n) const | ||||
|     { | ||||
|         return *(this->operator+(n)); | ||||
|     } | ||||
|  | ||||
|     /// return the key of an object iterator | ||||
|     auto key() const -> decltype(std::declval<Base>().key()) | ||||
|     { | ||||
|         auto it = --this->base(); | ||||
|         return it.key(); | ||||
|     } | ||||
|  | ||||
|     /// return the value of an iterator | ||||
|     reference value() const | ||||
|     { | ||||
|         auto it = --this->base(); | ||||
|         return it.operator * (); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,132 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstddef> // ptrdiff_t | ||||
| #include <limits>  // numeric_limits | ||||
|  | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /* | ||||
| @brief an iterator for primitive JSON types | ||||
|  | ||||
| This class models an iterator for primitive JSON types (boolean, number, | ||||
| string). It's only purpose is to allow the iterator/const_iterator classes | ||||
| to "iterate" over primitive values. Internally, the iterator is modeled by | ||||
| a `difference_type` variable. Value begin_value (`0`) models the begin, | ||||
| end_value (`1`) models past the end. | ||||
| */ | ||||
| class primitive_iterator_t | ||||
| { | ||||
|   private: | ||||
|     using difference_type = std::ptrdiff_t; | ||||
|     static constexpr difference_type begin_value = 0; | ||||
|     static constexpr difference_type end_value = begin_value + 1; | ||||
|  | ||||
|   JSON_PRIVATE_UNLESS_TESTED: | ||||
|     /// iterator as signed integer type | ||||
|     difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)(); | ||||
|  | ||||
|   public: | ||||
|     constexpr difference_type get_value() const noexcept | ||||
|     { | ||||
|         return m_it; | ||||
|     } | ||||
|  | ||||
|     /// set iterator to a defined beginning | ||||
|     void set_begin() noexcept | ||||
|     { | ||||
|         m_it = begin_value; | ||||
|     } | ||||
|  | ||||
|     /// set iterator to a defined past the end | ||||
|     void set_end() noexcept | ||||
|     { | ||||
|         m_it = end_value; | ||||
|     } | ||||
|  | ||||
|     /// return whether the iterator can be dereferenced | ||||
|     constexpr bool is_begin() const noexcept | ||||
|     { | ||||
|         return m_it == begin_value; | ||||
|     } | ||||
|  | ||||
|     /// return whether the iterator is at end | ||||
|     constexpr bool is_end() const noexcept | ||||
|     { | ||||
|         return m_it == end_value; | ||||
|     } | ||||
|  | ||||
|     friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept | ||||
|     { | ||||
|         return lhs.m_it == rhs.m_it; | ||||
|     } | ||||
|  | ||||
|     friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept | ||||
|     { | ||||
|         return lhs.m_it < rhs.m_it; | ||||
|     } | ||||
|  | ||||
|     primitive_iterator_t operator+(difference_type n) noexcept | ||||
|     { | ||||
|         auto result = *this; | ||||
|         result += n; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept | ||||
|     { | ||||
|         return lhs.m_it - rhs.m_it; | ||||
|     } | ||||
|  | ||||
|     primitive_iterator_t& operator++() noexcept | ||||
|     { | ||||
|         ++m_it; | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) | ||||
|     { | ||||
|         auto result = *this; | ||||
|         ++m_it; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     primitive_iterator_t& operator--() noexcept | ||||
|     { | ||||
|         --m_it; | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) | ||||
|     { | ||||
|         auto result = *this; | ||||
|         --m_it; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     primitive_iterator_t& operator+=(difference_type n) noexcept | ||||
|     { | ||||
|         m_it += n; | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     primitive_iterator_t& operator-=(difference_type n) noexcept | ||||
|     { | ||||
|         m_it -= n; | ||||
|         return *this; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,31 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <type_traits> // conditional, is_same | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /*! | ||||
| @brief Default base class of the @ref basic_json class. | ||||
|  | ||||
| So that the correct implementations of the copy / move ctors / assign operators | ||||
| of @ref basic_json do not require complex case distinctions | ||||
| (no base class / custom base class used as customization point), | ||||
| @ref basic_json always has a base class. | ||||
| By default, this class is used because it is empty and thus has no effect | ||||
| on the behavior of @ref basic_json. | ||||
| */ | ||||
| struct json_default_base {}; | ||||
|  | ||||
| template<class T> | ||||
| using json_base_class = typename std::conditional < | ||||
|                         std::is_same<T, void>::value, | ||||
|                         json_default_base, | ||||
|                         T | ||||
|                         >::type; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,988 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <algorithm> // all_of | ||||
| #include <cctype> // isdigit | ||||
| #include <cerrno> // errno, ERANGE | ||||
| #include <cstdlib> // strtoull | ||||
| #ifndef JSON_NO_IO | ||||
|     #include <iosfwd> // ostream | ||||
| #endif  // JSON_NO_IO | ||||
| #include <limits> // max | ||||
| #include <numeric> // accumulate | ||||
| #include <string> // string | ||||
| #include <utility> // move | ||||
| #include <vector> // vector | ||||
|  | ||||
| #include <nlohmann/detail/exceptions.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/string_concat.hpp> | ||||
| #include <nlohmann/detail/string_escape.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
|  | ||||
| /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document | ||||
| /// @sa https://json.nlohmann.me/api/json_pointer/ | ||||
| template<typename RefStringType> | ||||
| class json_pointer | ||||
| { | ||||
|     // allow basic_json to access private members | ||||
|     NLOHMANN_BASIC_JSON_TPL_DECLARATION | ||||
|     friend class basic_json; | ||||
|  | ||||
|     template<typename> | ||||
|     friend class json_pointer; | ||||
|  | ||||
|     template<typename T> | ||||
|     struct string_t_helper | ||||
|     { | ||||
|         using type = T; | ||||
|     }; | ||||
|  | ||||
|     NLOHMANN_BASIC_JSON_TPL_DECLARATION | ||||
|     struct string_t_helper<NLOHMANN_BASIC_JSON_TPL> | ||||
|     { | ||||
|         using type = StringType; | ||||
|     }; | ||||
|  | ||||
|   public: | ||||
|     // for backwards compatibility accept BasicJsonType | ||||
|     using string_t = typename string_t_helper<RefStringType>::type; | ||||
|  | ||||
|     /// @brief create JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ | ||||
|     explicit json_pointer(const string_t& s = "") | ||||
|         : reference_tokens(split(s)) | ||||
|     {} | ||||
|  | ||||
|     /// @brief return a string representation of the JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ | ||||
|     string_t to_string() const | ||||
|     { | ||||
|         return std::accumulate(reference_tokens.begin(), reference_tokens.end(), | ||||
|                                string_t{}, | ||||
|                                [](const string_t& a, const string_t& b) | ||||
|         { | ||||
|             return detail::concat(a, '/', detail::escape(b)); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /// @brief return a string representation of the JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ | ||||
|     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) | ||||
|     operator string_t() const | ||||
|     { | ||||
|         return to_string(); | ||||
|     } | ||||
|  | ||||
| #ifndef JSON_NO_IO | ||||
|     /// @brief write string representation of the JSON pointer to stream | ||||
|     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ | ||||
|     friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) | ||||
|     { | ||||
|         o << ptr.to_string(); | ||||
|         return o; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /// @brief append another JSON pointer at the end of this JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ | ||||
|     json_pointer& operator/=(const json_pointer& ptr) | ||||
|     { | ||||
|         reference_tokens.insert(reference_tokens.end(), | ||||
|                                 ptr.reference_tokens.begin(), | ||||
|                                 ptr.reference_tokens.end()); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     /// @brief append an unescaped reference token at the end of this JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ | ||||
|     json_pointer& operator/=(string_t token) | ||||
|     { | ||||
|         push_back(std::move(token)); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     /// @brief append an array index at the end of this JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ | ||||
|     json_pointer& operator/=(std::size_t array_idx) | ||||
|     { | ||||
|         return *this /= std::to_string(array_idx); | ||||
|     } | ||||
|  | ||||
|     /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ | ||||
|     friend json_pointer operator/(const json_pointer& lhs, | ||||
|                                   const json_pointer& rhs) | ||||
|     { | ||||
|         return json_pointer(lhs) /= rhs; | ||||
|     } | ||||
|  | ||||
|     /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ | ||||
|     friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) | ||||
|     { | ||||
|         return json_pointer(lhs) /= std::move(token); | ||||
|     } | ||||
|  | ||||
|     /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ | ||||
|     friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) | ||||
|     { | ||||
|         return json_pointer(lhs) /= array_idx; | ||||
|     } | ||||
|  | ||||
|     /// @brief returns the parent of this JSON pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ | ||||
|     json_pointer parent_pointer() const | ||||
|     { | ||||
|         if (empty()) | ||||
|         { | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         json_pointer res = *this; | ||||
|         res.pop_back(); | ||||
|         return res; | ||||
|     } | ||||
|  | ||||
|     /// @brief remove last reference token | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ | ||||
|     void pop_back() | ||||
|     { | ||||
|         if (JSON_HEDLEY_UNLIKELY(empty())) | ||||
|         { | ||||
|             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); | ||||
|         } | ||||
|  | ||||
|         reference_tokens.pop_back(); | ||||
|     } | ||||
|  | ||||
|     /// @brief return last reference token | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/back/ | ||||
|     const string_t& back() const | ||||
|     { | ||||
|         if (JSON_HEDLEY_UNLIKELY(empty())) | ||||
|         { | ||||
|             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); | ||||
|         } | ||||
|  | ||||
|         return reference_tokens.back(); | ||||
|     } | ||||
|  | ||||
|     /// @brief append an unescaped token at the end of the reference pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ | ||||
|     void push_back(const string_t& token) | ||||
|     { | ||||
|         reference_tokens.push_back(token); | ||||
|     } | ||||
|  | ||||
|     /// @brief append an unescaped token at the end of the reference pointer | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ | ||||
|     void push_back(string_t&& token) | ||||
|     { | ||||
|         reference_tokens.push_back(std::move(token)); | ||||
|     } | ||||
|  | ||||
|     /// @brief return whether pointer points to the root document | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/empty/ | ||||
|     bool empty() const noexcept | ||||
|     { | ||||
|         return reference_tokens.empty(); | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /*! | ||||
|     @param[in] s  reference token to be converted into an array index | ||||
|  | ||||
|     @return integer representation of @a s | ||||
|  | ||||
|     @throw parse_error.106  if an array index begins with '0' | ||||
|     @throw parse_error.109  if an array index begins not with a digit | ||||
|     @throw out_of_range.404 if string @a s could not be converted to an integer | ||||
|     @throw out_of_range.410 if an array index exceeds size_type | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     static typename BasicJsonType::size_type array_index(const string_t& s) | ||||
|     { | ||||
|         using size_type = typename BasicJsonType::size_type; | ||||
|  | ||||
|         // error condition (cf. RFC 6901, Sect. 4) | ||||
|         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) | ||||
|         { | ||||
|             JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); | ||||
|         } | ||||
|  | ||||
|         // error condition (cf. RFC 6901, Sect. 4) | ||||
|         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) | ||||
|         { | ||||
|             JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); | ||||
|         } | ||||
|  | ||||
|         const char* p = s.c_str(); | ||||
|         char* p_end = nullptr; | ||||
|         errno = 0; // strtoull doesn't reset errno | ||||
|         const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) | ||||
|         if (p == p_end // invalid input or empty string | ||||
|                 || errno == ERANGE // out of range | ||||
|                 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read | ||||
|         { | ||||
|             JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); | ||||
|         } | ||||
|  | ||||
|         // only triggered on special platforms (like 32bit), see also | ||||
|         // https://github.com/nlohmann/json/pull/2203 | ||||
|         if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int) | ||||
|         { | ||||
|             JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE | ||||
|         } | ||||
|  | ||||
|         return static_cast<size_type>(res); | ||||
|     } | ||||
|  | ||||
|   JSON_PRIVATE_UNLESS_TESTED: | ||||
|     json_pointer top() const | ||||
|     { | ||||
|         if (JSON_HEDLEY_UNLIKELY(empty())) | ||||
|         { | ||||
|             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); | ||||
|         } | ||||
|  | ||||
|         json_pointer result = *this; | ||||
|         result.reference_tokens = {reference_tokens[0]}; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /*! | ||||
|     @brief create and return a reference to the pointed to value | ||||
|  | ||||
|     @complexity Linear in the number of reference tokens. | ||||
|  | ||||
|     @throw parse_error.109 if array index is not a number | ||||
|     @throw type_error.313 if value cannot be unflattened | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     BasicJsonType& get_and_create(BasicJsonType& j) const | ||||
|     { | ||||
|         auto* result = &j; | ||||
|  | ||||
|         // in case no reference tokens exist, return a reference to the JSON value | ||||
|         // j which will be overwritten by a primitive value | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (result->type()) | ||||
|             { | ||||
|                 case detail::value_t::null: | ||||
|                 { | ||||
|                     if (reference_token == "0") | ||||
|                     { | ||||
|                         // start a new array if reference token is 0 | ||||
|                         result = &result->operator[](0); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // start a new object otherwise | ||||
|                         result = &result->operator[](reference_token); | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|                     // create an entry in the object | ||||
|                     result = &result->operator[](reference_token); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::array: | ||||
|                 { | ||||
|                     // create an entry in the array | ||||
|                     result = &result->operator[](array_index<BasicJsonType>(reference_token)); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                 The following code is only reached if there exists a reference | ||||
|                 token _and_ the current value is primitive. In this case, we have | ||||
|                 an error situation, because primitive values may only occur as | ||||
|                 single value; that is, with an empty list of reference tokens. | ||||
|                 */ | ||||
|                 case detail::value_t::string: | ||||
|                 case detail::value_t::boolean: | ||||
|                 case detail::value_t::number_integer: | ||||
|                 case detail::value_t::number_unsigned: | ||||
|                 case detail::value_t::number_float: | ||||
|                 case detail::value_t::binary: | ||||
|                 case detail::value_t::discarded: | ||||
|                 default: | ||||
|                     JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *result; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief return a reference to the pointed to value | ||||
|  | ||||
|     @note This version does not throw if a value is not present, but tries to | ||||
|           create nested values instead. For instance, calling this function | ||||
|           with pointer `"/this/that"` on a null value is equivalent to calling | ||||
|           `operator[]("this").operator[]("that")` on that value, effectively | ||||
|           changing the null value to an object. | ||||
|  | ||||
|     @param[in] ptr  a JSON value | ||||
|  | ||||
|     @return reference to the JSON value pointed to by the JSON pointer | ||||
|  | ||||
|     @complexity Linear in the length of the JSON pointer. | ||||
|  | ||||
|     @throw parse_error.106   if an array index begins with '0' | ||||
|     @throw parse_error.109   if an array index was not a number | ||||
|     @throw out_of_range.404  if the JSON pointer can not be resolved | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     BasicJsonType& get_unchecked(BasicJsonType* ptr) const | ||||
|     { | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             // convert null values to arrays or objects before continuing | ||||
|             if (ptr->is_null()) | ||||
|             { | ||||
|                 // check if reference token is a number | ||||
|                 const bool nums = | ||||
|                     std::all_of(reference_token.begin(), reference_token.end(), | ||||
|                                 [](const unsigned char x) | ||||
|                 { | ||||
|                     return std::isdigit(x); | ||||
|                 }); | ||||
|  | ||||
|                 // change value to array for numbers or "-" or to object otherwise | ||||
|                 *ptr = (nums || reference_token == "-") | ||||
|                        ? detail::value_t::array | ||||
|                        : detail::value_t::object; | ||||
|             } | ||||
|  | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|                     // use unchecked object access | ||||
|                     ptr = &ptr->operator[](reference_token); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::array: | ||||
|                 { | ||||
|                     if (reference_token == "-") | ||||
|                     { | ||||
|                         // explicitly treat "-" as index beyond the end | ||||
|                         ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // convert array index to number; unchecked access | ||||
|                         ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::null: | ||||
|                 case detail::value_t::string: | ||||
|                 case detail::value_t::boolean: | ||||
|                 case detail::value_t::number_integer: | ||||
|                 case detail::value_t::number_unsigned: | ||||
|                 case detail::value_t::number_float: | ||||
|                 case detail::value_t::binary: | ||||
|                 case detail::value_t::discarded: | ||||
|                 default: | ||||
|                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *ptr; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @throw parse_error.106   if an array index begins with '0' | ||||
|     @throw parse_error.109   if an array index was not a number | ||||
|     @throw out_of_range.402  if the array index '-' is used | ||||
|     @throw out_of_range.404  if the JSON pointer can not be resolved | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     BasicJsonType& get_checked(BasicJsonType* ptr) const | ||||
|     { | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|                     // note: at performs range check | ||||
|                     ptr = &ptr->at(reference_token); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::array: | ||||
|                 { | ||||
|                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | ||||
|                     { | ||||
|                         // "-" always fails the range check | ||||
|                         JSON_THROW(detail::out_of_range::create(402, detail::concat( | ||||
|                                 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), | ||||
|                                 ") is out of range"), ptr)); | ||||
|                     } | ||||
|  | ||||
|                     // note: at performs range check | ||||
|                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::null: | ||||
|                 case detail::value_t::string: | ||||
|                 case detail::value_t::boolean: | ||||
|                 case detail::value_t::number_integer: | ||||
|                 case detail::value_t::number_unsigned: | ||||
|                 case detail::value_t::number_float: | ||||
|                 case detail::value_t::binary: | ||||
|                 case detail::value_t::discarded: | ||||
|                 default: | ||||
|                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *ptr; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief return a const reference to the pointed to value | ||||
|  | ||||
|     @param[in] ptr  a JSON value | ||||
|  | ||||
|     @return const reference to the JSON value pointed to by the JSON | ||||
|     pointer | ||||
|  | ||||
|     @throw parse_error.106   if an array index begins with '0' | ||||
|     @throw parse_error.109   if an array index was not a number | ||||
|     @throw out_of_range.402  if the array index '-' is used | ||||
|     @throw out_of_range.404  if the JSON pointer can not be resolved | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const | ||||
|     { | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|                     // use unchecked object access | ||||
|                     ptr = &ptr->operator[](reference_token); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::array: | ||||
|                 { | ||||
|                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | ||||
|                     { | ||||
|                         // "-" cannot be used for const access | ||||
|                         JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); | ||||
|                     } | ||||
|  | ||||
|                     // use unchecked array access | ||||
|                     ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::null: | ||||
|                 case detail::value_t::string: | ||||
|                 case detail::value_t::boolean: | ||||
|                 case detail::value_t::number_integer: | ||||
|                 case detail::value_t::number_unsigned: | ||||
|                 case detail::value_t::number_float: | ||||
|                 case detail::value_t::binary: | ||||
|                 case detail::value_t::discarded: | ||||
|                 default: | ||||
|                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *ptr; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @throw parse_error.106   if an array index begins with '0' | ||||
|     @throw parse_error.109   if an array index was not a number | ||||
|     @throw out_of_range.402  if the array index '-' is used | ||||
|     @throw out_of_range.404  if the JSON pointer can not be resolved | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     const BasicJsonType& get_checked(const BasicJsonType* ptr) const | ||||
|     { | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|                     // note: at performs range check | ||||
|                     ptr = &ptr->at(reference_token); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::array: | ||||
|                 { | ||||
|                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | ||||
|                     { | ||||
|                         // "-" always fails the range check | ||||
|                         JSON_THROW(detail::out_of_range::create(402, detail::concat( | ||||
|                                 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), | ||||
|                                 ") is out of range"), ptr)); | ||||
|                     } | ||||
|  | ||||
|                     // note: at performs range check | ||||
|                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::null: | ||||
|                 case detail::value_t::string: | ||||
|                 case detail::value_t::boolean: | ||||
|                 case detail::value_t::number_integer: | ||||
|                 case detail::value_t::number_unsigned: | ||||
|                 case detail::value_t::number_float: | ||||
|                 case detail::value_t::binary: | ||||
|                 case detail::value_t::discarded: | ||||
|                 default: | ||||
|                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return *ptr; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @throw parse_error.106   if an array index begins with '0' | ||||
|     @throw parse_error.109   if an array index was not a number | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     bool contains(const BasicJsonType* ptr) const | ||||
|     { | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|                     if (!ptr->contains(reference_token)) | ||||
|                     { | ||||
|                         // we did not find the key in the object | ||||
|                         return false; | ||||
|                     } | ||||
|  | ||||
|                     ptr = &ptr->operator[](reference_token); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::array: | ||||
|                 { | ||||
|                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | ||||
|                     { | ||||
|                         // "-" always fails the range check | ||||
|                         return false; | ||||
|                     } | ||||
|                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) | ||||
|                     { | ||||
|                         // invalid char | ||||
|                         return false; | ||||
|                     } | ||||
|                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) | ||||
|                     { | ||||
|                         if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) | ||||
|                         { | ||||
|                             // first char should be between '1' and '9' | ||||
|                             return false; | ||||
|                         } | ||||
|                         for (std::size_t i = 1; i < reference_token.size(); i++) | ||||
|                         { | ||||
|                             if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) | ||||
|                             { | ||||
|                                 // other char should be between '0' and '9' | ||||
|                                 return false; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     const auto idx = array_index<BasicJsonType>(reference_token); | ||||
|                     if (idx >= ptr->size()) | ||||
|                     { | ||||
|                         // index out of range | ||||
|                         return false; | ||||
|                     } | ||||
|  | ||||
|                     ptr = &ptr->operator[](idx); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case detail::value_t::null: | ||||
|                 case detail::value_t::string: | ||||
|                 case detail::value_t::boolean: | ||||
|                 case detail::value_t::number_integer: | ||||
|                 case detail::value_t::number_unsigned: | ||||
|                 case detail::value_t::number_float: | ||||
|                 case detail::value_t::binary: | ||||
|                 case detail::value_t::discarded: | ||||
|                 default: | ||||
|                 { | ||||
|                     // we do not expect primitive values if there is still a | ||||
|                     // reference token to process | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // no reference token left means we found a primitive value | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief split the string input to reference tokens | ||||
|  | ||||
|     @note This function is only called by the json_pointer constructor. | ||||
|           All exceptions below are documented there. | ||||
|  | ||||
|     @throw parse_error.107  if the pointer is not empty or begins with '/' | ||||
|     @throw parse_error.108  if character '~' is not followed by '0' or '1' | ||||
|     */ | ||||
|     static std::vector<string_t> split(const string_t& reference_string) | ||||
|     { | ||||
|         std::vector<string_t> result; | ||||
|  | ||||
|         // special case: empty reference string -> no reference tokens | ||||
|         if (reference_string.empty()) | ||||
|         { | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         // check if nonempty reference string begins with slash | ||||
|         if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) | ||||
|         { | ||||
|             JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); | ||||
|         } | ||||
|  | ||||
|         // extract the reference tokens: | ||||
|         // - slash: position of the last read slash (or end of string) | ||||
|         // - start: position after the previous slash | ||||
|         for ( | ||||
|             // search for the first slash after the first character | ||||
|             std::size_t slash = reference_string.find_first_of('/', 1), | ||||
|             // set the beginning of the first reference token | ||||
|             start = 1; | ||||
|             // we can stop if start == 0 (if slash == string_t::npos) | ||||
|             start != 0; | ||||
|             // set the beginning of the next reference token | ||||
|             // (will eventually be 0 if slash == string_t::npos) | ||||
|             start = (slash == string_t::npos) ? 0 : slash + 1, | ||||
|             // find next slash | ||||
|             slash = reference_string.find_first_of('/', start)) | ||||
|         { | ||||
|             // use the text between the beginning of the reference token | ||||
|             // (start) and the last slash (slash). | ||||
|             auto reference_token = reference_string.substr(start, slash - start); | ||||
|  | ||||
|             // check reference tokens are properly escaped | ||||
|             for (std::size_t pos = reference_token.find_first_of('~'); | ||||
|                     pos != string_t::npos; | ||||
|                     pos = reference_token.find_first_of('~', pos + 1)) | ||||
|             { | ||||
|                 JSON_ASSERT(reference_token[pos] == '~'); | ||||
|  | ||||
|                 // ~ must be followed by 0 or 1 | ||||
|                 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || | ||||
|                                          (reference_token[pos + 1] != '0' && | ||||
|                                           reference_token[pos + 1] != '1'))) | ||||
|                 { | ||||
|                     JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // finally, store the reference token | ||||
|             detail::unescape(reference_token); | ||||
|             result.push_back(reference_token); | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /*! | ||||
|     @param[in] reference_string  the reference string to the current value | ||||
|     @param[in] value             the value to consider | ||||
|     @param[in,out] result        the result object to insert values to | ||||
|  | ||||
|     @note Empty objects or arrays are flattened to `null`. | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     static void flatten(const string_t& reference_string, | ||||
|                         const BasicJsonType& value, | ||||
|                         BasicJsonType& result) | ||||
|     { | ||||
|         switch (value.type()) | ||||
|         { | ||||
|             case detail::value_t::array: | ||||
|             { | ||||
|                 if (value.m_data.m_value.array->empty()) | ||||
|                 { | ||||
|                     // flatten empty array as null | ||||
|                     result[reference_string] = nullptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // iterate array and use index as reference string | ||||
|                     for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) | ||||
|                     { | ||||
|                         flatten(detail::concat(reference_string, '/', std::to_string(i)), | ||||
|                                 value.m_data.m_value.array->operator[](i), result); | ||||
|                     } | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case detail::value_t::object: | ||||
|             { | ||||
|                 if (value.m_data.m_value.object->empty()) | ||||
|                 { | ||||
|                     // flatten empty object as null | ||||
|                     result[reference_string] = nullptr; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // iterate object and use keys as reference string | ||||
|                     for (const auto& element : *value.m_data.m_value.object) | ||||
|                     { | ||||
|                         flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); | ||||
|                     } | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case detail::value_t::null: | ||||
|             case detail::value_t::string: | ||||
|             case detail::value_t::boolean: | ||||
|             case detail::value_t::number_integer: | ||||
|             case detail::value_t::number_unsigned: | ||||
|             case detail::value_t::number_float: | ||||
|             case detail::value_t::binary: | ||||
|             case detail::value_t::discarded: | ||||
|             default: | ||||
|             { | ||||
|                 // add primitive value with its reference string | ||||
|                 result[reference_string] = value; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @param[in] value  flattened JSON | ||||
|  | ||||
|     @return unflattened JSON | ||||
|  | ||||
|     @throw parse_error.109 if array index is not a number | ||||
|     @throw type_error.314  if value is not an object | ||||
|     @throw type_error.315  if object values are not primitive | ||||
|     @throw type_error.313  if value cannot be unflattened | ||||
|     */ | ||||
|     template<typename BasicJsonType> | ||||
|     static BasicJsonType | ||||
|     unflatten(const BasicJsonType& value) | ||||
|     { | ||||
|         if (JSON_HEDLEY_UNLIKELY(!value.is_object())) | ||||
|         { | ||||
|             JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); | ||||
|         } | ||||
|  | ||||
|         BasicJsonType result; | ||||
|  | ||||
|         // iterate the JSON object values | ||||
|         for (const auto& element : *value.m_data.m_value.object) | ||||
|         { | ||||
|             if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) | ||||
|             { | ||||
|                 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); | ||||
|             } | ||||
|  | ||||
|             // assign value to reference pointed to by JSON pointer; Note that if | ||||
|             // the JSON pointer is "" (i.e., points to the whole value), function | ||||
|             // get_and_create returns a reference to result itself. An assignment | ||||
|             // will then create a primitive value. | ||||
|             json_pointer(element.first).get_and_create(result) = element.second; | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     // can't use conversion operator because of ambiguity | ||||
|     json_pointer<string_t> convert() const& | ||||
|     { | ||||
|         json_pointer<string_t> result; | ||||
|         result.reference_tokens = reference_tokens; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     json_pointer<string_t> convert()&& | ||||
|     { | ||||
|         json_pointer<string_t> result; | ||||
|         result.reference_tokens = std::move(reference_tokens); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|   public: | ||||
| #if JSON_HAS_THREE_WAY_COMPARISON | ||||
|     /// @brief compares two JSON pointers for equality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | ||||
|     template<typename RefStringTypeRhs> | ||||
|     bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept | ||||
|     { | ||||
|         return reference_tokens == rhs.reference_tokens; | ||||
|     } | ||||
|  | ||||
|     /// @brief compares JSON pointer and string for equality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | ||||
|     JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) | ||||
|     bool operator==(const string_t& rhs) const | ||||
|     { | ||||
|         return *this == json_pointer(rhs); | ||||
|     } | ||||
|  | ||||
|     /// @brief 3-way compares two JSON pointers | ||||
|     template<typename RefStringTypeRhs> | ||||
|     std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD* | ||||
|     { | ||||
|         return  reference_tokens <=> rhs.reference_tokens; // *NOPAD* | ||||
|     } | ||||
| #else | ||||
|     /// @brief compares two JSON pointers for equality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | ||||
|     template<typename RefStringTypeLhs, typename RefStringTypeRhs> | ||||
|     // NOLINTNEXTLINE(readability-redundant-declaration) | ||||
|     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                            const json_pointer<RefStringTypeRhs>& rhs) noexcept; | ||||
|  | ||||
|     /// @brief compares JSON pointer and string for equality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | ||||
|     template<typename RefStringTypeLhs, typename StringType> | ||||
|     // NOLINTNEXTLINE(readability-redundant-declaration) | ||||
|     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                            const StringType& rhs); | ||||
|  | ||||
|     /// @brief compares string and JSON pointer for equality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | ||||
|     template<typename RefStringTypeRhs, typename StringType> | ||||
|     // NOLINTNEXTLINE(readability-redundant-declaration) | ||||
|     friend bool operator==(const StringType& lhs, | ||||
|                            const json_pointer<RefStringTypeRhs>& rhs); | ||||
|  | ||||
|     /// @brief compares two JSON pointers for inequality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ | ||||
|     template<typename RefStringTypeLhs, typename RefStringTypeRhs> | ||||
|     // NOLINTNEXTLINE(readability-redundant-declaration) | ||||
|     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                            const json_pointer<RefStringTypeRhs>& rhs) noexcept; | ||||
|  | ||||
|     /// @brief compares JSON pointer and string for inequality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ | ||||
|     template<typename RefStringTypeLhs, typename StringType> | ||||
|     // NOLINTNEXTLINE(readability-redundant-declaration) | ||||
|     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                            const StringType& rhs); | ||||
|  | ||||
|     /// @brief compares string and JSON pointer for inequality | ||||
|     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ | ||||
|     template<typename RefStringTypeRhs, typename StringType> | ||||
|     // NOLINTNEXTLINE(readability-redundant-declaration) | ||||
|     friend bool operator!=(const StringType& lhs, | ||||
|                            const json_pointer<RefStringTypeRhs>& rhs); | ||||
|  | ||||
|     /// @brief compares two JSON pointer for less-than | ||||
|     template<typename RefStringTypeLhs, typename RefStringTypeRhs> | ||||
|     // NOLINTNEXTLINE(readability-redundant-declaration) | ||||
|     friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                           const json_pointer<RefStringTypeRhs>& rhs) noexcept; | ||||
| #endif | ||||
|  | ||||
|   private: | ||||
|     /// the reference tokens | ||||
|     std::vector<string_t> reference_tokens; | ||||
| }; | ||||
|  | ||||
| #if !JSON_HAS_THREE_WAY_COMPARISON | ||||
| // functions cannot be defined inside class due to ODR violations | ||||
| template<typename RefStringTypeLhs, typename RefStringTypeRhs> | ||||
| inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                        const json_pointer<RefStringTypeRhs>& rhs) noexcept | ||||
| { | ||||
|     return lhs.reference_tokens == rhs.reference_tokens; | ||||
| } | ||||
|  | ||||
| template<typename RefStringTypeLhs, | ||||
|          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> | ||||
| JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) | ||||
| inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                        const StringType& rhs) | ||||
| { | ||||
|     return lhs == json_pointer<RefStringTypeLhs>(rhs); | ||||
| } | ||||
|  | ||||
| template<typename RefStringTypeRhs, | ||||
|          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> | ||||
| JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) | ||||
| inline bool operator==(const StringType& lhs, | ||||
|                        const json_pointer<RefStringTypeRhs>& rhs) | ||||
| { | ||||
|     return json_pointer<RefStringTypeRhs>(lhs) == rhs; | ||||
| } | ||||
|  | ||||
| template<typename RefStringTypeLhs, typename RefStringTypeRhs> | ||||
| inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                        const json_pointer<RefStringTypeRhs>& rhs) noexcept | ||||
| { | ||||
|     return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| template<typename RefStringTypeLhs, | ||||
|          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> | ||||
| JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) | ||||
| inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                        const StringType& rhs) | ||||
| { | ||||
|     return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| template<typename RefStringTypeRhs, | ||||
|          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> | ||||
| JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) | ||||
| inline bool operator!=(const StringType& lhs, | ||||
|                        const json_pointer<RefStringTypeRhs>& rhs) | ||||
| { | ||||
|     return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| template<typename RefStringTypeLhs, typename RefStringTypeRhs> | ||||
| inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, | ||||
|                       const json_pointer<RefStringTypeRhs>& rhs) noexcept | ||||
| { | ||||
|     return lhs.reference_tokens < rhs.reference_tokens; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,78 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <initializer_list> | ||||
| #include <utility> | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
| #include <nlohmann/detail/meta/type_traits.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| class json_ref | ||||
| { | ||||
|   public: | ||||
|     using value_type = BasicJsonType; | ||||
|  | ||||
|     json_ref(value_type&& value) | ||||
|         : owned_value(std::move(value)) | ||||
|     {} | ||||
|  | ||||
|     json_ref(const value_type& value) | ||||
|         : value_ref(&value) | ||||
|     {} | ||||
|  | ||||
|     json_ref(std::initializer_list<json_ref> init) | ||||
|         : owned_value(init) | ||||
|     {} | ||||
|  | ||||
|     template < | ||||
|         class... Args, | ||||
|         enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 > | ||||
|     json_ref(Args && ... args) | ||||
|         : owned_value(std::forward<Args>(args)...) | ||||
|     {} | ||||
|  | ||||
|     // class should be movable only | ||||
|     json_ref(json_ref&&) noexcept = default; | ||||
|     json_ref(const json_ref&) = delete; | ||||
|     json_ref& operator=(const json_ref&) = delete; | ||||
|     json_ref& operator=(json_ref&&) = delete; | ||||
|     ~json_ref() = default; | ||||
|  | ||||
|     value_type moved_or_copied() const | ||||
|     { | ||||
|         if (value_ref == nullptr) | ||||
|         { | ||||
|             return std::move(owned_value); | ||||
|         } | ||||
|         return *value_ref; | ||||
|     } | ||||
|  | ||||
|     value_type const& operator*() const | ||||
|     { | ||||
|         return value_ref ? *value_ref : owned_value; | ||||
|     } | ||||
|  | ||||
|     value_type const* operator->() const | ||||
|     { | ||||
|         return &** this; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     mutable value_type owned_value = nullptr; | ||||
|     value_type const* value_ref = nullptr; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
							
								
								
									
										476
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/macro_scope.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										476
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/macro_scope.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,476 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <utility> // declval, pair | ||||
| #include <nlohmann/detail/meta/detected.hpp> | ||||
| #include <nlohmann/thirdparty/hedley/hedley.hpp> | ||||
|  | ||||
| // This file contains all internal macro definitions (except those affecting ABI) | ||||
| // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
|  | ||||
| // exclude unsupported compilers | ||||
| #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) | ||||
|     #if defined(__clang__) | ||||
|         #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 | ||||
|             #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" | ||||
|         #endif | ||||
|     #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) | ||||
|         #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 | ||||
|             #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" | ||||
|         #endif | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
| // C++ language standard detection | ||||
| // if the user manually specified the used c++ version this is skipped | ||||
| #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) | ||||
|     #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) | ||||
|         #define JSON_HAS_CPP_20 | ||||
|         #define JSON_HAS_CPP_17 | ||||
|         #define JSON_HAS_CPP_14 | ||||
|     #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 | ||||
|         #define JSON_HAS_CPP_17 | ||||
|         #define JSON_HAS_CPP_14 | ||||
|     #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) | ||||
|         #define JSON_HAS_CPP_14 | ||||
|     #endif | ||||
|     // the cpp 11 flag is always specified because it is the minimal required version | ||||
|     #define JSON_HAS_CPP_11 | ||||
| #endif | ||||
|  | ||||
| #ifdef __has_include | ||||
|     #if __has_include(<version>) | ||||
|         #include <version> | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
| #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) | ||||
|     #ifdef JSON_HAS_CPP_17 | ||||
|         #if defined(__cpp_lib_filesystem) | ||||
|             #define JSON_HAS_FILESYSTEM 1 | ||||
|         #elif defined(__cpp_lib_experimental_filesystem) | ||||
|             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 | ||||
|         #elif !defined(__has_include) | ||||
|             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 | ||||
|         #elif __has_include(<filesystem>) | ||||
|             #define JSON_HAS_FILESYSTEM 1 | ||||
|         #elif __has_include(<experimental/filesystem>) | ||||
|             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 | ||||
|         #endif | ||||
|  | ||||
|         // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ | ||||
|         #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 | ||||
|             #undef JSON_HAS_FILESYSTEM | ||||
|             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|         #endif | ||||
|  | ||||
|         // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support | ||||
|         #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 | ||||
|             #undef JSON_HAS_FILESYSTEM | ||||
|             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|         #endif | ||||
|  | ||||
|         // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support | ||||
|         #if defined(__clang_major__) && __clang_major__ < 7 | ||||
|             #undef JSON_HAS_FILESYSTEM | ||||
|             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|         #endif | ||||
|  | ||||
|         // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support | ||||
|         #if defined(_MSC_VER) && _MSC_VER < 1914 | ||||
|             #undef JSON_HAS_FILESYSTEM | ||||
|             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|         #endif | ||||
|  | ||||
|         // no filesystem support before iOS 13 | ||||
|         #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 | ||||
|             #undef JSON_HAS_FILESYSTEM | ||||
|             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|         #endif | ||||
|  | ||||
|         // no filesystem support before macOS Catalina | ||||
|         #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 | ||||
|             #undef JSON_HAS_FILESYSTEM | ||||
|             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|         #endif | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|     #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_HAS_FILESYSTEM | ||||
|     #define JSON_HAS_FILESYSTEM 0 | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_HAS_THREE_WAY_COMPARISON | ||||
|     #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ | ||||
|         && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L | ||||
|         #define JSON_HAS_THREE_WAY_COMPARISON 1 | ||||
|     #else | ||||
|         #define JSON_HAS_THREE_WAY_COMPARISON 0 | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_HAS_RANGES | ||||
|     // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error | ||||
|     #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 | ||||
|         #define JSON_HAS_RANGES 0 | ||||
|     #elif defined(__cpp_lib_ranges) | ||||
|         #define JSON_HAS_RANGES 1 | ||||
|     #else | ||||
|         #define JSON_HAS_RANGES 0 | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_HAS_STATIC_RTTI | ||||
|     #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 | ||||
|         #define JSON_HAS_STATIC_RTTI 1 | ||||
|     #else | ||||
|         #define JSON_HAS_STATIC_RTTI 0 | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
| #ifdef JSON_HAS_CPP_17 | ||||
|     #define JSON_INLINE_VARIABLE inline | ||||
| #else | ||||
|     #define JSON_INLINE_VARIABLE | ||||
| #endif | ||||
|  | ||||
| #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) | ||||
|     #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] | ||||
| #else | ||||
|     #define JSON_NO_UNIQUE_ADDRESS | ||||
| #endif | ||||
|  | ||||
| // disable documentation warnings on clang | ||||
| #if defined(__clang__) | ||||
|     #pragma clang diagnostic push | ||||
|     #pragma clang diagnostic ignored "-Wdocumentation" | ||||
|     #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" | ||||
| #endif | ||||
|  | ||||
| // allow disabling exceptions | ||||
| #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) | ||||
|     #define JSON_THROW(exception) throw exception | ||||
|     #define JSON_TRY try | ||||
|     #define JSON_CATCH(exception) catch(exception) | ||||
|     #define JSON_INTERNAL_CATCH(exception) catch(exception) | ||||
| #else | ||||
|     #include <cstdlib> | ||||
|     #define JSON_THROW(exception) std::abort() | ||||
|     #define JSON_TRY if(true) | ||||
|     #define JSON_CATCH(exception) if(false) | ||||
|     #define JSON_INTERNAL_CATCH(exception) if(false) | ||||
| #endif | ||||
|  | ||||
| // override exception macros | ||||
| #if defined(JSON_THROW_USER) | ||||
|     #undef JSON_THROW | ||||
|     #define JSON_THROW JSON_THROW_USER | ||||
| #endif | ||||
| #if defined(JSON_TRY_USER) | ||||
|     #undef JSON_TRY | ||||
|     #define JSON_TRY JSON_TRY_USER | ||||
| #endif | ||||
| #if defined(JSON_CATCH_USER) | ||||
|     #undef JSON_CATCH | ||||
|     #define JSON_CATCH JSON_CATCH_USER | ||||
|     #undef JSON_INTERNAL_CATCH | ||||
|     #define JSON_INTERNAL_CATCH JSON_CATCH_USER | ||||
| #endif | ||||
| #if defined(JSON_INTERNAL_CATCH_USER) | ||||
|     #undef JSON_INTERNAL_CATCH | ||||
|     #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER | ||||
| #endif | ||||
|  | ||||
| // allow overriding assert | ||||
| #if !defined(JSON_ASSERT) | ||||
|     #include <cassert> // assert | ||||
|     #define JSON_ASSERT(x) assert(x) | ||||
| #endif | ||||
|  | ||||
| // allow to access some private functions (needed by the test suite) | ||||
| #if defined(JSON_TESTS_PRIVATE) | ||||
|     #define JSON_PRIVATE_UNLESS_TESTED public | ||||
| #else | ||||
|     #define JSON_PRIVATE_UNLESS_TESTED private | ||||
| #endif | ||||
|  | ||||
| /*! | ||||
| @brief macro to briefly define a mapping between an enum and JSON | ||||
| @def NLOHMANN_JSON_SERIALIZE_ENUM | ||||
| @since version 3.4.0 | ||||
| */ | ||||
| #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \ | ||||
|     template<typename BasicJsonType>                                                            \ | ||||
|     inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \ | ||||
|     {                                                                                           \ | ||||
|         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \ | ||||
|         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \ | ||||
|         auto it = std::find_if(std::begin(m), std::end(m),                                      \ | ||||
|                                [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \ | ||||
|         {                                                                                       \ | ||||
|             return ej_pair.first == e;                                                          \ | ||||
|         });                                                                                     \ | ||||
|         j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \ | ||||
|     }                                                                                           \ | ||||
|     template<typename BasicJsonType>                                                            \ | ||||
|     inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \ | ||||
|     {                                                                                           \ | ||||
|         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \ | ||||
|         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \ | ||||
|         auto it = std::find_if(std::begin(m), std::end(m),                                      \ | ||||
|                                [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ | ||||
|         {                                                                                       \ | ||||
|             return ej_pair.second == j;                                                         \ | ||||
|         });                                                                                     \ | ||||
|         e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \ | ||||
|     } | ||||
|  | ||||
| // Ugly macros to avoid uglier copy-paste when specializing basic_json. They | ||||
| // may be removed in the future once the class is split. | ||||
|  | ||||
| #define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \ | ||||
|     template<template<typename, typename, typename...> class ObjectType,   \ | ||||
|              template<typename, typename...> class ArrayType,              \ | ||||
|              class StringType, class BooleanType, class NumberIntegerType, \ | ||||
|              class NumberUnsignedType, class NumberFloatType,              \ | ||||
|              template<typename> class AllocatorType,                       \ | ||||
|              template<typename, typename = void> class JSONSerializer,     \ | ||||
|              class BinaryType,                                             \ | ||||
|              class CustomBaseClass> | ||||
|  | ||||
| #define NLOHMANN_BASIC_JSON_TPL                                            \ | ||||
|     basic_json<ObjectType, ArrayType, StringType, BooleanType,             \ | ||||
|     NumberIntegerType, NumberUnsignedType, NumberFloatType,                \ | ||||
|     AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> | ||||
|  | ||||
| // Macros to simplify conversion from/to types | ||||
|  | ||||
| #define NLOHMANN_JSON_EXPAND( x ) x | ||||
| #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME | ||||
| #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ | ||||
|         NLOHMANN_JSON_PASTE64, \ | ||||
|         NLOHMANN_JSON_PASTE63, \ | ||||
|         NLOHMANN_JSON_PASTE62, \ | ||||
|         NLOHMANN_JSON_PASTE61, \ | ||||
|         NLOHMANN_JSON_PASTE60, \ | ||||
|         NLOHMANN_JSON_PASTE59, \ | ||||
|         NLOHMANN_JSON_PASTE58, \ | ||||
|         NLOHMANN_JSON_PASTE57, \ | ||||
|         NLOHMANN_JSON_PASTE56, \ | ||||
|         NLOHMANN_JSON_PASTE55, \ | ||||
|         NLOHMANN_JSON_PASTE54, \ | ||||
|         NLOHMANN_JSON_PASTE53, \ | ||||
|         NLOHMANN_JSON_PASTE52, \ | ||||
|         NLOHMANN_JSON_PASTE51, \ | ||||
|         NLOHMANN_JSON_PASTE50, \ | ||||
|         NLOHMANN_JSON_PASTE49, \ | ||||
|         NLOHMANN_JSON_PASTE48, \ | ||||
|         NLOHMANN_JSON_PASTE47, \ | ||||
|         NLOHMANN_JSON_PASTE46, \ | ||||
|         NLOHMANN_JSON_PASTE45, \ | ||||
|         NLOHMANN_JSON_PASTE44, \ | ||||
|         NLOHMANN_JSON_PASTE43, \ | ||||
|         NLOHMANN_JSON_PASTE42, \ | ||||
|         NLOHMANN_JSON_PASTE41, \ | ||||
|         NLOHMANN_JSON_PASTE40, \ | ||||
|         NLOHMANN_JSON_PASTE39, \ | ||||
|         NLOHMANN_JSON_PASTE38, \ | ||||
|         NLOHMANN_JSON_PASTE37, \ | ||||
|         NLOHMANN_JSON_PASTE36, \ | ||||
|         NLOHMANN_JSON_PASTE35, \ | ||||
|         NLOHMANN_JSON_PASTE34, \ | ||||
|         NLOHMANN_JSON_PASTE33, \ | ||||
|         NLOHMANN_JSON_PASTE32, \ | ||||
|         NLOHMANN_JSON_PASTE31, \ | ||||
|         NLOHMANN_JSON_PASTE30, \ | ||||
|         NLOHMANN_JSON_PASTE29, \ | ||||
|         NLOHMANN_JSON_PASTE28, \ | ||||
|         NLOHMANN_JSON_PASTE27, \ | ||||
|         NLOHMANN_JSON_PASTE26, \ | ||||
|         NLOHMANN_JSON_PASTE25, \ | ||||
|         NLOHMANN_JSON_PASTE24, \ | ||||
|         NLOHMANN_JSON_PASTE23, \ | ||||
|         NLOHMANN_JSON_PASTE22, \ | ||||
|         NLOHMANN_JSON_PASTE21, \ | ||||
|         NLOHMANN_JSON_PASTE20, \ | ||||
|         NLOHMANN_JSON_PASTE19, \ | ||||
|         NLOHMANN_JSON_PASTE18, \ | ||||
|         NLOHMANN_JSON_PASTE17, \ | ||||
|         NLOHMANN_JSON_PASTE16, \ | ||||
|         NLOHMANN_JSON_PASTE15, \ | ||||
|         NLOHMANN_JSON_PASTE14, \ | ||||
|         NLOHMANN_JSON_PASTE13, \ | ||||
|         NLOHMANN_JSON_PASTE12, \ | ||||
|         NLOHMANN_JSON_PASTE11, \ | ||||
|         NLOHMANN_JSON_PASTE10, \ | ||||
|         NLOHMANN_JSON_PASTE9, \ | ||||
|         NLOHMANN_JSON_PASTE8, \ | ||||
|         NLOHMANN_JSON_PASTE7, \ | ||||
|         NLOHMANN_JSON_PASTE6, \ | ||||
|         NLOHMANN_JSON_PASTE5, \ | ||||
|         NLOHMANN_JSON_PASTE4, \ | ||||
|         NLOHMANN_JSON_PASTE3, \ | ||||
|         NLOHMANN_JSON_PASTE2, \ | ||||
|         NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) | ||||
| #define NLOHMANN_JSON_PASTE2(func, v1) func(v1) | ||||
| #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) | ||||
| #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) | ||||
| #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) | ||||
| #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) | ||||
| #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) | ||||
| #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) | ||||
| #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) | ||||
| #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) | ||||
| #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) | ||||
| #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) | ||||
| #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) | ||||
| #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) | ||||
| #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) | ||||
| #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) | ||||
| #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) | ||||
| #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) | ||||
| #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) | ||||
| #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) | ||||
| #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) | ||||
| #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) | ||||
| #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) | ||||
| #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) | ||||
| #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) | ||||
| #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) | ||||
| #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) | ||||
| #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) | ||||
| #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) | ||||
| #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) | ||||
| #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) | ||||
| #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) | ||||
| #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) | ||||
| #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) | ||||
| #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) | ||||
| #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) | ||||
| #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) | ||||
| #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) | ||||
| #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) | ||||
| #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) | ||||
| #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) | ||||
| #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) | ||||
| #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) | ||||
| #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) | ||||
| #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) | ||||
| #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) | ||||
| #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) | ||||
| #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) | ||||
| #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) | ||||
| #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) | ||||
| #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) | ||||
| #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) | ||||
| #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) | ||||
| #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) | ||||
| #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) | ||||
| #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) | ||||
| #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) | ||||
| #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) | ||||
| #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) | ||||
| #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) | ||||
| #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) | ||||
| #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) | ||||
| #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) | ||||
| #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) | ||||
|  | ||||
| #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; | ||||
| #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); | ||||
| #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); | ||||
|  | ||||
| /*! | ||||
| @brief macro | ||||
| @def NLOHMANN_DEFINE_TYPE_INTRUSIVE | ||||
| @since version 3.9.0 | ||||
| */ | ||||
| #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \ | ||||
|     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | ||||
|     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } | ||||
|  | ||||
| #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \ | ||||
|     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | ||||
|     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } | ||||
|  | ||||
| /*! | ||||
| @brief macro | ||||
| @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE | ||||
| @since version 3.9.0 | ||||
| */ | ||||
| #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \ | ||||
|     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | ||||
|     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } | ||||
|  | ||||
| #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...)  \ | ||||
|     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | ||||
|     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } | ||||
|  | ||||
| // inspired from https://stackoverflow.com/a/26745591 | ||||
| // allows to call any std function as if (e.g. with begin): | ||||
| // using std::begin; begin(x); | ||||
| // | ||||
| // it allows using the detected idiom to retrieve the return type | ||||
| // of such an expression | ||||
| #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \ | ||||
|     namespace detail {                                                            \ | ||||
|     using std::std_name;                                                          \ | ||||
|     \ | ||||
|     template<typename... T>                                                       \ | ||||
|     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \ | ||||
|     }                                                                             \ | ||||
|     \ | ||||
|     namespace detail2 {                                                           \ | ||||
|     struct std_name##_tag                                                         \ | ||||
|     {                                                                             \ | ||||
|     };                                                                            \ | ||||
|     \ | ||||
|     template<typename... T>                                                       \ | ||||
|     std_name##_tag std_name(T&&...);                                              \ | ||||
|     \ | ||||
|     template<typename... T>                                                       \ | ||||
|     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \ | ||||
|     \ | ||||
|     template<typename... T>                                                       \ | ||||
|     struct would_call_std_##std_name                                              \ | ||||
|     {                                                                             \ | ||||
|         static constexpr auto const value = ::nlohmann::detail::                  \ | ||||
|                                             is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \ | ||||
|     };                                                                            \ | ||||
|     } /* namespace detail2 */ \ | ||||
|     \ | ||||
|     template<typename... T>                                                       \ | ||||
|     struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \ | ||||
|     {                                                                             \ | ||||
|     } | ||||
|  | ||||
| #ifndef JSON_USE_IMPLICIT_CONVERSIONS | ||||
|     #define JSON_USE_IMPLICIT_CONVERSIONS 1 | ||||
| #endif | ||||
|  | ||||
| #if JSON_USE_IMPLICIT_CONVERSIONS | ||||
|     #define JSON_EXPLICIT | ||||
| #else | ||||
|     #define JSON_EXPLICIT explicit | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_DISABLE_ENUM_SERIALIZATION | ||||
|     #define JSON_DISABLE_ENUM_SERIALIZATION 0 | ||||
| #endif | ||||
|  | ||||
| #ifndef JSON_USE_GLOBAL_UDLS | ||||
|     #define JSON_USE_GLOBAL_UDLS 1 | ||||
| #endif | ||||
| @@ -0,0 +1,45 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| // restore clang diagnostic settings | ||||
| #if defined(__clang__) | ||||
|     #pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
| // clean up | ||||
| #undef JSON_ASSERT | ||||
| #undef JSON_INTERNAL_CATCH | ||||
| #undef JSON_THROW | ||||
| #undef JSON_PRIVATE_UNLESS_TESTED | ||||
| #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION | ||||
| #undef NLOHMANN_BASIC_JSON_TPL | ||||
| #undef JSON_EXPLICIT | ||||
| #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL | ||||
| #undef JSON_INLINE_VARIABLE | ||||
| #undef JSON_NO_UNIQUE_ADDRESS | ||||
| #undef JSON_DISABLE_ENUM_SERIALIZATION | ||||
| #undef JSON_USE_GLOBAL_UDLS | ||||
|  | ||||
| #ifndef JSON_TEST_KEEP_MACROS | ||||
|     #undef JSON_CATCH | ||||
|     #undef JSON_TRY | ||||
|     #undef JSON_HAS_CPP_11 | ||||
|     #undef JSON_HAS_CPP_14 | ||||
|     #undef JSON_HAS_CPP_17 | ||||
|     #undef JSON_HAS_CPP_20 | ||||
|     #undef JSON_HAS_FILESYSTEM | ||||
|     #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
|     #undef JSON_HAS_THREE_WAY_COMPARISON | ||||
|     #undef JSON_HAS_RANGES | ||||
|     #undef JSON_HAS_STATIC_RTTI | ||||
|     #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | ||||
| #endif | ||||
|  | ||||
| #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> | ||||
| @@ -0,0 +1,17 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
|  | ||||
| NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,17 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
|  | ||||
| NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,171 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-FileCopyrightText: 2018 The Abseil Authors | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <array> // array | ||||
| #include <cstddef> // size_t | ||||
| #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type | ||||
| #include <utility> // index_sequence, make_index_sequence, index_sequence_for | ||||
|  | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<typename T> | ||||
| using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; | ||||
|  | ||||
| #ifdef JSON_HAS_CPP_14 | ||||
|  | ||||
| // the following utilities are natively available in C++14 | ||||
| using std::enable_if_t; | ||||
| using std::index_sequence; | ||||
| using std::make_index_sequence; | ||||
| using std::index_sequence_for; | ||||
|  | ||||
| #else | ||||
|  | ||||
| // alias templates to reduce boilerplate | ||||
| template<bool B, typename T = void> | ||||
| using enable_if_t = typename std::enable_if<B, T>::type; | ||||
|  | ||||
| // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h | ||||
| // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. | ||||
|  | ||||
| //// START OF CODE FROM GOOGLE ABSEIL | ||||
|  | ||||
| // integer_sequence | ||||
| // | ||||
| // Class template representing a compile-time integer sequence. An instantiation | ||||
| // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its | ||||
| // type through its template arguments (which is a common need when | ||||
| // working with C++11 variadic templates). `absl::integer_sequence` is designed | ||||
| // to be a drop-in replacement for C++14's `std::integer_sequence`. | ||||
| // | ||||
| // Example: | ||||
| // | ||||
| //   template< class T, T... Ints > | ||||
| //   void user_function(integer_sequence<T, Ints...>); | ||||
| // | ||||
| //   int main() | ||||
| //   { | ||||
| //     // user_function's `T` will be deduced to `int` and `Ints...` | ||||
| //     // will be deduced to `0, 1, 2, 3, 4`. | ||||
| //     user_function(make_integer_sequence<int, 5>()); | ||||
| //   } | ||||
| template <typename T, T... Ints> | ||||
| struct integer_sequence | ||||
| { | ||||
|     using value_type = T; | ||||
|     static constexpr std::size_t size() noexcept | ||||
|     { | ||||
|         return sizeof...(Ints); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // index_sequence | ||||
| // | ||||
| // A helper template for an `integer_sequence` of `size_t`, | ||||
| // `absl::index_sequence` is designed to be a drop-in replacement for C++14's | ||||
| // `std::index_sequence`. | ||||
| template <size_t... Ints> | ||||
| using index_sequence = integer_sequence<size_t, Ints...>; | ||||
|  | ||||
| namespace utility_internal | ||||
| { | ||||
|  | ||||
| template <typename Seq, size_t SeqSize, size_t Rem> | ||||
| struct Extend; | ||||
|  | ||||
| // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. | ||||
| template <typename T, T... Ints, size_t SeqSize> | ||||
| struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> | ||||
| { | ||||
|     using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; | ||||
| }; | ||||
|  | ||||
| template <typename T, T... Ints, size_t SeqSize> | ||||
| struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> | ||||
| { | ||||
|     using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; | ||||
| }; | ||||
|  | ||||
| // Recursion helper for 'make_integer_sequence<T, N>'. | ||||
| // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. | ||||
| template <typename T, size_t N> | ||||
| struct Gen | ||||
| { | ||||
|     using type = | ||||
|         typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct Gen<T, 0> | ||||
| { | ||||
|     using type = integer_sequence<T>; | ||||
| }; | ||||
|  | ||||
| }  // namespace utility_internal | ||||
|  | ||||
| // Compile-time sequences of integers | ||||
|  | ||||
| // make_integer_sequence | ||||
| // | ||||
| // This template alias is equivalent to | ||||
| // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in | ||||
| // replacement for C++14's `std::make_integer_sequence`. | ||||
| template <typename T, T N> | ||||
| using make_integer_sequence = typename utility_internal::Gen<T, N>::type; | ||||
|  | ||||
| // make_index_sequence | ||||
| // | ||||
| // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, | ||||
| // and is designed to be a drop-in replacement for C++14's | ||||
| // `std::make_index_sequence`. | ||||
| template <size_t N> | ||||
| using make_index_sequence = make_integer_sequence<size_t, N>; | ||||
|  | ||||
| // index_sequence_for | ||||
| // | ||||
| // Converts a typename pack into an index sequence of the same length, and | ||||
| // is designed to be a drop-in replacement for C++14's | ||||
| // `std::index_sequence_for()` | ||||
| template <typename... Ts> | ||||
| using index_sequence_for = make_index_sequence<sizeof...(Ts)>; | ||||
|  | ||||
| //// END OF CODE FROM GOOGLE ABSEIL | ||||
|  | ||||
| #endif | ||||
|  | ||||
| // dispatch utility (taken from ranges-v3) | ||||
| template<unsigned N> struct priority_tag : priority_tag < N - 1 > {}; | ||||
| template<> struct priority_tag<0> {}; | ||||
|  | ||||
| // taken from ranges-v3 | ||||
| template<typename T> | ||||
| struct static_const | ||||
| { | ||||
|     static JSON_INLINE_VARIABLE constexpr T value{}; | ||||
| }; | ||||
|  | ||||
| #ifndef JSON_HAS_CPP_17 | ||||
|     template<typename T> | ||||
|     constexpr T static_const<T>::value; | ||||
| #endif | ||||
|  | ||||
| template<typename T, typename... Args> | ||||
| inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args) | ||||
| { | ||||
|     return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}}; | ||||
| } | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,70 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <type_traits> | ||||
|  | ||||
| #include <nlohmann/detail/meta/void_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| // https://en.cppreference.com/w/cpp/experimental/is_detected | ||||
| struct nonesuch | ||||
| { | ||||
|     nonesuch() = delete; | ||||
|     ~nonesuch() = delete; | ||||
|     nonesuch(nonesuch const&) = delete; | ||||
|     nonesuch(nonesuch const&&) = delete; | ||||
|     void operator=(nonesuch const&) = delete; | ||||
|     void operator=(nonesuch&&) = delete; | ||||
| }; | ||||
|  | ||||
| template<class Default, | ||||
|          class AlwaysVoid, | ||||
|          template<class...> class Op, | ||||
|          class... Args> | ||||
| struct detector | ||||
| { | ||||
|     using value_t = std::false_type; | ||||
|     using type = Default; | ||||
| }; | ||||
|  | ||||
| template<class Default, template<class...> class Op, class... Args> | ||||
| struct detector<Default, void_t<Op<Args...>>, Op, Args...> | ||||
| { | ||||
|     using value_t = std::true_type; | ||||
|     using type = Op<Args...>; | ||||
| }; | ||||
|  | ||||
| template<template<class...> class Op, class... Args> | ||||
| using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; | ||||
|  | ||||
| template<template<class...> class Op, class... Args> | ||||
| struct is_detected_lazy : is_detected<Op, Args...> { }; | ||||
|  | ||||
| template<template<class...> class Op, class... Args> | ||||
| using detected_t = typename detector<nonesuch, void, Op, Args...>::type; | ||||
|  | ||||
| template<class Default, template<class...> class Op, class... Args> | ||||
| using detected_or = detector<Default, void, Op, Args...>; | ||||
|  | ||||
| template<class Default, template<class...> class Op, class... Args> | ||||
| using detected_or_t = typename detected_or<Default, Op, Args...>::type; | ||||
|  | ||||
| template<class Expected, template<class...> class Op, class... Args> | ||||
| using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; | ||||
|  | ||||
| template<class To, template<class...> class Op, class... Args> | ||||
| using is_detected_convertible = | ||||
|     std::is_convertible<detected_t<Op, Args...>, To>; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,21 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| // dispatching helper struct | ||||
| template <class T> struct identity_tag {}; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
							
								
								
									
										159
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/meta/is_sax.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/meta/is_sax.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstdint> // size_t | ||||
| #include <utility> // declval | ||||
| #include <string> // string | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
| #include <nlohmann/detail/meta/detected.hpp> | ||||
| #include <nlohmann/detail/meta/type_traits.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<typename T> | ||||
| using null_function_t = decltype(std::declval<T&>().null()); | ||||
|  | ||||
| template<typename T> | ||||
| using boolean_function_t = | ||||
|     decltype(std::declval<T&>().boolean(std::declval<bool>())); | ||||
|  | ||||
| template<typename T, typename Integer> | ||||
| using number_integer_function_t = | ||||
|     decltype(std::declval<T&>().number_integer(std::declval<Integer>())); | ||||
|  | ||||
| template<typename T, typename Unsigned> | ||||
| using number_unsigned_function_t = | ||||
|     decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>())); | ||||
|  | ||||
| template<typename T, typename Float, typename String> | ||||
| using number_float_function_t = decltype(std::declval<T&>().number_float( | ||||
|                                     std::declval<Float>(), std::declval<const String&>())); | ||||
|  | ||||
| template<typename T, typename String> | ||||
| using string_function_t = | ||||
|     decltype(std::declval<T&>().string(std::declval<String&>())); | ||||
|  | ||||
| template<typename T, typename Binary> | ||||
| using binary_function_t = | ||||
|     decltype(std::declval<T&>().binary(std::declval<Binary&>())); | ||||
|  | ||||
| template<typename T> | ||||
| using start_object_function_t = | ||||
|     decltype(std::declval<T&>().start_object(std::declval<std::size_t>())); | ||||
|  | ||||
| template<typename T, typename String> | ||||
| using key_function_t = | ||||
|     decltype(std::declval<T&>().key(std::declval<String&>())); | ||||
|  | ||||
| template<typename T> | ||||
| using end_object_function_t = decltype(std::declval<T&>().end_object()); | ||||
|  | ||||
| template<typename T> | ||||
| using start_array_function_t = | ||||
|     decltype(std::declval<T&>().start_array(std::declval<std::size_t>())); | ||||
|  | ||||
| template<typename T> | ||||
| using end_array_function_t = decltype(std::declval<T&>().end_array()); | ||||
|  | ||||
| template<typename T, typename Exception> | ||||
| using parse_error_function_t = decltype(std::declval<T&>().parse_error( | ||||
|         std::declval<std::size_t>(), std::declval<const std::string&>(), | ||||
|         std::declval<const Exception&>())); | ||||
|  | ||||
| template<typename SAX, typename BasicJsonType> | ||||
| struct is_sax | ||||
| { | ||||
|   private: | ||||
|     static_assert(is_basic_json<BasicJsonType>::value, | ||||
|                   "BasicJsonType must be of type basic_json<...>"); | ||||
|  | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using binary_t = typename BasicJsonType::binary_t; | ||||
|     using exception_t = typename BasicJsonType::exception; | ||||
|  | ||||
|   public: | ||||
|     static constexpr bool value = | ||||
|         is_detected_exact<bool, null_function_t, SAX>::value && | ||||
|         is_detected_exact<bool, boolean_function_t, SAX>::value && | ||||
|         is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value && | ||||
|         is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value && | ||||
|         is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value && | ||||
|         is_detected_exact<bool, string_function_t, SAX, string_t>::value && | ||||
|         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value && | ||||
|         is_detected_exact<bool, start_object_function_t, SAX>::value && | ||||
|         is_detected_exact<bool, key_function_t, SAX, string_t>::value && | ||||
|         is_detected_exact<bool, end_object_function_t, SAX>::value && | ||||
|         is_detected_exact<bool, start_array_function_t, SAX>::value && | ||||
|         is_detected_exact<bool, end_array_function_t, SAX>::value && | ||||
|         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value; | ||||
| }; | ||||
|  | ||||
| template<typename SAX, typename BasicJsonType> | ||||
| struct is_sax_static_asserts | ||||
| { | ||||
|   private: | ||||
|     static_assert(is_basic_json<BasicJsonType>::value, | ||||
|                   "BasicJsonType must be of type basic_json<...>"); | ||||
|  | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using binary_t = typename BasicJsonType::binary_t; | ||||
|     using exception_t = typename BasicJsonType::exception; | ||||
|  | ||||
|   public: | ||||
|     static_assert(is_detected_exact<bool, null_function_t, SAX>::value, | ||||
|                   "Missing/invalid function: bool null()"); | ||||
|     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, | ||||
|                   "Missing/invalid function: bool boolean(bool)"); | ||||
|     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, | ||||
|                   "Missing/invalid function: bool boolean(bool)"); | ||||
|     static_assert( | ||||
|         is_detected_exact<bool, number_integer_function_t, SAX, | ||||
|         number_integer_t>::value, | ||||
|         "Missing/invalid function: bool number_integer(number_integer_t)"); | ||||
|     static_assert( | ||||
|         is_detected_exact<bool, number_unsigned_function_t, SAX, | ||||
|         number_unsigned_t>::value, | ||||
|         "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); | ||||
|     static_assert(is_detected_exact<bool, number_float_function_t, SAX, | ||||
|                   number_float_t, string_t>::value, | ||||
|                   "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); | ||||
|     static_assert( | ||||
|         is_detected_exact<bool, string_function_t, SAX, string_t>::value, | ||||
|         "Missing/invalid function: bool string(string_t&)"); | ||||
|     static_assert( | ||||
|         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value, | ||||
|         "Missing/invalid function: bool binary(binary_t&)"); | ||||
|     static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value, | ||||
|                   "Missing/invalid function: bool start_object(std::size_t)"); | ||||
|     static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value, | ||||
|                   "Missing/invalid function: bool key(string_t&)"); | ||||
|     static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value, | ||||
|                   "Missing/invalid function: bool end_object()"); | ||||
|     static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value, | ||||
|                   "Missing/invalid function: bool start_array(std::size_t)"); | ||||
|     static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value, | ||||
|                   "Missing/invalid function: bool end_array()"); | ||||
|     static_assert( | ||||
|         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value, | ||||
|         "Missing/invalid function: bool parse_error(std::size_t, const " | ||||
|         "std::string&, const exception&)"); | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,29 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
|  | ||||
| #if JSON_HAS_EXPERIMENTAL_FILESYSTEM | ||||
| #include <experimental/filesystem> | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
| namespace std_fs = std::experimental::filesystem; | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| #elif JSON_HAS_FILESYSTEM | ||||
| #include <filesystem> | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
| namespace std_fs = std::filesystem; | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| #endif | ||||
| @@ -0,0 +1,737 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <limits> // numeric_limits | ||||
| #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type | ||||
| #include <utility> // declval | ||||
| #include <tuple> // tuple | ||||
|  | ||||
| #include <nlohmann/detail/iterators/iterator_traits.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/meta/call_std/begin.hpp> | ||||
| #include <nlohmann/detail/meta/call_std/end.hpp> | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
| #include <nlohmann/detail/meta/detected.hpp> | ||||
| #include <nlohmann/json_fwd.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| /*! | ||||
| @brief detail namespace with internal helper functions | ||||
|  | ||||
| This namespace collects functions that should not be exposed, | ||||
| implementations of some @ref basic_json methods, and meta-programming helpers. | ||||
|  | ||||
| @since version 2.1.0 | ||||
| */ | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| ///////////// | ||||
| // helpers // | ||||
| ///////////// | ||||
|  | ||||
| // Note to maintainers: | ||||
| // | ||||
| // Every trait in this file expects a non CV-qualified type. | ||||
| // The only exceptions are in the 'aliases for detected' section | ||||
| // (i.e. those of the form: decltype(T::member_function(std::declval<T>()))) | ||||
| // | ||||
| // In this case, T has to be properly CV-qualified to constraint the function arguments | ||||
| // (e.g. to_json(BasicJsonType&, const T&)) | ||||
|  | ||||
| template<typename> struct is_basic_json : std::false_type {}; | ||||
|  | ||||
| NLOHMANN_BASIC_JSON_TPL_DECLARATION | ||||
| struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {}; | ||||
|  | ||||
| // used by exceptions create() member functions | ||||
| // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t | ||||
| // false_type otherwise | ||||
| template<typename BasicJsonContext> | ||||
| struct is_basic_json_context : | ||||
|     std::integral_constant < bool, | ||||
|     is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value | ||||
|     || std::is_same<BasicJsonContext, std::nullptr_t>::value > | ||||
| {}; | ||||
|  | ||||
| ////////////////////// | ||||
| // json_ref helpers // | ||||
| ////////////////////// | ||||
|  | ||||
| template<typename> | ||||
| class json_ref; | ||||
|  | ||||
| template<typename> | ||||
| struct is_json_ref : std::false_type {}; | ||||
|  | ||||
| template<typename T> | ||||
| struct is_json_ref<json_ref<T>> : std::true_type {}; | ||||
|  | ||||
| ////////////////////////// | ||||
| // aliases for detected // | ||||
| ////////////////////////// | ||||
|  | ||||
| template<typename T> | ||||
| using mapped_type_t = typename T::mapped_type; | ||||
|  | ||||
| template<typename T> | ||||
| using key_type_t = typename T::key_type; | ||||
|  | ||||
| template<typename T> | ||||
| using value_type_t = typename T::value_type; | ||||
|  | ||||
| template<typename T> | ||||
| using difference_type_t = typename T::difference_type; | ||||
|  | ||||
| template<typename T> | ||||
| using pointer_t = typename T::pointer; | ||||
|  | ||||
| template<typename T> | ||||
| using reference_t = typename T::reference; | ||||
|  | ||||
| template<typename T> | ||||
| using iterator_category_t = typename T::iterator_category; | ||||
|  | ||||
| template<typename T, typename... Args> | ||||
| using to_json_function = decltype(T::to_json(std::declval<Args>()...)); | ||||
|  | ||||
| template<typename T, typename... Args> | ||||
| using from_json_function = decltype(T::from_json(std::declval<Args>()...)); | ||||
|  | ||||
| template<typename T, typename U> | ||||
| using get_template_function = decltype(std::declval<T>().template get<U>()); | ||||
|  | ||||
| // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists | ||||
| template<typename BasicJsonType, typename T, typename = void> | ||||
| struct has_from_json : std::false_type {}; | ||||
|  | ||||
| // trait checking if j.get<T> is valid | ||||
| // use this trait instead of std::is_constructible or std::is_convertible, | ||||
| // both rely on, or make use of implicit conversions, and thus fail when T | ||||
| // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) | ||||
| template <typename BasicJsonType, typename T> | ||||
| struct is_getable | ||||
| { | ||||
|     static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename T> | ||||
| struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> | ||||
| { | ||||
|     using serializer = typename BasicJsonType::template json_serializer<T, void>; | ||||
|  | ||||
|     static constexpr bool value = | ||||
|         is_detected_exact<void, from_json_function, serializer, | ||||
|         const BasicJsonType&, T&>::value; | ||||
| }; | ||||
|  | ||||
| // This trait checks if JSONSerializer<T>::from_json(json const&) exists | ||||
| // this overload is used for non-default-constructible user-defined-types | ||||
| template<typename BasicJsonType, typename T, typename = void> | ||||
| struct has_non_default_from_json : std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename T> | ||||
| struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> | ||||
| { | ||||
|     using serializer = typename BasicJsonType::template json_serializer<T, void>; | ||||
|  | ||||
|     static constexpr bool value = | ||||
|         is_detected_exact<T, from_json_function, serializer, | ||||
|         const BasicJsonType&>::value; | ||||
| }; | ||||
|  | ||||
| // This trait checks if BasicJsonType::json_serializer<T>::to_json exists | ||||
| // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. | ||||
| template<typename BasicJsonType, typename T, typename = void> | ||||
| struct has_to_json : std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename T> | ||||
| struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> | ||||
| { | ||||
|     using serializer = typename BasicJsonType::template json_serializer<T, void>; | ||||
|  | ||||
|     static constexpr bool value = | ||||
|         is_detected_exact<void, to_json_function, serializer, BasicJsonType&, | ||||
|         T>::value; | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| using detect_key_compare = typename T::key_compare; | ||||
|  | ||||
| template<typename T> | ||||
| struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {}; | ||||
|  | ||||
| // obtains the actual object key comparator | ||||
| template<typename BasicJsonType> | ||||
| struct actual_object_comparator | ||||
| { | ||||
|     using object_t = typename BasicJsonType::object_t; | ||||
|     using object_comparator_t = typename BasicJsonType::default_object_comparator_t; | ||||
|     using type = typename std::conditional < has_key_compare<object_t>::value, | ||||
|           typename object_t::key_compare, object_comparator_t>::type; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type; | ||||
|  | ||||
| /////////////////// | ||||
| // is_ functions // | ||||
| /////////////////// | ||||
|  | ||||
| // https://en.cppreference.com/w/cpp/types/conjunction | ||||
| template<class...> struct conjunction : std::true_type { }; | ||||
| template<class B> struct conjunction<B> : B { }; | ||||
| template<class B, class... Bn> | ||||
| struct conjunction<B, Bn...> | ||||
| : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {}; | ||||
|  | ||||
| // https://en.cppreference.com/w/cpp/types/negation | ||||
| template<class B> struct negation : std::integral_constant < bool, !B::value > { }; | ||||
|  | ||||
| // Reimplementation of is_constructible and is_default_constructible, due to them being broken for | ||||
| // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). | ||||
| // This causes compile errors in e.g. clang 3.5 or gcc 4.9. | ||||
| template <typename T> | ||||
| struct is_default_constructible : std::is_default_constructible<T> {}; | ||||
|  | ||||
| template <typename T1, typename T2> | ||||
| struct is_default_constructible<std::pair<T1, T2>> | ||||
|             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; | ||||
|  | ||||
| template <typename T1, typename T2> | ||||
| struct is_default_constructible<const std::pair<T1, T2>> | ||||
|             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; | ||||
|  | ||||
| template <typename... Ts> | ||||
| struct is_default_constructible<std::tuple<Ts...>> | ||||
|             : conjunction<is_default_constructible<Ts>...> {}; | ||||
|  | ||||
| template <typename... Ts> | ||||
| struct is_default_constructible<const std::tuple<Ts...>> | ||||
|             : conjunction<is_default_constructible<Ts>...> {}; | ||||
|  | ||||
| template <typename T, typename... Args> | ||||
| struct is_constructible : std::is_constructible<T, Args...> {}; | ||||
|  | ||||
| template <typename T1, typename T2> | ||||
| struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {}; | ||||
|  | ||||
| template <typename T1, typename T2> | ||||
| struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {}; | ||||
|  | ||||
| template <typename... Ts> | ||||
| struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {}; | ||||
|  | ||||
| template <typename... Ts> | ||||
| struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {}; | ||||
|  | ||||
| template<typename T, typename = void> | ||||
| struct is_iterator_traits : std::false_type {}; | ||||
|  | ||||
| template<typename T> | ||||
| struct is_iterator_traits<iterator_traits<T>> | ||||
| { | ||||
|   private: | ||||
|     using traits = iterator_traits<T>; | ||||
|  | ||||
|   public: | ||||
|     static constexpr auto value = | ||||
|         is_detected<value_type_t, traits>::value && | ||||
|         is_detected<difference_type_t, traits>::value && | ||||
|         is_detected<pointer_t, traits>::value && | ||||
|         is_detected<iterator_category_t, traits>::value && | ||||
|         is_detected<reference_t, traits>::value; | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct is_range | ||||
| { | ||||
|   private: | ||||
|     using t_ref = typename std::add_lvalue_reference<T>::type; | ||||
|  | ||||
|     using iterator = detected_t<result_of_begin, t_ref>; | ||||
|     using sentinel = detected_t<result_of_end, t_ref>; | ||||
|  | ||||
|     // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator | ||||
|     // and https://en.cppreference.com/w/cpp/iterator/sentinel_for | ||||
|     // but reimplementing these would be too much work, as a lot of other concepts are used underneath | ||||
|     static constexpr auto is_iterator_begin = | ||||
|         is_iterator_traits<iterator_traits<iterator>>::value; | ||||
|  | ||||
|   public: | ||||
|     static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin; | ||||
| }; | ||||
|  | ||||
| template<typename R> | ||||
| using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>; | ||||
|  | ||||
| template<typename T> | ||||
| using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>; | ||||
|  | ||||
| // The following implementation of is_complete_type is taken from | ||||
| // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ | ||||
| // and is written by Xiang Fan who agreed to using it in this library. | ||||
|  | ||||
| template<typename T, typename = void> | ||||
| struct is_complete_type : std::false_type {}; | ||||
|  | ||||
| template<typename T> | ||||
| struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleObjectType, | ||||
|          typename = void> | ||||
| struct is_compatible_object_type_impl : std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleObjectType> | ||||
| struct is_compatible_object_type_impl < | ||||
|     BasicJsonType, CompatibleObjectType, | ||||
|     enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&& | ||||
|     is_detected<key_type_t, CompatibleObjectType>::value >> | ||||
| { | ||||
|     using object_t = typename BasicJsonType::object_t; | ||||
|  | ||||
|     // macOS's is_constructible does not play well with nonesuch... | ||||
|     static constexpr bool value = | ||||
|         is_constructible<typename object_t::key_type, | ||||
|         typename CompatibleObjectType::key_type>::value && | ||||
|         is_constructible<typename object_t::mapped_type, | ||||
|         typename CompatibleObjectType::mapped_type>::value; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleObjectType> | ||||
| struct is_compatible_object_type | ||||
|     : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleObjectType, | ||||
|          typename = void> | ||||
| struct is_constructible_object_type_impl : std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleObjectType> | ||||
| struct is_constructible_object_type_impl < | ||||
|     BasicJsonType, ConstructibleObjectType, | ||||
|     enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&& | ||||
|     is_detected<key_type_t, ConstructibleObjectType>::value >> | ||||
| { | ||||
|     using object_t = typename BasicJsonType::object_t; | ||||
|  | ||||
|     static constexpr bool value = | ||||
|         (is_default_constructible<ConstructibleObjectType>::value && | ||||
|          (std::is_move_assignable<ConstructibleObjectType>::value || | ||||
|           std::is_copy_assignable<ConstructibleObjectType>::value) && | ||||
|          (is_constructible<typename ConstructibleObjectType::key_type, | ||||
|           typename object_t::key_type>::value && | ||||
|           std::is_same < | ||||
|           typename object_t::mapped_type, | ||||
|           typename ConstructibleObjectType::mapped_type >::value)) || | ||||
|         (has_from_json<BasicJsonType, | ||||
|          typename ConstructibleObjectType::mapped_type>::value || | ||||
|          has_non_default_from_json < | ||||
|          BasicJsonType, | ||||
|          typename ConstructibleObjectType::mapped_type >::value); | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleObjectType> | ||||
| struct is_constructible_object_type | ||||
|     : is_constructible_object_type_impl<BasicJsonType, | ||||
|       ConstructibleObjectType> {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleStringType> | ||||
| struct is_compatible_string_type | ||||
| { | ||||
|     static constexpr auto value = | ||||
|         is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleStringType> | ||||
| struct is_constructible_string_type | ||||
| { | ||||
|     // launder type through decltype() to fix compilation failure on ICPC | ||||
| #ifdef __INTEL_COMPILER | ||||
|     using laundered_type = decltype(std::declval<ConstructibleStringType>()); | ||||
| #else | ||||
|     using laundered_type = ConstructibleStringType; | ||||
| #endif | ||||
|  | ||||
|     static constexpr auto value = | ||||
|         conjunction < | ||||
|         is_constructible<laundered_type, typename BasicJsonType::string_t>, | ||||
|         is_detected_exact<typename BasicJsonType::string_t::value_type, | ||||
|         value_type_t, laundered_type >>::value; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleArrayType, typename = void> | ||||
| struct is_compatible_array_type_impl : std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleArrayType> | ||||
| struct is_compatible_array_type_impl < | ||||
|     BasicJsonType, CompatibleArrayType, | ||||
|     enable_if_t < | ||||
|     is_detected<iterator_t, CompatibleArrayType>::value&& | ||||
|     is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&& | ||||
| // special case for types like std::filesystem::path whose iterator's value_type are themselves | ||||
| // c.f. https://github.com/nlohmann/json/pull/3073 | ||||
|     !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >> | ||||
| { | ||||
|     static constexpr bool value = | ||||
|         is_constructible<BasicJsonType, | ||||
|         range_value_t<CompatibleArrayType>>::value; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleArrayType> | ||||
| struct is_compatible_array_type | ||||
|     : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleArrayType, typename = void> | ||||
| struct is_constructible_array_type_impl : std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleArrayType> | ||||
| struct is_constructible_array_type_impl < | ||||
|     BasicJsonType, ConstructibleArrayType, | ||||
|     enable_if_t<std::is_same<ConstructibleArrayType, | ||||
|     typename BasicJsonType::value_type>::value >> | ||||
|             : std::true_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleArrayType> | ||||
| struct is_constructible_array_type_impl < | ||||
|     BasicJsonType, ConstructibleArrayType, | ||||
|     enable_if_t < !std::is_same<ConstructibleArrayType, | ||||
|     typename BasicJsonType::value_type>::value&& | ||||
|     !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&& | ||||
|     is_default_constructible<ConstructibleArrayType>::value&& | ||||
| (std::is_move_assignable<ConstructibleArrayType>::value || | ||||
|  std::is_copy_assignable<ConstructibleArrayType>::value)&& | ||||
| is_detected<iterator_t, ConstructibleArrayType>::value&& | ||||
| is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&& | ||||
| is_detected<range_value_t, ConstructibleArrayType>::value&& | ||||
| // special case for types like std::filesystem::path whose iterator's value_type are themselves | ||||
| // c.f. https://github.com/nlohmann/json/pull/3073 | ||||
| !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&& | ||||
|         is_complete_type < | ||||
|         detected_t<range_value_t, ConstructibleArrayType >>::value >> | ||||
| { | ||||
|     using value_type = range_value_t<ConstructibleArrayType>; | ||||
|  | ||||
|     static constexpr bool value = | ||||
|         std::is_same<value_type, | ||||
|         typename BasicJsonType::array_t::value_type>::value || | ||||
|         has_from_json<BasicJsonType, | ||||
|         value_type>::value || | ||||
|         has_non_default_from_json < | ||||
|         BasicJsonType, | ||||
|         value_type >::value; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename ConstructibleArrayType> | ||||
| struct is_constructible_array_type | ||||
|     : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {}; | ||||
|  | ||||
| template<typename RealIntegerType, typename CompatibleNumberIntegerType, | ||||
|          typename = void> | ||||
| struct is_compatible_integer_type_impl : std::false_type {}; | ||||
|  | ||||
| template<typename RealIntegerType, typename CompatibleNumberIntegerType> | ||||
| struct is_compatible_integer_type_impl < | ||||
|     RealIntegerType, CompatibleNumberIntegerType, | ||||
|     enable_if_t < std::is_integral<RealIntegerType>::value&& | ||||
|     std::is_integral<CompatibleNumberIntegerType>::value&& | ||||
|     !std::is_same<bool, CompatibleNumberIntegerType>::value >> | ||||
| { | ||||
|     // is there an assert somewhere on overflows? | ||||
|     using RealLimits = std::numeric_limits<RealIntegerType>; | ||||
|     using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>; | ||||
|  | ||||
|     static constexpr auto value = | ||||
|         is_constructible<RealIntegerType, | ||||
|         CompatibleNumberIntegerType>::value && | ||||
|         CompatibleLimits::is_integer && | ||||
|         RealLimits::is_signed == CompatibleLimits::is_signed; | ||||
| }; | ||||
|  | ||||
| template<typename RealIntegerType, typename CompatibleNumberIntegerType> | ||||
| struct is_compatible_integer_type | ||||
|     : is_compatible_integer_type_impl<RealIntegerType, | ||||
|       CompatibleNumberIntegerType> {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleType, typename = void> | ||||
| struct is_compatible_type_impl: std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleType> | ||||
| struct is_compatible_type_impl < | ||||
|     BasicJsonType, CompatibleType, | ||||
|     enable_if_t<is_complete_type<CompatibleType>::value >> | ||||
| { | ||||
|     static constexpr bool value = | ||||
|         has_to_json<BasicJsonType, CompatibleType>::value; | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType, typename CompatibleType> | ||||
| struct is_compatible_type | ||||
|     : is_compatible_type_impl<BasicJsonType, CompatibleType> {}; | ||||
|  | ||||
| template<typename T1, typename T2> | ||||
| struct is_constructible_tuple : std::false_type {}; | ||||
|  | ||||
| template<typename T1, typename... Args> | ||||
| struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {}; | ||||
|  | ||||
| template<typename BasicJsonType, typename T> | ||||
| struct is_json_iterator_of : std::false_type {}; | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {}; | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type | ||||
| {}; | ||||
|  | ||||
| // checks if a given type T is a template specialization of Primary | ||||
| template<template <typename...> class Primary, typename T> | ||||
| struct is_specialization_of : std::false_type {}; | ||||
|  | ||||
| template<template <typename...> class Primary, typename... Args> | ||||
| struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {}; | ||||
|  | ||||
| template<typename T> | ||||
| using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>; | ||||
|  | ||||
| // checks if A and B are comparable using Compare functor | ||||
| template<typename Compare, typename A, typename B, typename = void> | ||||
| struct is_comparable : std::false_type {}; | ||||
|  | ||||
| template<typename Compare, typename A, typename B> | ||||
| struct is_comparable<Compare, A, B, void_t< | ||||
| decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())), | ||||
| decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>())) | ||||
| >> : std::true_type {}; | ||||
|  | ||||
| template<typename T> | ||||
| using detect_is_transparent = typename T::is_transparent; | ||||
|  | ||||
| // type trait to check if KeyType can be used as object key (without a BasicJsonType) | ||||
| // see is_usable_as_basic_json_key_type below | ||||
| template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, | ||||
|          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> | ||||
| using is_usable_as_key_type = typename std::conditional < | ||||
|                               is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value | ||||
|                               && !(ExcludeObjectKeyType && std::is_same<KeyType, | ||||
|                                    ObjectKeyType>::value) | ||||
|                               && (!RequireTransparentComparator | ||||
|                                   || is_detected <detect_is_transparent, Comparator>::value) | ||||
|                               && !is_json_pointer<KeyType>::value, | ||||
|                               std::true_type, | ||||
|                               std::false_type >::type; | ||||
|  | ||||
| // type trait to check if KeyType can be used as object key | ||||
| // true if: | ||||
| //   - KeyType is comparable with BasicJsonType::object_t::key_type | ||||
| //   - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type | ||||
| //   - the comparator is transparent or RequireTransparentComparator is false | ||||
| //   - KeyType is not a JSON iterator or json_pointer | ||||
| template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, | ||||
|          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> | ||||
| using is_usable_as_basic_json_key_type = typename std::conditional < | ||||
|         is_usable_as_key_type<typename BasicJsonType::object_comparator_t, | ||||
|         typename BasicJsonType::object_t::key_type, KeyTypeCVRef, | ||||
|         RequireTransparentComparator, ExcludeObjectKeyType>::value | ||||
|         && !is_json_iterator_of<BasicJsonType, KeyType>::value, | ||||
|         std::true_type, | ||||
|         std::false_type >::type; | ||||
|  | ||||
| template<typename ObjectType, typename KeyType> | ||||
| using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>())); | ||||
|  | ||||
| // type trait to check if object_t has an erase() member functions accepting KeyType | ||||
| template<typename BasicJsonType, typename KeyType> | ||||
| using has_erase_with_key_type = typename std::conditional < | ||||
|                                 is_detected < | ||||
|                                 detect_erase_with_key_type, | ||||
|                                 typename BasicJsonType::object_t, KeyType >::value, | ||||
|                                 std::true_type, | ||||
|                                 std::false_type >::type; | ||||
|  | ||||
| // a naive helper to check if a type is an ordered_map (exploits the fact that | ||||
| // ordered_map inherits capacity() from std::vector) | ||||
| template <typename T> | ||||
| struct is_ordered_map | ||||
| { | ||||
|     using one = char; | ||||
|  | ||||
|     struct two | ||||
|     { | ||||
|         char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | ||||
|     }; | ||||
|  | ||||
|     template <typename C> static one test( decltype(&C::capacity) ) ; | ||||
|     template <typename C> static two test(...); | ||||
|  | ||||
|     enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||||
| }; | ||||
|  | ||||
| // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) | ||||
| template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 > | ||||
| T conditional_static_cast(U value) | ||||
| { | ||||
|     return static_cast<T>(value); | ||||
| } | ||||
|  | ||||
| template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0> | ||||
| T conditional_static_cast(U value) | ||||
| { | ||||
|     return value; | ||||
| } | ||||
|  | ||||
| template<typename... Types> | ||||
| using all_integral = conjunction<std::is_integral<Types>...>; | ||||
|  | ||||
| template<typename... Types> | ||||
| using all_signed = conjunction<std::is_signed<Types>...>; | ||||
|  | ||||
| template<typename... Types> | ||||
| using all_unsigned = conjunction<std::is_unsigned<Types>...>; | ||||
|  | ||||
| // there's a disjunction trait in another PR; replace when merged | ||||
| template<typename... Types> | ||||
| using same_sign = std::integral_constant < bool, | ||||
|       all_signed<Types...>::value || all_unsigned<Types...>::value >; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| using never_out_of_range = std::integral_constant < bool, | ||||
|       (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) | ||||
|       || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >; | ||||
|  | ||||
| template<typename OfType, typename T, | ||||
|          bool OfTypeSigned = std::is_signed<OfType>::value, | ||||
|          bool TSigned = std::is_signed<T>::value> | ||||
| struct value_in_range_of_impl2; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| struct value_in_range_of_impl2<OfType, T, false, false> | ||||
| { | ||||
|     static constexpr bool test(T val) | ||||
|     { | ||||
|         using CommonType = typename std::common_type<OfType, T>::type; | ||||
|         return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| struct value_in_range_of_impl2<OfType, T, true, false> | ||||
| { | ||||
|     static constexpr bool test(T val) | ||||
|     { | ||||
|         using CommonType = typename std::common_type<OfType, T>::type; | ||||
|         return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| struct value_in_range_of_impl2<OfType, T, false, true> | ||||
| { | ||||
|     static constexpr bool test(T val) | ||||
|     { | ||||
|         using CommonType = typename std::common_type<OfType, T>::type; | ||||
|         return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| struct value_in_range_of_impl2<OfType, T, true, true> | ||||
| { | ||||
|     static constexpr bool test(T val) | ||||
|     { | ||||
|         using CommonType = typename std::common_type<OfType, T>::type; | ||||
|         return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)()) | ||||
|                && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename OfType, typename T, | ||||
|          bool NeverOutOfRange = never_out_of_range<OfType, T>::value, | ||||
|          typename = detail::enable_if_t<all_integral<OfType, T>::value>> | ||||
| struct value_in_range_of_impl1; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| struct value_in_range_of_impl1<OfType, T, false> | ||||
| { | ||||
|     static constexpr bool test(T val) | ||||
|     { | ||||
|         return value_in_range_of_impl2<OfType, T>::test(val); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| struct value_in_range_of_impl1<OfType, T, true> | ||||
| { | ||||
|     static constexpr bool test(T /*val*/) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<typename OfType, typename T> | ||||
| inline constexpr bool value_in_range_of(T val) | ||||
| { | ||||
|     return value_in_range_of_impl1<OfType, T>::test(val); | ||||
| } | ||||
|  | ||||
| template<bool Value> | ||||
| using bool_constant = std::integral_constant<bool, Value>; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // is_c_string | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| namespace impl | ||||
| { | ||||
|  | ||||
| template<typename T> | ||||
| inline constexpr bool is_c_string() | ||||
| { | ||||
|     using TUnExt = typename std::remove_extent<T>::type; | ||||
|     using TUnCVExt = typename std::remove_cv<TUnExt>::type; | ||||
|     using TUnPtr = typename std::remove_pointer<T>::type; | ||||
|     using TUnCVPtr = typename std::remove_cv<TUnPtr>::type; | ||||
|     return | ||||
|         (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) | ||||
|         || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value); | ||||
| } | ||||
|  | ||||
| }  // namespace impl | ||||
|  | ||||
| // checks whether T is a [cv] char */[cv] char[] C string | ||||
| template<typename T> | ||||
| struct is_c_string : bool_constant<impl::is_c_string<T>()> {}; | ||||
|  | ||||
| template<typename T> | ||||
| using is_c_string_uncvref = is_c_string<uncvref_t<T>>; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // is_transparent | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| namespace impl | ||||
| { | ||||
|  | ||||
| template<typename T> | ||||
| inline constexpr bool is_transparent() | ||||
| { | ||||
|     return is_detected<detect_is_transparent, T>::value; | ||||
| } | ||||
|  | ||||
| }  // namespace impl | ||||
|  | ||||
| // checks whether T has a member named is_transparent | ||||
| template<typename T> | ||||
| struct is_transparent : bool_constant<impl::is_transparent<T>()> {}; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,24 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<typename ...Ts> struct make_void | ||||
| { | ||||
|     using type = void; | ||||
| }; | ||||
| template<typename ...Ts> using void_t = typename make_void<Ts...>::type; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,147 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <algorithm> // copy | ||||
| #include <cstddef> // size_t | ||||
| #include <iterator> // back_inserter | ||||
| #include <memory> // shared_ptr, make_shared | ||||
| #include <string> // basic_string | ||||
| #include <vector> // vector | ||||
|  | ||||
| #ifndef JSON_NO_IO | ||||
|     #include <ios>      // streamsize | ||||
|     #include <ostream>  // basic_ostream | ||||
| #endif  // JSON_NO_IO | ||||
|  | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /// abstract output adapter interface | ||||
| template<typename CharType> struct output_adapter_protocol | ||||
| { | ||||
|     virtual void write_character(CharType c) = 0; | ||||
|     virtual void write_characters(const CharType* s, std::size_t length) = 0; | ||||
|     virtual ~output_adapter_protocol() = default; | ||||
|  | ||||
|     output_adapter_protocol() = default; | ||||
|     output_adapter_protocol(const output_adapter_protocol&) = default; | ||||
|     output_adapter_protocol(output_adapter_protocol&&) noexcept = default; | ||||
|     output_adapter_protocol& operator=(const output_adapter_protocol&) = default; | ||||
|     output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; | ||||
| }; | ||||
|  | ||||
| /// a type to simplify interfaces | ||||
| template<typename CharType> | ||||
| using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; | ||||
|  | ||||
| /// output adapter for byte vectors | ||||
| template<typename CharType, typename AllocatorType = std::allocator<CharType>> | ||||
| class output_vector_adapter : public output_adapter_protocol<CharType> | ||||
| { | ||||
|   public: | ||||
|     explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept | ||||
|         : v(vec) | ||||
|     {} | ||||
|  | ||||
|     void write_character(CharType c) override | ||||
|     { | ||||
|         v.push_back(c); | ||||
|     } | ||||
|  | ||||
|     JSON_HEDLEY_NON_NULL(2) | ||||
|     void write_characters(const CharType* s, std::size_t length) override | ||||
|     { | ||||
|         v.insert(v.end(), s, s + length); | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     std::vector<CharType, AllocatorType>& v; | ||||
| }; | ||||
|  | ||||
| #ifndef JSON_NO_IO | ||||
| /// output adapter for output streams | ||||
| template<typename CharType> | ||||
| class output_stream_adapter : public output_adapter_protocol<CharType> | ||||
| { | ||||
|   public: | ||||
|     explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept | ||||
|         : stream(s) | ||||
|     {} | ||||
|  | ||||
|     void write_character(CharType c) override | ||||
|     { | ||||
|         stream.put(c); | ||||
|     } | ||||
|  | ||||
|     JSON_HEDLEY_NON_NULL(2) | ||||
|     void write_characters(const CharType* s, std::size_t length) override | ||||
|     { | ||||
|         stream.write(s, static_cast<std::streamsize>(length)); | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     std::basic_ostream<CharType>& stream; | ||||
| }; | ||||
| #endif  // JSON_NO_IO | ||||
|  | ||||
| /// output adapter for basic_string | ||||
| template<typename CharType, typename StringType = std::basic_string<CharType>> | ||||
| class output_string_adapter : public output_adapter_protocol<CharType> | ||||
| { | ||||
|   public: | ||||
|     explicit output_string_adapter(StringType& s) noexcept | ||||
|         : str(s) | ||||
|     {} | ||||
|  | ||||
|     void write_character(CharType c) override | ||||
|     { | ||||
|         str.push_back(c); | ||||
|     } | ||||
|  | ||||
|     JSON_HEDLEY_NON_NULL(2) | ||||
|     void write_characters(const CharType* s, std::size_t length) override | ||||
|     { | ||||
|         str.append(s, length); | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     StringType& str; | ||||
| }; | ||||
|  | ||||
| template<typename CharType, typename StringType = std::basic_string<CharType>> | ||||
| class output_adapter | ||||
| { | ||||
|   public: | ||||
|     template<typename AllocatorType = std::allocator<CharType>> | ||||
|     output_adapter(std::vector<CharType, AllocatorType>& vec) | ||||
|         : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {} | ||||
|  | ||||
| #ifndef JSON_NO_IO | ||||
|     output_adapter(std::basic_ostream<CharType>& s) | ||||
|         : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {} | ||||
| #endif  // JSON_NO_IO | ||||
|  | ||||
|     output_adapter(StringType& s) | ||||
|         : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {} | ||||
|  | ||||
|     operator output_adapter_t<CharType>() | ||||
|     { | ||||
|         return oa; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     output_adapter_t<CharType> oa = nullptr; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,988 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de> | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <algorithm> // reverse, remove, fill, find, none_of | ||||
| #include <array> // array | ||||
| #include <clocale> // localeconv, lconv | ||||
| #include <cmath> // labs, isfinite, isnan, signbit | ||||
| #include <cstddef> // size_t, ptrdiff_t | ||||
| #include <cstdint> // uint8_t | ||||
| #include <cstdio> // snprintf | ||||
| #include <limits> // numeric_limits | ||||
| #include <string> // string, char_traits | ||||
| #include <iomanip> // setfill, setw | ||||
| #include <type_traits> // is_same | ||||
| #include <utility> // move | ||||
|  | ||||
| #include <nlohmann/detail/conversions/to_chars.hpp> | ||||
| #include <nlohmann/detail/exceptions.hpp> | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
| #include <nlohmann/detail/output/binary_writer.hpp> | ||||
| #include <nlohmann/detail/output/output_adapters.hpp> | ||||
| #include <nlohmann/detail/string_concat.hpp> | ||||
| #include <nlohmann/detail/value_t.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /////////////////// | ||||
| // serialization // | ||||
| /////////////////// | ||||
|  | ||||
| /// how to treat decoding errors | ||||
| enum class error_handler_t | ||||
| { | ||||
|     strict,  ///< throw a type_error exception in case of invalid UTF-8 | ||||
|     replace, ///< replace invalid UTF-8 sequences with U+FFFD | ||||
|     ignore   ///< ignore invalid UTF-8 sequences | ||||
| }; | ||||
|  | ||||
| template<typename BasicJsonType> | ||||
| class serializer | ||||
| { | ||||
|     using string_t = typename BasicJsonType::string_t; | ||||
|     using number_float_t = typename BasicJsonType::number_float_t; | ||||
|     using number_integer_t = typename BasicJsonType::number_integer_t; | ||||
|     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||||
|     using binary_char_t = typename BasicJsonType::binary_t::value_type; | ||||
|     static constexpr std::uint8_t UTF8_ACCEPT = 0; | ||||
|     static constexpr std::uint8_t UTF8_REJECT = 1; | ||||
|  | ||||
|   public: | ||||
|     /*! | ||||
|     @param[in] s  output stream to serialize to | ||||
|     @param[in] ichar  indentation character to use | ||||
|     @param[in] error_handler_  how to react on decoding errors | ||||
|     */ | ||||
|     serializer(output_adapter_t<char> s, const char ichar, | ||||
|                error_handler_t error_handler_ = error_handler_t::strict) | ||||
|         : o(std::move(s)) | ||||
|         , loc(std::localeconv()) | ||||
|         , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep))) | ||||
|         , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point))) | ||||
|         , indent_char(ichar) | ||||
|         , indent_string(512, indent_char) | ||||
|         , error_handler(error_handler_) | ||||
|     {} | ||||
|  | ||||
|     // delete because of pointer members | ||||
|     serializer(const serializer&) = delete; | ||||
|     serializer& operator=(const serializer&) = delete; | ||||
|     serializer(serializer&&) = delete; | ||||
|     serializer& operator=(serializer&&) = delete; | ||||
|     ~serializer() = default; | ||||
|  | ||||
|     /*! | ||||
|     @brief internal implementation of the serialization function | ||||
|  | ||||
|     This function is called by the public member function dump and organizes | ||||
|     the serialization internally. The indentation level is propagated as | ||||
|     additional parameter. In case of arrays and objects, the function is | ||||
|     called recursively. | ||||
|  | ||||
|     - strings and object keys are escaped using `escape_string()` | ||||
|     - integer numbers are converted implicitly via `operator<<` | ||||
|     - floating-point numbers are converted to a string using `"%g"` format | ||||
|     - binary values are serialized as objects containing the subtype and the | ||||
|       byte array | ||||
|  | ||||
|     @param[in] val               value to serialize | ||||
|     @param[in] pretty_print      whether the output shall be pretty-printed | ||||
|     @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters | ||||
|     in the output are escaped with `\uXXXX` sequences, and the result consists | ||||
|     of ASCII characters only. | ||||
|     @param[in] indent_step       the indent level | ||||
|     @param[in] current_indent    the current indent level (only used internally) | ||||
|     */ | ||||
|     void dump(const BasicJsonType& val, | ||||
|               const bool pretty_print, | ||||
|               const bool ensure_ascii, | ||||
|               const unsigned int indent_step, | ||||
|               const unsigned int current_indent = 0) | ||||
|     { | ||||
|         switch (val.m_data.m_type) | ||||
|         { | ||||
|             case value_t::object: | ||||
|             { | ||||
|                 if (val.m_data.m_value.object->empty()) | ||||
|                 { | ||||
|                     o->write_characters("{}", 2); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (pretty_print) | ||||
|                 { | ||||
|                     o->write_characters("{\n", 2); | ||||
|  | ||||
|                     // variable to hold indentation for recursive calls | ||||
|                     const auto new_indent = current_indent + indent_step; | ||||
|                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) | ||||
|                     { | ||||
|                         indent_string.resize(indent_string.size() * 2, ' '); | ||||
|                     } | ||||
|  | ||||
|                     // first n-1 elements | ||||
|                     auto i = val.m_data.m_value.object->cbegin(); | ||||
|                     for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) | ||||
|                     { | ||||
|                         o->write_characters(indent_string.c_str(), new_indent); | ||||
|                         o->write_character('\"'); | ||||
|                         dump_escaped(i->first, ensure_ascii); | ||||
|                         o->write_characters("\": ", 3); | ||||
|                         dump(i->second, true, ensure_ascii, indent_step, new_indent); | ||||
|                         o->write_characters(",\n", 2); | ||||
|                     } | ||||
|  | ||||
|                     // last element | ||||
|                     JSON_ASSERT(i != val.m_data.m_value.object->cend()); | ||||
|                     JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); | ||||
|                     o->write_characters(indent_string.c_str(), new_indent); | ||||
|                     o->write_character('\"'); | ||||
|                     dump_escaped(i->first, ensure_ascii); | ||||
|                     o->write_characters("\": ", 3); | ||||
|                     dump(i->second, true, ensure_ascii, indent_step, new_indent); | ||||
|  | ||||
|                     o->write_character('\n'); | ||||
|                     o->write_characters(indent_string.c_str(), current_indent); | ||||
|                     o->write_character('}'); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     o->write_character('{'); | ||||
|  | ||||
|                     // first n-1 elements | ||||
|                     auto i = val.m_data.m_value.object->cbegin(); | ||||
|                     for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) | ||||
|                     { | ||||
|                         o->write_character('\"'); | ||||
|                         dump_escaped(i->first, ensure_ascii); | ||||
|                         o->write_characters("\":", 2); | ||||
|                         dump(i->second, false, ensure_ascii, indent_step, current_indent); | ||||
|                         o->write_character(','); | ||||
|                     } | ||||
|  | ||||
|                     // last element | ||||
|                     JSON_ASSERT(i != val.m_data.m_value.object->cend()); | ||||
|                     JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); | ||||
|                     o->write_character('\"'); | ||||
|                     dump_escaped(i->first, ensure_ascii); | ||||
|                     o->write_characters("\":", 2); | ||||
|                     dump(i->second, false, ensure_ascii, indent_step, current_indent); | ||||
|  | ||||
|                     o->write_character('}'); | ||||
|                 } | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::array: | ||||
|             { | ||||
|                 if (val.m_data.m_value.array->empty()) | ||||
|                 { | ||||
|                     o->write_characters("[]", 2); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (pretty_print) | ||||
|                 { | ||||
|                     o->write_characters("[\n", 2); | ||||
|  | ||||
|                     // variable to hold indentation for recursive calls | ||||
|                     const auto new_indent = current_indent + indent_step; | ||||
|                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) | ||||
|                     { | ||||
|                         indent_string.resize(indent_string.size() * 2, ' '); | ||||
|                     } | ||||
|  | ||||
|                     // first n-1 elements | ||||
|                     for (auto i = val.m_data.m_value.array->cbegin(); | ||||
|                             i != val.m_data.m_value.array->cend() - 1; ++i) | ||||
|                     { | ||||
|                         o->write_characters(indent_string.c_str(), new_indent); | ||||
|                         dump(*i, true, ensure_ascii, indent_step, new_indent); | ||||
|                         o->write_characters(",\n", 2); | ||||
|                     } | ||||
|  | ||||
|                     // last element | ||||
|                     JSON_ASSERT(!val.m_data.m_value.array->empty()); | ||||
|                     o->write_characters(indent_string.c_str(), new_indent); | ||||
|                     dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); | ||||
|  | ||||
|                     o->write_character('\n'); | ||||
|                     o->write_characters(indent_string.c_str(), current_indent); | ||||
|                     o->write_character(']'); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     o->write_character('['); | ||||
|  | ||||
|                     // first n-1 elements | ||||
|                     for (auto i = val.m_data.m_value.array->cbegin(); | ||||
|                             i != val.m_data.m_value.array->cend() - 1; ++i) | ||||
|                     { | ||||
|                         dump(*i, false, ensure_ascii, indent_step, current_indent); | ||||
|                         o->write_character(','); | ||||
|                     } | ||||
|  | ||||
|                     // last element | ||||
|                     JSON_ASSERT(!val.m_data.m_value.array->empty()); | ||||
|                     dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); | ||||
|  | ||||
|                     o->write_character(']'); | ||||
|                 } | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::string: | ||||
|             { | ||||
|                 o->write_character('\"'); | ||||
|                 dump_escaped(*val.m_data.m_value.string, ensure_ascii); | ||||
|                 o->write_character('\"'); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::binary: | ||||
|             { | ||||
|                 if (pretty_print) | ||||
|                 { | ||||
|                     o->write_characters("{\n", 2); | ||||
|  | ||||
|                     // variable to hold indentation for recursive calls | ||||
|                     const auto new_indent = current_indent + indent_step; | ||||
|                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) | ||||
|                     { | ||||
|                         indent_string.resize(indent_string.size() * 2, ' '); | ||||
|                     } | ||||
|  | ||||
|                     o->write_characters(indent_string.c_str(), new_indent); | ||||
|  | ||||
|                     o->write_characters("\"bytes\": [", 10); | ||||
|  | ||||
|                     if (!val.m_data.m_value.binary->empty()) | ||||
|                     { | ||||
|                         for (auto i = val.m_data.m_value.binary->cbegin(); | ||||
|                                 i != val.m_data.m_value.binary->cend() - 1; ++i) | ||||
|                         { | ||||
|                             dump_integer(*i); | ||||
|                             o->write_characters(", ", 2); | ||||
|                         } | ||||
|                         dump_integer(val.m_data.m_value.binary->back()); | ||||
|                     } | ||||
|  | ||||
|                     o->write_characters("],\n", 3); | ||||
|                     o->write_characters(indent_string.c_str(), new_indent); | ||||
|  | ||||
|                     o->write_characters("\"subtype\": ", 11); | ||||
|                     if (val.m_data.m_value.binary->has_subtype()) | ||||
|                     { | ||||
|                         dump_integer(val.m_data.m_value.binary->subtype()); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         o->write_characters("null", 4); | ||||
|                     } | ||||
|                     o->write_character('\n'); | ||||
|                     o->write_characters(indent_string.c_str(), current_indent); | ||||
|                     o->write_character('}'); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     o->write_characters("{\"bytes\":[", 10); | ||||
|  | ||||
|                     if (!val.m_data.m_value.binary->empty()) | ||||
|                     { | ||||
|                         for (auto i = val.m_data.m_value.binary->cbegin(); | ||||
|                                 i != val.m_data.m_value.binary->cend() - 1; ++i) | ||||
|                         { | ||||
|                             dump_integer(*i); | ||||
|                             o->write_character(','); | ||||
|                         } | ||||
|                         dump_integer(val.m_data.m_value.binary->back()); | ||||
|                     } | ||||
|  | ||||
|                     o->write_characters("],\"subtype\":", 12); | ||||
|                     if (val.m_data.m_value.binary->has_subtype()) | ||||
|                     { | ||||
|                         dump_integer(val.m_data.m_value.binary->subtype()); | ||||
|                         o->write_character('}'); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         o->write_characters("null}", 5); | ||||
|                     } | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::boolean: | ||||
|             { | ||||
|                 if (val.m_data.m_value.boolean) | ||||
|                 { | ||||
|                     o->write_characters("true", 4); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     o->write_characters("false", 5); | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::number_integer: | ||||
|             { | ||||
|                 dump_integer(val.m_data.m_value.number_integer); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::number_unsigned: | ||||
|             { | ||||
|                 dump_integer(val.m_data.m_value.number_unsigned); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::number_float: | ||||
|             { | ||||
|                 dump_float(val.m_data.m_value.number_float); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::discarded: | ||||
|             { | ||||
|                 o->write_characters("<discarded>", 11); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             case value_t::null: | ||||
|             { | ||||
|                 o->write_characters("null", 4); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             default:            // LCOV_EXCL_LINE | ||||
|                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   JSON_PRIVATE_UNLESS_TESTED: | ||||
|     /*! | ||||
|     @brief dump escaped string | ||||
|  | ||||
|     Escape a string by replacing certain special characters by a sequence of an | ||||
|     escape character (backslash) and another character and other control | ||||
|     characters by a sequence of "\u" followed by a four-digit hex | ||||
|     representation. The escaped string is written to output stream @a o. | ||||
|  | ||||
|     @param[in] s  the string to escape | ||||
|     @param[in] ensure_ascii  whether to escape non-ASCII characters with | ||||
|                              \uXXXX sequences | ||||
|  | ||||
|     @complexity Linear in the length of string @a s. | ||||
|     */ | ||||
|     void dump_escaped(const string_t& s, const bool ensure_ascii) | ||||
|     { | ||||
|         std::uint32_t codepoint{}; | ||||
|         std::uint8_t state = UTF8_ACCEPT; | ||||
|         std::size_t bytes = 0;  // number of bytes written to string_buffer | ||||
|  | ||||
|         // number of bytes written at the point of the last valid byte | ||||
|         std::size_t bytes_after_last_accept = 0; | ||||
|         std::size_t undumped_chars = 0; | ||||
|  | ||||
|         for (std::size_t i = 0; i < s.size(); ++i) | ||||
|         { | ||||
|             const auto byte = static_cast<std::uint8_t>(s[i]); | ||||
|  | ||||
|             switch (decode(state, codepoint, byte)) | ||||
|             { | ||||
|                 case UTF8_ACCEPT:  // decode found a new code point | ||||
|                 { | ||||
|                     switch (codepoint) | ||||
|                     { | ||||
|                         case 0x08: // backspace | ||||
|                         { | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             string_buffer[bytes++] = 'b'; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         case 0x09: // horizontal tab | ||||
|                         { | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             string_buffer[bytes++] = 't'; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         case 0x0A: // newline | ||||
|                         { | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             string_buffer[bytes++] = 'n'; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         case 0x0C: // formfeed | ||||
|                         { | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             string_buffer[bytes++] = 'f'; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         case 0x0D: // carriage return | ||||
|                         { | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             string_buffer[bytes++] = 'r'; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         case 0x22: // quotation mark | ||||
|                         { | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             string_buffer[bytes++] = '\"'; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         case 0x5C: // reverse solidus | ||||
|                         { | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             string_buffer[bytes++] = '\\'; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         default: | ||||
|                         { | ||||
|                             // escape control characters (0x00..0x1F) or, if | ||||
|                             // ensure_ascii parameter is used, non-ASCII characters | ||||
|                             if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) | ||||
|                             { | ||||
|                                 if (codepoint <= 0xFFFF) | ||||
|                                 { | ||||
|                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||||
|                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", | ||||
|                                                                       static_cast<std::uint16_t>(codepoint))); | ||||
|                                     bytes += 6; | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||||
|                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", | ||||
|                                                                       static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)), | ||||
|                                                                       static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)))); | ||||
|                                     bytes += 12; | ||||
|                                 } | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 // copy byte to buffer (all previous bytes | ||||
|                                 // been copied have in default case above) | ||||
|                                 string_buffer[bytes++] = s[i]; | ||||
|                             } | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     // write buffer and reset index; there must be 13 bytes | ||||
|                     // left, as this is the maximal number of bytes to be | ||||
|                     // written ("\uxxxx\uxxxx\0") for one code point | ||||
|                     if (string_buffer.size() - bytes < 13) | ||||
|                     { | ||||
|                         o->write_characters(string_buffer.data(), bytes); | ||||
|                         bytes = 0; | ||||
|                     } | ||||
|  | ||||
|                     // remember the byte position of this accept | ||||
|                     bytes_after_last_accept = bytes; | ||||
|                     undumped_chars = 0; | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case UTF8_REJECT:  // decode found invalid UTF-8 byte | ||||
|                 { | ||||
|                     switch (error_handler) | ||||
|                     { | ||||
|                         case error_handler_t::strict: | ||||
|                         { | ||||
|                             JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr)); | ||||
|                         } | ||||
|  | ||||
|                         case error_handler_t::ignore: | ||||
|                         case error_handler_t::replace: | ||||
|                         { | ||||
|                             // in case we saw this character the first time, we | ||||
|                             // would like to read it again, because the byte | ||||
|                             // may be OK for itself, but just not OK for the | ||||
|                             // previous sequence | ||||
|                             if (undumped_chars > 0) | ||||
|                             { | ||||
|                                 --i; | ||||
|                             } | ||||
|  | ||||
|                             // reset length buffer to the last accepted index; | ||||
|                             // thus removing/ignoring the invalid characters | ||||
|                             bytes = bytes_after_last_accept; | ||||
|  | ||||
|                             if (error_handler == error_handler_t::replace) | ||||
|                             { | ||||
|                                 // add a replacement character | ||||
|                                 if (ensure_ascii) | ||||
|                                 { | ||||
|                                     string_buffer[bytes++] = '\\'; | ||||
|                                     string_buffer[bytes++] = 'u'; | ||||
|                                     string_buffer[bytes++] = 'f'; | ||||
|                                     string_buffer[bytes++] = 'f'; | ||||
|                                     string_buffer[bytes++] = 'f'; | ||||
|                                     string_buffer[bytes++] = 'd'; | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF'); | ||||
|                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF'); | ||||
|                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD'); | ||||
|                                 } | ||||
|  | ||||
|                                 // write buffer and reset index; there must be 13 bytes | ||||
|                                 // left, as this is the maximal number of bytes to be | ||||
|                                 // written ("\uxxxx\uxxxx\0") for one code point | ||||
|                                 if (string_buffer.size() - bytes < 13) | ||||
|                                 { | ||||
|                                     o->write_characters(string_buffer.data(), bytes); | ||||
|                                     bytes = 0; | ||||
|                                 } | ||||
|  | ||||
|                                 bytes_after_last_accept = bytes; | ||||
|                             } | ||||
|  | ||||
|                             undumped_chars = 0; | ||||
|  | ||||
|                             // continue processing the string | ||||
|                             state = UTF8_ACCEPT; | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         default:            // LCOV_EXCL_LINE | ||||
|                             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 default:  // decode found yet incomplete multi-byte code point | ||||
|                 { | ||||
|                     if (!ensure_ascii) | ||||
|                     { | ||||
|                         // code point will not be escaped - copy byte to buffer | ||||
|                         string_buffer[bytes++] = s[i]; | ||||
|                     } | ||||
|                     ++undumped_chars; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // we finished processing the string | ||||
|         if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) | ||||
|         { | ||||
|             // write buffer | ||||
|             if (bytes > 0) | ||||
|             { | ||||
|                 o->write_characters(string_buffer.data(), bytes); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // we finish reading, but do not accept: string was incomplete | ||||
|             switch (error_handler) | ||||
|             { | ||||
|                 case error_handler_t::strict: | ||||
|                 { | ||||
|                     JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr)); | ||||
|                 } | ||||
|  | ||||
|                 case error_handler_t::ignore: | ||||
|                 { | ||||
|                     // write all accepted bytes | ||||
|                     o->write_characters(string_buffer.data(), bytes_after_last_accept); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case error_handler_t::replace: | ||||
|                 { | ||||
|                     // write all accepted bytes | ||||
|                     o->write_characters(string_buffer.data(), bytes_after_last_accept); | ||||
|                     // add a replacement character | ||||
|                     if (ensure_ascii) | ||||
|                     { | ||||
|                         o->write_characters("\\ufffd", 6); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         o->write_characters("\xEF\xBF\xBD", 3); | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 default:            // LCOV_EXCL_LINE | ||||
|                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /*! | ||||
|     @brief count digits | ||||
|  | ||||
|     Count the number of decimal (base 10) digits for an input unsigned integer. | ||||
|  | ||||
|     @param[in] x  unsigned integer number to count its digits | ||||
|     @return    number of decimal digits | ||||
|     */ | ||||
|     inline unsigned int count_digits(number_unsigned_t x) noexcept | ||||
|     { | ||||
|         unsigned int n_digits = 1; | ||||
|         for (;;) | ||||
|         { | ||||
|             if (x < 10) | ||||
|             { | ||||
|                 return n_digits; | ||||
|             } | ||||
|             if (x < 100) | ||||
|             { | ||||
|                 return n_digits + 1; | ||||
|             } | ||||
|             if (x < 1000) | ||||
|             { | ||||
|                 return n_digits + 2; | ||||
|             } | ||||
|             if (x < 10000) | ||||
|             { | ||||
|                 return n_digits + 3; | ||||
|             } | ||||
|             x = x / 10000u; | ||||
|             n_digits += 4; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|      * @brief convert a byte to a uppercase hex representation | ||||
|      * @param[in] byte byte to represent | ||||
|      * @return representation ("00".."FF") | ||||
|      */ | ||||
|     static std::string hex_bytes(std::uint8_t byte) | ||||
|     { | ||||
|         std::string result = "FF"; | ||||
|         constexpr const char* nibble_to_hex = "0123456789ABCDEF"; | ||||
|         result[0] = nibble_to_hex[byte / 16]; | ||||
|         result[1] = nibble_to_hex[byte % 16]; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     // templates to avoid warnings about useless casts | ||||
|     template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0> | ||||
|     bool is_negative_number(NumberType x) | ||||
|     { | ||||
|         return x < 0; | ||||
|     } | ||||
|  | ||||
|     template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 > | ||||
|     bool is_negative_number(NumberType /*unused*/) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief dump an integer | ||||
|  | ||||
|     Dump a given integer to output stream @a o. Works internally with | ||||
|     @a number_buffer. | ||||
|  | ||||
|     @param[in] x  integer number (signed or unsigned) to dump | ||||
|     @tparam NumberType either @a number_integer_t or @a number_unsigned_t | ||||
|     */ | ||||
|     template < typename NumberType, detail::enable_if_t < | ||||
|                    std::is_integral<NumberType>::value || | ||||
|                    std::is_same<NumberType, number_unsigned_t>::value || | ||||
|                    std::is_same<NumberType, number_integer_t>::value || | ||||
|                    std::is_same<NumberType, binary_char_t>::value, | ||||
|                    int > = 0 > | ||||
|     void dump_integer(NumberType x) | ||||
|     { | ||||
|         static constexpr std::array<std::array<char, 2>, 100> digits_to_99 | ||||
|         { | ||||
|             { | ||||
|                 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, | ||||
|                 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, | ||||
|                 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, | ||||
|                 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, | ||||
|                 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, | ||||
|                 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, | ||||
|                 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, | ||||
|                 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, | ||||
|                 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, | ||||
|                 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         // special case for "0" | ||||
|         if (x == 0) | ||||
|         { | ||||
|             o->write_character('0'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // use a pointer to fill the buffer | ||||
|         auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||||
|  | ||||
|         number_unsigned_t abs_value; | ||||
|  | ||||
|         unsigned int n_chars{}; | ||||
|  | ||||
|         if (is_negative_number(x)) | ||||
|         { | ||||
|             *buffer_ptr = '-'; | ||||
|             abs_value = remove_sign(static_cast<number_integer_t>(x)); | ||||
|  | ||||
|             // account one more byte for the minus sign | ||||
|             n_chars = 1 + count_digits(abs_value); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             abs_value = static_cast<number_unsigned_t>(x); | ||||
|             n_chars = count_digits(abs_value); | ||||
|         } | ||||
|  | ||||
|         // spare 1 byte for '\0' | ||||
|         JSON_ASSERT(n_chars < number_buffer.size() - 1); | ||||
|  | ||||
|         // jump to the end to generate the string from backward, | ||||
|         // so we later avoid reversing the result | ||||
|         buffer_ptr += n_chars; | ||||
|  | ||||
|         // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu | ||||
|         // See: https://www.youtube.com/watch?v=o4-CwDo2zpg | ||||
|         while (abs_value >= 100) | ||||
|         { | ||||
|             const auto digits_index = static_cast<unsigned>((abs_value % 100)); | ||||
|             abs_value /= 100; | ||||
|             *(--buffer_ptr) = digits_to_99[digits_index][1]; | ||||
|             *(--buffer_ptr) = digits_to_99[digits_index][0]; | ||||
|         } | ||||
|  | ||||
|         if (abs_value >= 10) | ||||
|         { | ||||
|             const auto digits_index = static_cast<unsigned>(abs_value); | ||||
|             *(--buffer_ptr) = digits_to_99[digits_index][1]; | ||||
|             *(--buffer_ptr) = digits_to_99[digits_index][0]; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             *(--buffer_ptr) = static_cast<char>('0' + abs_value); | ||||
|         } | ||||
|  | ||||
|         o->write_characters(number_buffer.data(), n_chars); | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief dump a floating-point number | ||||
|  | ||||
|     Dump a given floating-point number to output stream @a o. Works internally | ||||
|     with @a number_buffer. | ||||
|  | ||||
|     @param[in] x  floating-point number to dump | ||||
|     */ | ||||
|     void dump_float(number_float_t x) | ||||
|     { | ||||
|         // NaN / inf | ||||
|         if (!std::isfinite(x)) | ||||
|         { | ||||
|             o->write_characters("null", 4); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // If number_float_t is an IEEE-754 single or double precision number, | ||||
|         // use the Grisu2 algorithm to produce short numbers which are | ||||
|         // guaranteed to round-trip, using strtof and strtod, resp. | ||||
|         // | ||||
|         // NB: The test below works if <long double> == <double>. | ||||
|         static constexpr bool is_ieee_single_or_double | ||||
|             = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) || | ||||
|               (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024); | ||||
|  | ||||
|         dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>()); | ||||
|     } | ||||
|  | ||||
|     void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) | ||||
|     { | ||||
|         auto* begin = number_buffer.data(); | ||||
|         auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); | ||||
|  | ||||
|         o->write_characters(begin, static_cast<size_t>(end - begin)); | ||||
|     } | ||||
|  | ||||
|     void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) | ||||
|     { | ||||
|         // get number of digits for a float -> text -> float round-trip | ||||
|         static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; | ||||
|  | ||||
|         // the actual conversion | ||||
|         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||||
|         std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); | ||||
|  | ||||
|         // negative value indicates an error | ||||
|         JSON_ASSERT(len > 0); | ||||
|         // check if buffer was large enough | ||||
|         JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size()); | ||||
|  | ||||
|         // erase thousands separator | ||||
|         if (thousands_sep != '\0') | ||||
|         { | ||||
|             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 | ||||
|             const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); | ||||
|             std::fill(end, number_buffer.end(), '\0'); | ||||
|             JSON_ASSERT((end - number_buffer.begin()) <= len); | ||||
|             len = (end - number_buffer.begin()); | ||||
|         } | ||||
|  | ||||
|         // convert decimal point to '.' | ||||
|         if (decimal_point != '\0' && decimal_point != '.') | ||||
|         { | ||||
|             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 | ||||
|             const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); | ||||
|             if (dec_pos != number_buffer.end()) | ||||
|             { | ||||
|                 *dec_pos = '.'; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         o->write_characters(number_buffer.data(), static_cast<std::size_t>(len)); | ||||
|  | ||||
|         // determine if we need to append ".0" | ||||
|         const bool value_is_int_like = | ||||
|             std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, | ||||
|                          [](char c) | ||||
|         { | ||||
|             return c == '.' || c == 'e'; | ||||
|         }); | ||||
|  | ||||
|         if (value_is_int_like) | ||||
|         { | ||||
|             o->write_characters(".0", 2); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|     @brief check whether a string is UTF-8 encoded | ||||
|  | ||||
|     The function checks each byte of a string whether it is UTF-8 encoded. The | ||||
|     result of the check is stored in the @a state parameter. The function must | ||||
|     be called initially with state 0 (accept). State 1 means the string must | ||||
|     be rejected, because the current byte is not allowed. If the string is | ||||
|     completely processed, but the state is non-zero, the string ended | ||||
|     prematurely; that is, the last byte indicated more bytes should have | ||||
|     followed. | ||||
|  | ||||
|     @param[in,out] state  the state of the decoding | ||||
|     @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT) | ||||
|     @param[in] byte       next byte to decode | ||||
|     @return               new state | ||||
|  | ||||
|     @note The function has been edited: a std::array is used. | ||||
|  | ||||
|     @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> | ||||
|     @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ | ||||
|     */ | ||||
|     static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept | ||||
|     { | ||||
|         static const std::array<std::uint8_t, 400> utf8d = | ||||
|         { | ||||
|             { | ||||
|                 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 | ||||
|                 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 | ||||
|                 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 | ||||
|                 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 | ||||
|                 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 | ||||
|                 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 | ||||
|                 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 | ||||
|                 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF | ||||
|                 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF | ||||
|                 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 | ||||
|                 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 | ||||
|                 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 | ||||
|                 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 | ||||
|                 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 | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         JSON_ASSERT(byte < utf8d.size()); | ||||
|         const std::uint8_t type = utf8d[byte]; | ||||
|  | ||||
|         codep = (state != UTF8_ACCEPT) | ||||
|                 ? (byte & 0x3fu) | (codep << 6u) | ||||
|                 : (0xFFu >> type) & (byte); | ||||
|  | ||||
|         const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type); | ||||
|         JSON_ASSERT(index < utf8d.size()); | ||||
|         state = utf8d[index]; | ||||
|         return state; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Overload to make the compiler happy while it is instantiating | ||||
|      * dump_integer for number_unsigned_t. | ||||
|      * Must never be called. | ||||
|      */ | ||||
|     number_unsigned_t remove_sign(number_unsigned_t x) | ||||
|     { | ||||
|         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | ||||
|         return x; // LCOV_EXCL_LINE | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Helper function for dump_integer | ||||
|      * | ||||
|      * This function takes a negative signed integer and returns its absolute | ||||
|      * value as unsigned integer. The plus/minus shuffling is necessary as we can | ||||
|      * not directly remove the sign of an arbitrary signed integer as the | ||||
|      * absolute values of INT_MIN and INT_MAX are usually not the same. See | ||||
|      * #1708 for details. | ||||
|      */ | ||||
|     inline number_unsigned_t remove_sign(number_integer_t x) noexcept | ||||
|     { | ||||
|         JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression) | ||||
|         return static_cast<number_unsigned_t>(-(x + 1)) + 1; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     /// the output of the serializer | ||||
|     output_adapter_t<char> o = nullptr; | ||||
|  | ||||
|     /// a (hopefully) large enough character buffer | ||||
|     std::array<char, 64> number_buffer{{}}; | ||||
|  | ||||
|     /// the locale | ||||
|     const std::lconv* loc = nullptr; | ||||
|     /// the locale's thousand separator character | ||||
|     const char thousands_sep = '\0'; | ||||
|     /// the locale's decimal point character | ||||
|     const char decimal_point = '\0'; | ||||
|  | ||||
|     /// string buffer | ||||
|     std::array<char, 512> string_buffer{{}}; | ||||
|  | ||||
|     /// the indentation character | ||||
|     const char indent_char; | ||||
|     /// the indentation string | ||||
|     string_t indent_string; | ||||
|  | ||||
|     /// error_handler how to react on decoding errors | ||||
|     const error_handler_t error_handler; | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,146 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstring> // strlen | ||||
| #include <string> // string | ||||
| #include <utility> // forward | ||||
|  | ||||
| #include <nlohmann/detail/meta/cpp_future.hpp> | ||||
| #include <nlohmann/detail/meta/detected.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| inline std::size_t concat_length() | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| template<typename... Args> | ||||
| inline std::size_t concat_length(const char* cstr, const Args& ... rest); | ||||
|  | ||||
| template<typename StringType, typename... Args> | ||||
| inline std::size_t concat_length(const StringType& str, const Args& ... rest); | ||||
|  | ||||
| template<typename... Args> | ||||
| inline std::size_t concat_length(const char /*c*/, const Args& ... rest) | ||||
| { | ||||
|     return 1 + concat_length(rest...); | ||||
| } | ||||
|  | ||||
| template<typename... Args> | ||||
| inline std::size_t concat_length(const char* cstr, const Args& ... rest) | ||||
| { | ||||
|     // cppcheck-suppress ignoredReturnValue | ||||
|     return ::strlen(cstr) + concat_length(rest...); | ||||
| } | ||||
|  | ||||
| template<typename StringType, typename... Args> | ||||
| inline std::size_t concat_length(const StringType& str, const Args& ... rest) | ||||
| { | ||||
|     return str.size() + concat_length(rest...); | ||||
| } | ||||
|  | ||||
| template<typename OutStringType> | ||||
| inline void concat_into(OutStringType& /*out*/) | ||||
| {} | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ())); | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using detect_string_can_append = is_detected<string_can_append, StringType, Arg>; | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ()); | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>; | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end())); | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>; | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size())); | ||||
|  | ||||
| template<typename StringType, typename Arg> | ||||
| using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>; | ||||
|  | ||||
| template < typename OutStringType, typename Arg, typename... Args, | ||||
|            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | ||||
|                          && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 > | ||||
| inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); | ||||
|  | ||||
| template < typename OutStringType, typename Arg, typename... Args, | ||||
|            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | ||||
|                          && !detect_string_can_append_op<OutStringType, Arg>::value | ||||
|                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 > | ||||
| inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); | ||||
|  | ||||
| template < typename OutStringType, typename Arg, typename... Args, | ||||
|            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | ||||
|                          && !detect_string_can_append_op<OutStringType, Arg>::value | ||||
|                          && !detect_string_can_append_iter<OutStringType, Arg>::value | ||||
|                          && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 > | ||||
| inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); | ||||
|  | ||||
| template<typename OutStringType, typename Arg, typename... Args, | ||||
|          enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0> | ||||
| inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) | ||||
| { | ||||
|     out.append(std::forward<Arg>(arg)); | ||||
|     concat_into(out, std::forward<Args>(rest)...); | ||||
| } | ||||
|  | ||||
| template < typename OutStringType, typename Arg, typename... Args, | ||||
|            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | ||||
|                          && detect_string_can_append_op<OutStringType, Arg>::value, int > > | ||||
| inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) | ||||
| { | ||||
|     out += std::forward<Arg>(arg); | ||||
|     concat_into(out, std::forward<Args>(rest)...); | ||||
| } | ||||
|  | ||||
| template < typename OutStringType, typename Arg, typename... Args, | ||||
|            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | ||||
|                          && !detect_string_can_append_op<OutStringType, Arg>::value | ||||
|                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > > | ||||
| inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) | ||||
| { | ||||
|     out.append(arg.begin(), arg.end()); | ||||
|     concat_into(out, std::forward<Args>(rest)...); | ||||
| } | ||||
|  | ||||
| template < typename OutStringType, typename Arg, typename... Args, | ||||
|            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | ||||
|                          && !detect_string_can_append_op<OutStringType, Arg>::value | ||||
|                          && !detect_string_can_append_iter<OutStringType, Arg>::value | ||||
|                          && detect_string_can_append_data<OutStringType, Arg>::value, int > > | ||||
| inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) | ||||
| { | ||||
|     out.append(arg.data(), arg.size()); | ||||
|     concat_into(out, std::forward<Args>(rest)...); | ||||
| } | ||||
|  | ||||
| template<typename OutStringType = std::string, typename... Args> | ||||
| inline OutStringType concat(Args && ... args) | ||||
| { | ||||
|     OutStringType str; | ||||
|     str.reserve(concat_length(args...)); | ||||
|     concat_into(str, std::forward<Args>(args)...); | ||||
|     return str; | ||||
| } | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
| @@ -0,0 +1,72 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <nlohmann/detail/abi_macros.hpp> | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /*! | ||||
| @brief replace all occurrences of a substring by another string | ||||
|  | ||||
| @param[in,out] s  the string to manipulate; changed so that all | ||||
|                occurrences of @a f are replaced with @a t | ||||
| @param[in]     f  the substring to replace with @a t | ||||
| @param[in]     t  the string to replace @a f | ||||
|  | ||||
| @pre The search string @a f must not be empty. **This precondition is | ||||
| enforced with an assertion.** | ||||
|  | ||||
| @since version 2.0.0 | ||||
| */ | ||||
| template<typename StringType> | ||||
| inline void replace_substring(StringType& s, const StringType& f, | ||||
|                               const StringType& t) | ||||
| { | ||||
|     JSON_ASSERT(!f.empty()); | ||||
|     for (auto pos = s.find(f);                // find first occurrence of f | ||||
|             pos != StringType::npos;          // make sure f was found | ||||
|             s.replace(pos, f.size(), t),      // replace with t, and | ||||
|             pos = s.find(f, pos + t.size()))  // find next occurrence of f | ||||
|     {} | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * @brief string escaping as described in RFC 6901 (Sect. 4) | ||||
|  * @param[in] s string to escape | ||||
|  * @return    escaped string | ||||
|  * | ||||
|  * Note the order of escaping "~" to "~0" and "/" to "~1" is important. | ||||
|  */ | ||||
| template<typename StringType> | ||||
| inline StringType escape(StringType s) | ||||
| { | ||||
|     replace_substring(s, StringType{"~"}, StringType{"~0"}); | ||||
|     replace_substring(s, StringType{"/"}, StringType{"~1"}); | ||||
|     return s; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * @brief string unescaping as described in RFC 6901 (Sect. 4) | ||||
|  * @param[in] s string to unescape | ||||
|  * @return    unescaped string | ||||
|  * | ||||
|  * Note the order of escaping "~1" to "/" and "~0" to "~" is important. | ||||
|  */ | ||||
| template<typename StringType> | ||||
| static void unescape(StringType& s) | ||||
| { | ||||
|     replace_substring(s, StringType{"~1"}, StringType{"/"}); | ||||
|     replace_substring(s, StringType{"~0"}, StringType{"~"}); | ||||
| } | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
							
								
								
									
										118
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/value_t.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								source/Irrlicht/lib/json/include/nlohmann/detail/value_t.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| //     __ _____ _____ _____ | ||||
| //  __|  |   __|     |   | |  JSON for Modern C++ | ||||
| // |  |  |__   |  |  | | | |  version 3.11.2 | ||||
| // |_____|_____|_____|_|___|  https://github.com/nlohmann/json | ||||
| // | ||||
| // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <array> // array | ||||
| #include <cstddef> // size_t | ||||
| #include <cstdint> // uint8_t | ||||
| #include <string> // string | ||||
|  | ||||
| #include <nlohmann/detail/macro_scope.hpp> | ||||
| #if JSON_HAS_THREE_WAY_COMPARISON | ||||
|     #include <compare> // partial_ordering | ||||
| #endif | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| /////////////////////////// | ||||
| // JSON type enumeration // | ||||
| /////////////////////////// | ||||
|  | ||||
| /*! | ||||
| @brief the JSON type enumeration | ||||
|  | ||||
| This enumeration collects the different JSON types. It is internally used to | ||||
| distinguish the stored values, and the functions @ref basic_json::is_null(), | ||||
| @ref basic_json::is_object(), @ref basic_json::is_array(), | ||||
| @ref basic_json::is_string(), @ref basic_json::is_boolean(), | ||||
| @ref basic_json::is_number() (with @ref basic_json::is_number_integer(), | ||||
| @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), | ||||
| @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and | ||||
| @ref basic_json::is_structured() rely on it. | ||||
|  | ||||
| @note There are three enumeration entries (number_integer, number_unsigned, and | ||||
| number_float), because the library distinguishes these three types for numbers: | ||||
| @ref basic_json::number_unsigned_t is used for unsigned integers, | ||||
| @ref basic_json::number_integer_t is used for signed integers, and | ||||
| @ref basic_json::number_float_t is used for floating-point numbers or to | ||||
| approximate integers which do not fit in the limits of their respective type. | ||||
|  | ||||
| @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON | ||||
| value with the default value for a given type | ||||
|  | ||||
| @since version 1.0.0 | ||||
| */ | ||||
| enum class value_t : std::uint8_t | ||||
| { | ||||
|     null,             ///< null value | ||||
|     object,           ///< object (unordered set of name/value pairs) | ||||
|     array,            ///< array (ordered collection of values) | ||||
|     string,           ///< string value | ||||
|     boolean,          ///< boolean value | ||||
|     number_integer,   ///< number value (signed integer) | ||||
|     number_unsigned,  ///< number value (unsigned integer) | ||||
|     number_float,     ///< number value (floating-point) | ||||
|     binary,           ///< binary array (ordered collection of bytes) | ||||
|     discarded         ///< discarded by the parser callback function | ||||
| }; | ||||
|  | ||||
| /*! | ||||
| @brief comparison operator for JSON types | ||||
|  | ||||
| Returns an ordering that is similar to Python: | ||||
| - order: null < boolean < number < object < array < string < binary | ||||
| - furthermore, each type is not smaller than itself | ||||
| - discarded values are not comparable | ||||
| - binary is represented as a b"" string in python and directly comparable to a | ||||
|   string; however, making a binary array directly comparable with a string would | ||||
|   be surprising behavior in a JSON file. | ||||
|  | ||||
| @since version 1.0.0 | ||||
| */ | ||||
| #if JSON_HAS_THREE_WAY_COMPARISON | ||||
|     inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* | ||||
| #else | ||||
|     inline bool operator<(const value_t lhs, const value_t rhs) noexcept | ||||
| #endif | ||||
| { | ||||
|     static constexpr std::array<std::uint8_t, 9> order = {{ | ||||
|             0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, | ||||
|             1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, | ||||
|             6 /* binary */ | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     const auto l_index = static_cast<std::size_t>(lhs); | ||||
|     const auto r_index = static_cast<std::size_t>(rhs); | ||||
| #if JSON_HAS_THREE_WAY_COMPARISON | ||||
|     if (l_index < order.size() && r_index < order.size()) | ||||
|     { | ||||
|         return order[l_index] <=> order[r_index]; // *NOPAD* | ||||
|     } | ||||
|     return std::partial_ordering::unordered; | ||||
| #else | ||||
|     return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| // GCC selects the built-in operator< over an operator rewritten from | ||||
| // a user-defined spaceship operator | ||||
| // Clang, MSVC, and ICC select the rewritten candidate | ||||
| // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) | ||||
| #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) | ||||
| inline bool operator<(const value_t lhs, const value_t rhs) noexcept | ||||
| { | ||||
|     return std::is_lt(lhs <=> rhs); // *NOPAD* | ||||
| } | ||||
| #endif | ||||
|  | ||||
| }  // namespace detail | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
		Reference in New Issue
	
	Block a user