diff --git a/.gitmodules b/.gitmodules index b79ccd4..15d4b83 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "app/src/main/cpp/Dobby"] - path = app/src/main/cpp/Dobby - url = https://github.com/jmpews/Dobby.git +[submodule "app/src/main/cpp/libcxx"] + path = app/src/main/cpp/libcxx + url = https://github.com/topjohnwu/libcxx.git diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7d39699..c6a5fc3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -8,16 +8,6 @@ android { ndkVersion = "26.1.10909125" buildToolsVersion = "34.0.0" - packaging { - jniLibs { - excludes += "**/libdobby.so" - } - } - - buildFeatures { - prefab = true - } - defaultConfig { applicationId = "es.chiteroman.playintegrityfix" minSdk = 26 @@ -26,15 +16,10 @@ android { versionName = "1.0" externalNativeBuild { - cmake { - arguments += "-DANDROID_STL=none" - arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel" - - cppFlags += "-std=c++20" - cppFlags += "-fno-exceptions" - cppFlags += "-fno-rtti" - cppFlags += "-fvisibility=hidden" - cppFlags += "-fvisibility-inlines-hidden" + ndk { + jobs = Runtime.getRuntime().availableProcessors() + abiFilters += "armeabi-v7a" + abiFilters += "arm64-v8a" } } } @@ -53,13 +38,8 @@ android { } externalNativeBuild { - cmake { - path = file("src/main/cpp/CMakeLists.txt") - version = "3.22.1" + ndkBuild { + path = file("src/main/cpp/Android.mk") } } -} - -dependencies { - implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0") } \ No newline at end of file diff --git a/app/src/main/cpp/Android.mk b/app/src/main/cpp/Android.mk new file mode 100644 index 0000000..9632627 --- /dev/null +++ b/app/src/main/cpp/Android.mk @@ -0,0 +1,33 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := zygisk +LOCAL_SRC_FILES := main.cpp +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/*.c) +LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/common/*.c) +LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/third_party/xdl/*.c) + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook +LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/common +LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/include +LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/bsd +LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/lss +LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/xdl + +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/arch/arm/*.c) + LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/arch/arm +endif + +ifeq ($(TARGET_ARCH_ABI),arm64-v8a) + LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/arch/arm64/*.c) + LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/arch/arm64 +endif + +LOCAL_STATIC_LIBRARIES := libcxx +LOCAL_LDLIBS := -llog +include $(BUILD_SHARED_LIBRARY) + +include $(LOCAL_PATH)/libcxx/Android.mk \ No newline at end of file diff --git a/app/src/main/cpp/Application.mk b/app/src/main/cpp/Application.mk new file mode 100644 index 0000000..da73f7c --- /dev/null +++ b/app/src/main/cpp/Application.mk @@ -0,0 +1,4 @@ +APP_STL := none +APP_CFLAGS := -Oz -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden +APP_CPPFLAGS := -std=c++20 +APP_LDFLAGS := -Oz \ No newline at end of file diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt deleted file mode 100644 index 2071d71..0000000 --- a/app/src/main/cpp/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.22.1) - -project("playintegrityfix") - -find_package(cxx REQUIRED CONFIG) - -link_libraries(cxx::cxx) - -add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp) - -add_subdirectory(Dobby) - -SET_OPTION(Plugin.Android.BionicLinkerUtil ON) - -target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby_static) \ No newline at end of file diff --git a/app/src/main/cpp/Dobby b/app/src/main/cpp/Dobby deleted file mode 160000 index b0176de..0000000 --- a/app/src/main/cpp/Dobby +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b0176de574104726bb68dff3b77ee666300fc338 diff --git a/app/src/main/cpp/json.hpp b/app/src/main/cpp/json.hpp index dc58ca1..4d1a37a 100644 --- a/app/src/main/cpp/json.hpp +++ b/app/src/main/cpp/json.hpp @@ -27,6 +27,7 @@ #endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr +#include // accumulate #include // string, stoi, to_string #include // declval, forward, move, pair, swap #include // vector @@ -182,9 +183,6 @@ #include // nullptr_t #include // exception -#if JSON_DIAGNOSTICS - #include // accumulate -#endif #include // runtime_error #include // to_string #include // vector @@ -2485,14 +2483,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP #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 @@ -2600,13 +2590,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP class NumberUnsignedType, class NumberFloatType, \ template class AllocatorType, \ template class JSONSerializer, \ - class BinaryType, \ - class CustomBaseClass> + class BinaryType> #define NLOHMANN_BASIC_JSON_TPL \ basic_json + AllocatorType, JSONSerializer, BinaryType> // Macros to simplify conversion from/to types @@ -2756,7 +2745,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #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__)) } + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } /*! @brief macro @@ -2769,7 +2758,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP #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__)) } + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { 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): @@ -3399,8 +3389,7 @@ NLOHMANN_JSON_NAMESPACE_END template class AllocatorType = std::allocator, template class JSONSerializer = adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> + class BinaryType = std::vector> class basic_json; /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document @@ -3624,6 +3613,7 @@ template struct is_default_constructible> : conjunction...> {}; + template struct is_constructible : std::is_constructible {}; @@ -3639,6 +3629,7 @@ struct is_constructible> : is_default_constructible struct is_constructible> : is_default_constructible> {}; + template struct is_iterator_traits : std::false_type {}; @@ -4048,6 +4039,7 @@ struct value_in_range_of_impl2 } }; + template struct value_in_range_of_impl2 { @@ -4173,28 +4165,28 @@ inline std::size_t concat_length() } template -inline std::size_t concat_length(const char* cstr, const Args& ... rest); +inline std::size_t concat_length(const char* cstr, Args&& ... rest); template -inline std::size_t concat_length(const StringType& str, const Args& ... rest); +inline std::size_t concat_length(const StringType& str, Args&& ... rest); template -inline std::size_t concat_length(const char /*c*/, const Args& ... rest) +inline std::size_t concat_length(const char /*c*/, Args&& ... rest) { - return 1 + concat_length(rest...); + return 1 + concat_length(std::forward(rest)...); } template -inline std::size_t concat_length(const char* cstr, const Args& ... rest) +inline std::size_t concat_length(const char* cstr, Args&& ... rest) { // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(rest...); + return ::strlen(cstr) + concat_length(std::forward(rest)...); } template -inline std::size_t concat_length(const StringType& str, const Args& ... rest) +inline std::size_t concat_length(const StringType& str, Args&& ... rest) { - return str.size() + concat_length(rest...); + return str.size() + concat_length(std::forward(rest)...); } template @@ -4285,7 +4277,7 @@ template inline OutStringType concat(Args && ... args) { OutStringType str; - str.reserve(concat_length(args...)); + str.reserve(concat_length(std::forward(args)...)); concat_into(str, std::forward(args)...); return str; } @@ -4294,6 +4286,7 @@ inline OutStringType concat(Args && ... args) NLOHMANN_JSON_NAMESPACE_END + NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -4341,9 +4334,9 @@ class exception : public std::exception { case value_t::array: { - for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) + for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) { - if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) + if (¤t->m_parent->m_value.array->operator[](i) == current) { tokens.emplace_back(std::to_string(i)); break; @@ -4354,7 +4347,7 @@ class exception : public std::exception case value_t::object: { - for (const auto& element : *current->m_parent->m_data.m_value.object) + for (const auto& element : *current->m_parent->m_value.object) { if (&element.second == current) { @@ -4417,17 +4410,17 @@ class parse_error : public exception template::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); + 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::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); + 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()}; } @@ -4461,7 +4454,7 @@ class invalid_iterator : public exception template::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); + std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4479,7 +4472,7 @@ class type_error : public exception template::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); + std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4496,7 +4489,7 @@ class out_of_range : public exception template::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); + std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4513,7 +4506,7 @@ class other_error : public exception template::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); + std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -5154,10 +5147,10 @@ template class iteration_proxy_value // 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::value - && std::is_nothrow_move_constructible::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) + && std::is_nothrow_move_constructible::value) = default; iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(std::is_nothrow_move_assignable::value - && std::is_nothrow_move_assignable::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) + && std::is_nothrow_move_assignable::value) = default; ~iteration_proxy_value() = default; /// dereference operator (needed for range-based for) @@ -5304,11 +5297,11 @@ namespace std #pragma clang diagnostic ignored "-Wmismatched-tags" #endif template -class tuple_size<::nlohmann::detail::iteration_proxy_value> // NOLINT(cert-dcl58-cpp) +class tuple_size<::nlohmann::detail::iteration_proxy_value> : public std::integral_constant {}; template -class tuple_element> // NOLINT(cert-dcl58-cpp) +class tuple_element> { public: using type = decltype( @@ -5347,7 +5340,7 @@ namespace detail /* * 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 + * j.m_value.destroy(j.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. */ @@ -5360,9 +5353,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::boolean; + j.m_value = b; j.assert_invariant(); } }; @@ -5373,18 +5366,18 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = s; j.assert_invariant(); } template 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.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = std::move(s); j.assert_invariant(); } @@ -5393,9 +5386,9 @@ struct external_constructor 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(str); + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value.string = j.template create(str); j.assert_invariant(); } }; @@ -5406,18 +5399,18 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); } template 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.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(std::move(b)); j.assert_invariant(); } }; @@ -5428,9 +5421,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::number_float; + j.m_value = val; j.assert_invariant(); } }; @@ -5441,9 +5434,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::number_unsigned; + j.m_value = val; j.assert_invariant(); } }; @@ -5454,9 +5447,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::number_integer; + j.m_value = val; j.assert_invariant(); } }; @@ -5467,9 +5460,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = arr; j.set_parents(); j.assert_invariant(); } @@ -5477,9 +5470,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = std::move(arr); j.set_parents(); j.assert_invariant(); } @@ -5492,9 +5485,9 @@ struct external_constructor 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(begin(arr), end(arr)); + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); j.set_parents(); j.assert_invariant(); } @@ -5502,14 +5495,14 @@ struct external_constructor template static void construct(BasicJsonType& j, const std::vector& 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()); + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.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.m_value.array->push_back(x); + j.set_parent(j.m_value.array->back()); } j.assert_invariant(); } @@ -5518,13 +5511,13 @@ struct external_constructor enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray& 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()); + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.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()); + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); } j.set_parents(); j.assert_invariant(); @@ -5537,9 +5530,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = obj; j.set_parents(); j.assert_invariant(); } @@ -5547,9 +5540,9 @@ struct external_constructor template 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.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = std::move(obj); j.set_parents(); j.assert_invariant(); } @@ -5561,9 +5554,9 @@ struct external_constructor 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(begin(obj), end(obj)); + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); j.set_parents(); j.assert_invariant(); } @@ -6147,6 +6140,7 @@ class file_input_adapter 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 @@ -6245,6 +6239,7 @@ class iterator_input_adapter } }; + template struct wide_string_input_helper; @@ -6368,7 +6363,7 @@ struct wide_string_input_helper } }; -// Wraps another input adapter to convert wide character types into individual bytes. +// Wraps another input apdater to convert wide character types into individual bytes. template class wide_string_input_adapter { @@ -6413,6 +6408,7 @@ class wide_string_input_adapter std::size_t utf8_bytes_filled = 0; }; + template struct iterator_input_adapter_factory { @@ -6714,6 +6710,7 @@ struct json_sax virtual ~json_sax() = default; }; + namespace detail { /*! @@ -6815,7 +6812,7 @@ class json_sax_dom_parser 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)); + object_element = &(ref_stack.back()->m_value.object->operator[](val)); return true; } @@ -6890,8 +6887,8 @@ class json_sax_dom_parser if (ref_stack.back()->is_array()) { - ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_data.m_value.array->back()); + ref_stack.back()->m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_value.array->back()); } JSON_ASSERT(ref_stack.back()->is_object()); @@ -7010,7 +7007,7 @@ class json_sax_dom_callback_parser // 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); + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); } return true; @@ -7095,7 +7092,7 @@ class json_sax_dom_callback_parser // remove discarded value if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) { - ref_stack.back()->m_data.m_value.array->pop_back(); + ref_stack.back()->m_value.array->pop_back(); } return true; @@ -7162,7 +7159,7 @@ class json_sax_dom_callback_parser if (ref_stack.empty()) { root = std::move(value); - return {true, & root}; + return {true, &root}; } // skip this value if we already decided to skip the parent @@ -7178,8 +7175,8 @@ class json_sax_dom_callback_parser // 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())}; + ref_stack.back()->m_value.array->emplace_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; } // object @@ -7526,7 +7523,7 @@ class lexer : public lexer_base for (auto range = ranges.begin(); range != ranges.end(); ++range) { get(); - if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions) + if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) { add(current); } @@ -9132,6 +9129,7 @@ static inline bool little_endianness(int num = 1) noexcept return *reinterpret_cast(&num) == 1; } + /////////////////// // binary reader // /////////////////// @@ -9406,7 +9404,7 @@ class binary_reader { std::array cr{{}}; static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - const std::string cr_str{cr.data()}; + std::string cr_str{cr.data()}; return sax->parse_error(element_type_parse_position, cr_str, parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); } @@ -11229,7 +11227,7 @@ class binary_reader } if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr)); } std::vector dim; if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) @@ -11341,7 +11339,7 @@ class binary_reader exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); } - const bool is_error = get_ubjson_size_value(result.first, is_ndarray); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); if (input_format == input_format_t::bjdata && is_ndarray) { if (inside_ndarray) @@ -11356,7 +11354,7 @@ class binary_reader if (current == '#') { - const bool is_error = get_ubjson_size_value(result.first, is_ndarray); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); if (input_format == input_format_t::bjdata && is_ndarray) { return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, @@ -12441,25 +12439,13 @@ class parser 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::end_of_input: case token_type::literal_or_value: default: // the last token was unexpected { @@ -12901,7 +12887,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { @@ -12998,17 +12984,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_data.m_value.object->begin(); + m_it.object_iterator = m_object->m_value.object->begin(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_data.m_value.array->begin(); + m_it.array_iterator = m_object->m_value.array->begin(); break; } @@ -13042,17 +13028,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_data.m_value.object->end(); + m_it.object_iterator = m_object->m_value.object->end(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_data.m_value.array->end(); + m_it.array_iterator = m_object->m_value.array->end(); break; } @@ -13081,17 +13067,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->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()); + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); return *m_it.array_iterator; } @@ -13125,17 +13111,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->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()); + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); return &*m_it.array_iterator; } @@ -13178,7 +13164,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { @@ -13229,7 +13215,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { @@ -13276,7 +13262,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: return (m_it.object_iterator == other.m_it.object_iterator); @@ -13321,7 +13307,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); @@ -13377,7 +13363,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -13456,7 +13442,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -13485,7 +13471,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); @@ -13687,40 +13673,6 @@ NLOHMANN_JSON_NAMESPACE_END // #include -// #include - - -#include // conditional, is_same - -// #include - - -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 -using json_base_class = typename std::conditional < - std::is_same::value, - json_default_base, - T - >::type; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ @@ -13959,7 +13911,7 @@ class json_pointer 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) + 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(p_end - p) != s.size())) // incomplete read @@ -14115,7 +14067,7 @@ class json_pointer if (reference_token == "-") { // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); + ptr = &ptr->operator[](ptr->m_value.array->size()); } else { @@ -14167,7 +14119,7 @@ class json_pointer { // "-" 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()), + "array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); } @@ -14224,7 +14176,7 @@ class json_pointer 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)); + JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); } // use unchecked array access @@ -14274,7 +14226,7 @@ class json_pointer { // "-" 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()), + "array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); } @@ -14469,7 +14421,7 @@ class json_pointer { case detail::value_t::array: { - if (value.m_data.m_value.array->empty()) + if (value.m_value.array->empty()) { // flatten empty array as null result[reference_string] = nullptr; @@ -14477,10 +14429,10 @@ class json_pointer else { // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) { flatten(detail::concat(reference_string, '/', std::to_string(i)), - value.m_data.m_value.array->operator[](i), result); + value.m_value.array->operator[](i), result); } } break; @@ -14488,7 +14440,7 @@ class json_pointer case detail::value_t::object: { - if (value.m_data.m_value.object->empty()) + if (value.m_value.object->empty()) { // flatten empty object as null result[reference_string] = nullptr; @@ -14496,7 +14448,7 @@ class json_pointer else { // iterate object and use keys as reference string - for (const auto& element : *value.m_data.m_value.object) + for (const auto& element : *value.m_value.object) { flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); } @@ -14543,7 +14495,7 @@ class json_pointer BasicJsonType result; // iterate the JSON object values - for (const auto& element : *value.m_data.m_value.object) + for (const auto& element : *value.m_value.object) { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { @@ -15026,7 +14978,7 @@ class binary_writer { case value_t::object: { - write_bson_object(*j.m_data.m_value.object); + write_bson_object(*j.m_value.object); break; } @@ -15061,7 +15013,7 @@ class binary_writer case value_t::boolean: { - oa->write_character(j.m_data.m_value.boolean + oa->write_character(j.m_value.boolean ? to_char_type(0xF5) : to_char_type(0xF4)); break; @@ -15069,42 +15021,42 @@ class binary_writer case value_t::number_integer: { - if (j.m_data.m_value.number_integer >= 0) + if (j.m_value.number_integer >= 0) { // CBOR does not differentiate between positive signed // integers and unsigned integers. Therefore, we used the // code from the value_t::number_unsigned case here. - if (j.m_data.m_value.number_integer <= 0x17) + if (j.m_value.number_integer <= 0x17) { - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } } else { // The conversions below encode the sign in the first // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_data.m_value.number_integer; - if (j.m_data.m_value.number_integer >= -24) + const auto positive_number = -1 - j.m_value.number_integer; + if (j.m_value.number_integer >= -24) { write_number(static_cast(0x20 + positive_number)); } @@ -15134,52 +15086,52 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned <= 0x17) + if (j.m_value.number_unsigned <= 0x17) { - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } break; } case value_t::number_float: { - if (std::isnan(j.m_data.m_value.number_float)) + if (std::isnan(j.m_value.number_float)) { // NaN is 0xf97e00 in CBOR oa->write_character(to_char_type(0xF9)); oa->write_character(to_char_type(0x7E)); oa->write_character(to_char_type(0x00)); } - else if (std::isinf(j.m_data.m_value.number_float)) + else if (std::isinf(j.m_value.number_float)) { // Infinity is 0xf97c00, -Infinity is 0xf9fc00 oa->write_character(to_char_type(0xf9)); - oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); + oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); oa->write_character(to_char_type(0x00)); } else { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); + write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); } break; } @@ -15187,7 +15139,7 @@ class binary_writer case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_data.m_value.string->size(); + const auto N = j.m_value.string->size(); if (N <= 0x17) { write_number(static_cast(0x60 + N)); @@ -15217,15 +15169,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_data.m_value.string->c_str()), - j.m_data.m_value.string->size()); + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_data.m_value.array->size(); + const auto N = j.m_value.array->size(); if (N <= 0x17) { write_number(static_cast(0x80 + N)); @@ -15254,7 +15206,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_data.m_value.array) + for (const auto& el : *j.m_value.array) { write_cbor(el); } @@ -15263,32 +15215,32 @@ class binary_writer case value_t::binary: { - if (j.m_data.m_value.binary->has_subtype()) + if (j.m_value.binary->has_subtype()) { - if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd8)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } - else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd9)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } - else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xda)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } - else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xdb)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } } // step 1: write control byte and the binary array size - const auto N = j.m_data.m_value.binary->size(); + const auto N = j.m_value.binary->size(); if (N <= 0x17) { write_number(static_cast(0x40 + N)); @@ -15318,7 +15270,7 @@ class binary_writer // step 2: write each element oa->write_characters( - reinterpret_cast(j.m_data.m_value.binary->data()), + reinterpret_cast(j.m_value.binary->data()), N); break; @@ -15327,7 +15279,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_data.m_value.object->size(); + const auto N = j.m_value.object->size(); if (N <= 0x17) { write_number(static_cast(0xA0 + N)); @@ -15356,7 +15308,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_data.m_value.object) + for (const auto& el : *j.m_value.object) { write_cbor(el.first); write_cbor(el.second); @@ -15385,7 +15337,7 @@ class binary_writer case value_t::boolean: // true and false { - oa->write_character(j.m_data.m_value.boolean + oa->write_character(j.m_value.boolean ? to_char_type(0xC3) : to_char_type(0xC2)); break; @@ -15393,75 +15345,75 @@ class binary_writer case value_t::number_integer: { - if (j.m_data.m_value.number_integer >= 0) + if (j.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive // signed integers and unsigned integers. Therefore, we used // the code from the value_t::number_unsigned case here. - if (j.m_data.m_value.number_unsigned < 128) + if (j.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } } else { - if (j.m_data.m_value.number_integer >= -32) + if (j.m_value.number_integer >= -32) { // negative fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 oa->write_character(to_char_type(0xD0)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 oa->write_character(to_char_type(0xD1)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 oa->write_character(to_char_type(0xD2)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 oa->write_character(to_char_type(0xD3)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } } break; @@ -15469,48 +15421,48 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned < 128) + if (j.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } break; } case value_t::number_float: { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); + write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); break; } case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_data.m_value.string->size(); + const auto N = j.m_value.string->size(); if (N <= 31) { // fixstr @@ -15537,15 +15489,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_data.m_value.string->c_str()), - j.m_data.m_value.string->size()); + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_data.m_value.array->size(); + const auto N = j.m_value.array->size(); if (N <= 15) { // fixarray @@ -15565,7 +15517,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_data.m_value.array) + for (const auto& el : *j.m_value.array) { write_msgpack(el); } @@ -15576,10 +15528,10 @@ class binary_writer { // step 0: determine if the binary type has a set subtype to // determine whether or not to use the ext or fixext types - const bool use_ext = j.m_data.m_value.binary->has_subtype(); + const bool use_ext = j.m_value.binary->has_subtype(); // step 1: write control byte and the byte string length - const auto N = j.m_data.m_value.binary->size(); + const auto N = j.m_value.binary->size(); if (N <= (std::numeric_limits::max)()) { std::uint8_t output_type{}; @@ -15624,18 +15576,18 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - const std::uint8_t output_type = use_ext - ? 0xC8 // ext 16 - : 0xC5; // bin 16 + std::uint8_t output_type = use_ext + ? 0xC8 // ext 16 + : 0xC5; // bin 16 oa->write_character(to_char_type(output_type)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - const std::uint8_t output_type = use_ext - ? 0xC9 // ext 32 - : 0xC6; // bin 32 + std::uint8_t output_type = use_ext + ? 0xC9 // ext 32 + : 0xC6; // bin 32 oa->write_character(to_char_type(output_type)); write_number(static_cast(N)); @@ -15644,12 +15596,12 @@ class binary_writer // step 1.5: if this is an ext type, write the subtype if (use_ext) { - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } // step 2: write the byte string oa->write_characters( - reinterpret_cast(j.m_data.m_value.binary->data()), + reinterpret_cast(j.m_value.binary->data()), N); break; @@ -15658,7 +15610,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_data.m_value.object->size(); + const auto N = j.m_value.object->size(); if (N <= 15) { // fixmap @@ -15678,7 +15630,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_data.m_value.object) + for (const auto& el : *j.m_value.object) { write_msgpack(el.first); write_msgpack(el.second); @@ -15718,7 +15670,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(j.m_data.m_value.boolean + oa->write_character(j.m_value.boolean ? to_char_type('T') : to_char_type('F')); } @@ -15727,19 +15679,19 @@ class binary_writer case value_t::number_integer: { - write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata); break; } case value_t::number_unsigned: { - write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata); break; } case value_t::number_float: { - write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata); break; } @@ -15749,10 +15701,10 @@ class binary_writer { oa->write_character(to_char_type('S')); } - write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata); oa->write_characters( - reinterpret_cast(j.m_data.m_value.string->c_str()), - j.m_data.m_value.string->size()); + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); break; } @@ -15764,7 +15716,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_data.m_value.array->empty()) + if (use_type && !j.m_value.array->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15787,10 +15739,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata); } - for (const auto& el : *j.m_data.m_value.array) + for (const auto& el : *j.m_value.array) { write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); } @@ -15810,7 +15762,7 @@ class binary_writer oa->write_character(to_char_type('[')); } - if (use_type && !j.m_data.m_value.binary->empty()) + if (use_type && !j.m_value.binary->empty()) { JSON_ASSERT(use_count); oa->write_character(to_char_type('$')); @@ -15820,21 +15772,21 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata); } if (use_type) { oa->write_characters( - reinterpret_cast(j.m_data.m_value.binary->data()), - j.m_data.m_value.binary->size()); + reinterpret_cast(j.m_value.binary->data()), + j.m_value.binary->size()); } else { - for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) + for (size_t i = 0; i < j.m_value.binary->size(); ++i) { oa->write_character(to_char_type('U')); - oa->write_character(j.m_data.m_value.binary->data()[i]); + oa->write_character(j.m_value.binary->data()[i]); } } @@ -15848,9 +15800,9 @@ class binary_writer case value_t::object: { - if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) + if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end()) { - if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) + if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) { break; } @@ -15862,7 +15814,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_data.m_value.object->empty()) + if (use_type && !j.m_value.object->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15885,10 +15837,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata); } - for (const auto& el : *j.m_data.m_value.object) + for (const auto& el : *j.m_value.object) { write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); oa->write_characters( @@ -16038,19 +15990,19 @@ class binary_writer void write_bson_unsigned(const string_t& name, const BasicJsonType& j) { - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(j.m_data.m_value.number_unsigned), true); + write_number(static_cast(j.m_value.number_unsigned), true); } - else if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(j.m_data.m_value.number_unsigned), true); + write_number(static_cast(j.m_value.number_unsigned), true); } else { - JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); + JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); } } @@ -16131,13 +16083,13 @@ class binary_writer switch (j.type()) { case value_t::object: - return header_size + calc_bson_object_size(*j.m_data.m_value.object); + return header_size + calc_bson_object_size(*j.m_value.object); case value_t::array: - return header_size + calc_bson_array_size(*j.m_data.m_value.array); + return header_size + calc_bson_array_size(*j.m_value.array); case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_data.m_value.binary); + return header_size + calc_bson_binary_size(*j.m_value.binary); case value_t::boolean: return header_size + 1ul; @@ -16146,13 +16098,13 @@ class binary_writer return header_size + 8ul; case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer); + return header_size + calc_bson_integer_size(j.m_value.number_integer); case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned); + return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); case value_t::string: - return header_size + calc_bson_string_size(*j.m_data.m_value.string); + return header_size + calc_bson_string_size(*j.m_value.string); case value_t::null: return header_size + 0ul; @@ -16178,28 +16130,28 @@ class binary_writer switch (j.type()) { case value_t::object: - return write_bson_object_entry(name, *j.m_data.m_value.object); + return write_bson_object_entry(name, *j.m_value.object); case value_t::array: - return write_bson_array(name, *j.m_data.m_value.array); + return write_bson_array(name, *j.m_value.array); case value_t::binary: - return write_bson_binary(name, *j.m_data.m_value.binary); + return write_bson_binary(name, *j.m_value.binary); case value_t::boolean: - return write_bson_boolean(name, j.m_data.m_value.boolean); + return write_bson_boolean(name, j.m_value.boolean); case value_t::number_float: - return write_bson_double(name, j.m_data.m_value.number_float); + return write_bson_double(name, j.m_value.number_float); case value_t::number_integer: - return write_bson_integer(name, j.m_data.m_value.number_integer); + return write_bson_integer(name, j.m_value.number_integer); case value_t::number_unsigned: return write_bson_unsigned(name, j); case value_t::string: - return write_bson_string(name, *j.m_data.m_value.string); + return write_bson_string(name, *j.m_value.string); case value_t::null: return write_bson_null(name); @@ -16221,8 +16173,8 @@ class binary_writer */ static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) { - const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), - [](size_t result, const typename BasicJsonType::object_t::value_type & el) + std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), + [](size_t result, const typename BasicJsonType::object_t::value_type & el) { return result += calc_bson_element_size(el.first, el.second); }); @@ -16472,35 +16424,35 @@ class binary_writer return 'Z'; case value_t::boolean: - return j.m_data.m_value.boolean ? 'T' : 'F'; + return j.m_value.boolean ? 'T' : 'F'; case value_t::number_integer: { - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'i'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'U'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'I'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) { return 'u'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'l'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) { return 'm'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'L'; } @@ -16510,35 +16462,35 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'i'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'U'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'I'; } - if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'u'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'l'; } - if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'm'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'L'; } - if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits::max)()) { return 'M'; } @@ -16547,7 +16499,7 @@ class binary_writer } case value_t::number_float: - return get_ubjson_float_prefix(j.m_data.m_value.number_float); + return get_ubjson_float_prefix(j.m_value.number_float); case value_t::string: return 'S'; @@ -16596,7 +16548,7 @@ class binary_writer std::size_t len = (value.at(key).empty() ? 0 : 1); for (const auto& el : value.at(key)) { - len *= static_cast(el.m_data.m_value.number_unsigned); + len *= static_cast(el.m_value.number_unsigned); } key = "_ArrayData_"; @@ -16618,70 +16570,70 @@ class binary_writer { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'i') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'u') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'I') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'm') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'l') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'M') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'L') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'd') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_float), true); + write_number(static_cast(el.m_value.number_float), true); } } else if (dtype == 'D') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_float), true); + write_number(static_cast(el.m_value.number_float), true); } } return false; @@ -17740,7 +17692,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) // NB: If the neighbors are computed for single-precision numbers, there is a single float // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision // value is off by 1 ulp. -#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) +#if 0 const boundaries w = compute_boundaries(static_cast(value)); #else const boundaries w = compute_boundaries(value); @@ -18042,11 +17994,11 @@ class serializer const unsigned int indent_step, const unsigned int current_indent = 0) { - switch (val.m_data.m_type) + switch (val.m_type) { case value_t::object: { - if (val.m_data.m_value.object->empty()) + if (val.m_value.object->empty()) { o->write_characters("{}", 2); return; @@ -18064,8 +18016,8 @@ class serializer } // 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) + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) { o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); @@ -18076,8 +18028,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_data.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -18093,8 +18045,8 @@ class serializer 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) + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) { o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -18104,8 +18056,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_data.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); o->write_characters("\":", 2); @@ -18119,7 +18071,7 @@ class serializer case value_t::array: { - if (val.m_data.m_value.array->empty()) + if (val.m_value.array->empty()) { o->write_characters("[]", 2); return; @@ -18137,8 +18089,8 @@ class serializer } // first n-1 elements - for (auto i = val.m_data.m_value.array->cbegin(); - i != val.m_data.m_value.array->cend() - 1; ++i) + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) { o->write_characters(indent_string.c_str(), new_indent); dump(*i, true, ensure_ascii, indent_step, new_indent); @@ -18146,9 +18098,9 @@ class serializer } // last element - JSON_ASSERT(!val.m_data.m_value.array->empty()); + JSON_ASSERT(!val.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); + dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -18159,16 +18111,16 @@ class serializer 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) + for (auto i = val.m_value.array->cbegin(); + i != val.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); + JSON_ASSERT(!val.m_value.array->empty()); + dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); o->write_character(']'); } @@ -18179,7 +18131,7 @@ class serializer case value_t::string: { o->write_character('\"'); - dump_escaped(*val.m_data.m_value.string, ensure_ascii); + dump_escaped(*val.m_value.string, ensure_ascii); o->write_character('\"'); return; } @@ -18201,24 +18153,24 @@ class serializer o->write_characters("\"bytes\": [", 10); - if (!val.m_data.m_value.binary->empty()) + if (!val.m_value.binary->empty()) { - for (auto i = val.m_data.m_value.binary->cbegin(); - i != val.m_data.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_characters(", ", 2); } - dump_integer(val.m_data.m_value.binary->back()); + dump_integer(val.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()) + if (val.m_value.binary->has_subtype()) { - dump_integer(val.m_data.m_value.binary->subtype()); + dump_integer(val.m_value.binary->subtype()); } else { @@ -18232,21 +18184,21 @@ class serializer { o->write_characters("{\"bytes\":[", 10); - if (!val.m_data.m_value.binary->empty()) + if (!val.m_value.binary->empty()) { - for (auto i = val.m_data.m_value.binary->cbegin(); - i != val.m_data.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_character(','); } - dump_integer(val.m_data.m_value.binary->back()); + dump_integer(val.m_value.binary->back()); } o->write_characters("],\"subtype\":", 12); - if (val.m_data.m_value.binary->has_subtype()) + if (val.m_value.binary->has_subtype()) { - dump_integer(val.m_data.m_value.binary->subtype()); + dump_integer(val.m_value.binary->subtype()); o->write_character('}'); } else @@ -18259,7 +18211,7 @@ class serializer case value_t::boolean: { - if (val.m_data.m_value.boolean) + if (val.m_value.boolean) { o->write_characters("true", 4); } @@ -18272,19 +18224,19 @@ class serializer case value_t::number_integer: { - dump_integer(val.m_data.m_value.number_integer); + dump_integer(val.m_value.number_integer); return; } case value_t::number_unsigned: { - dump_integer(val.m_data.m_value.number_unsigned); + dump_integer(val.m_value.number_unsigned); return; } case value_t::number_float: { - dump_float(val.m_data.m_value.number_float); + dump_float(val.m_value.number_float); return; } @@ -18858,8 +18810,8 @@ class serializer ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte); - const std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < utf8d.size()); + std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + JSON_ASSERT(index < 400); state = utf8d[index]; return state; } @@ -19046,7 +18998,7 @@ template , template::value, int> = 0> - T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) + T & at(KeyType && key) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19074,7 +19026,7 @@ template , template::value, int> = 0> - const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) + const T & at(KeyType && key) const { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19108,7 +19060,7 @@ template , template::value, int> = 0> - size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) + size_type erase(KeyType && key) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19199,7 +19151,7 @@ template , template::value, int> = 0> - size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) + size_type count(KeyType && key) const { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19225,7 +19177,7 @@ template , template::value, int> = 0> - iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) + iterator find(KeyType && key) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19288,9 +19240,7 @@ NLOHMANN_JSON_NAMESPACE_END #if defined(JSON_HAS_CPP_17) - #if JSON_HAS_STATIC_RTTI - #include - #endif + #include #include #endif @@ -19321,7 +19271,6 @@ The invariants are checked by member function assert_invariant(). */ NLOHMANN_BASIC_JSON_TPL_DECLARATION class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) - : public ::nlohmann::detail::json_base_class { private: template friend struct detail::external_constructor; @@ -19348,7 +19297,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// workaround type for MSVC using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - using json_base_class_t = ::nlohmann::detail::json_base_class; JSON_PRIVATE_UNLESS_TESTED: // convenience aliases for types residing in namespace detail; @@ -19420,6 +19368,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + ///////////////////// // container types // ///////////////////// @@ -19461,6 +19410,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + /// @brief returns the allocator associated with the container /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ static allocator_type get_allocator() @@ -19523,6 +19473,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; #endif + #if defined(_MSVC_LANG) result["compiler"]["c++"] = std::to_string(_MSVC_LANG); #elif defined(__cplusplus) @@ -19533,6 +19484,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } + /////////////////////////// // JSON value data types // /////////////////////////// @@ -19779,16 +19731,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void destroy(value_t t) { - if ( - (t == value_t::object && object == nullptr) || - (t == value_t::array && array == nullptr) || - (t == value_t::string && string == nullptr) || - (t == value_t::binary && binary == nullptr) - ) - { - //not initialized (e.g. due to exception in the ctor) - return; - } if (t == value_t::array || t == value_t::object) { // flatten the current json_value to a heap-allocated stack @@ -19819,18 +19761,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // its children to the stack to be processed later if (current_item.is_array()) { - std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); + std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); - current_item.m_data.m_value.array->clear(); + current_item.m_value.array->clear(); } else if (current_item.is_object()) { - for (auto&& it : *current_item.m_data.m_value.object) + for (auto&& it : *current_item.m_value.object) { stack.push_back(std::move(it.second)); } - current_item.m_data.m_value.object->clear(); + current_item.m_value.object->clear(); } // it's now safe that current_item get destructed @@ -19907,10 +19849,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec */ void assert_invariant(bool check_parents = true) const noexcept { - JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); - JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); - JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); - JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); + JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); + JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); + JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); + JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); #if JSON_DIAGNOSTICS JSON_TRY @@ -19929,11 +19871,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void set_parents() { #if JSON_DIAGNOSTICS - switch (m_data.m_type) + switch (m_type) { case value_t::array: { - for (auto& element : *m_data.m_value.array) + for (auto& element : *m_value.array) { element.m_parent = this; } @@ -19942,7 +19884,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::object: { - for (auto& element : *m_data.m_value.object) + for (auto& element : *m_value.object) { element.second.m_parent = this; } @@ -19983,7 +19925,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); - if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -20039,7 +19981,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief create an empty value with a given type /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const value_t v) - : m_data(v) + : m_type(v), m_value(v) { assert_invariant(); } @@ -20113,12 +20055,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec *this = nullptr; break; case value_t::discarded: - m_data.m_type = value_t::discarded; + m_type = value_t::discarded; break; default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } - JSON_ASSERT(m_data.m_type == val.type()); + JSON_ASSERT(m_type == val.type()); set_parents(); assert_invariant(); } @@ -20134,10 +20076,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec bool is_an_object = std::all_of(init.begin(), init.end(), [](const detail::json_ref& element_ref) { - // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int; - // (many string types can be constructed from 0 via its null-pointer guise, so we get a - // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows) - return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast(0)].is_string(); + return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); }); // adjust type if type deduction is not wanted @@ -20159,22 +20098,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_an_object) { // the initializer list is a list of pairs -> create object - m_data.m_type = value_t::object; - m_data.m_value = value_t::object; + m_type = value_t::object; + m_value = value_t::object; for (auto& element_ref : init) { auto element = element_ref.moved_or_copied(); - m_data.m_value.object->emplace( - std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), - std::move((*element.m_data.m_value.array)[1])); + m_value.object->emplace( + std::move(*((*element.m_value.array)[0].m_value.string)), + std::move((*element.m_value.array)[1])); } } else { // the initializer list describes an array -> create array - m_data.m_type = value_t::array; - m_data.m_value.array = create(init.begin(), init.end()); + m_type = value_t::array; + m_value.array = create(init.begin(), init.end()); } set_parents(); @@ -20187,8 +20126,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = init; + res.m_type = value_t::binary; + res.m_value = init; return res; } @@ -20198,8 +20137,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = binary_t(init, subtype); + res.m_type = value_t::binary; + res.m_value = binary_t(init, subtype); return res; } @@ -20209,8 +20148,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = std::move(init); + res.m_type = value_t::binary; + res.m_value = std::move(init); return res; } @@ -20220,8 +20159,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = binary_t(std::move(init), subtype); + res.m_type = value_t::binary; + res.m_value = binary_t(std::move(init), subtype); return res; } @@ -20243,9 +20182,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief construct an array with count copies of given value /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ - basic_json(size_type cnt, const basic_json& val): - m_data{cnt, val} + basic_json(size_type cnt, const basic_json& val) + : m_type(value_t::array) { + m_value.array = create(cnt, val); set_parents(); assert_invariant(); } @@ -20267,10 +20207,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // copy type from first iterator - m_data.m_type = first.m_object->m_data.m_type; + m_type = first.m_object->m_type; // check if iterator range is complete for primitive values - switch (m_data.m_type) + switch (m_type) { case value_t::boolean: case value_t::number_float: @@ -20295,55 +20235,55 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } - switch (m_data.m_type) + switch (m_type) { case value_t::number_integer: { - m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; + m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { - m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; + m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { - m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; + m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { - m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; + m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { - m_data.m_value = *first.m_object->m_data.m_value.string; + m_value = *first.m_object->m_value.string; break; } case value_t::object: { - m_data.m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); + m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); break; } case value_t::array: { - m_data.m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); break; } case value_t::binary: { - m_data.m_value = *first.m_object->m_data.m_value.binary; + m_value = *first.m_object->m_value.binary; break; } @@ -20357,6 +20297,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec assert_invariant(); } + /////////////////////////////////////// // other constructors and destructor // /////////////////////////////////////// @@ -20369,59 +20310,58 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief copy constructor /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const basic_json& other) - : json_base_class_t(other) + : m_type(other.m_type) { - m_data.m_type = other.m_data.m_type; // check of passed value is valid other.assert_invariant(); - switch (m_data.m_type) + switch (m_type) { case value_t::object: { - m_data.m_value = *other.m_data.m_value.object; + m_value = *other.m_value.object; break; } case value_t::array: { - m_data.m_value = *other.m_data.m_value.array; + m_value = *other.m_value.array; break; } case value_t::string: { - m_data.m_value = *other.m_data.m_value.string; + m_value = *other.m_value.string; break; } case value_t::boolean: { - m_data.m_value = other.m_data.m_value.boolean; + m_value = other.m_value.boolean; break; } case value_t::number_integer: { - m_data.m_value = other.m_data.m_value.number_integer; + m_value = other.m_value.number_integer; break; } case value_t::number_unsigned: { - m_data.m_value = other.m_data.m_value.number_unsigned; + m_value = other.m_value.number_unsigned; break; } case value_t::number_float: { - m_data.m_value = other.m_data.m_value.number_float; + m_value = other.m_value.number_float; break; } case value_t::binary: { - m_data.m_value = *other.m_data.m_value.binary; + m_value = *other.m_value.binary; break; } @@ -20438,15 +20378,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief move constructor /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(basic_json&& other) noexcept - : json_base_class_t(std::forward(other)), - m_data(std::move(other.m_data)) + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) { // check that passed value is valid other.assert_invariant(false); // invalidate payload - other.m_data.m_type = value_t::null; - other.m_data.m_value = {}; + other.m_type = value_t::null; + other.m_value = {}; set_parents(); assert_invariant(); @@ -20458,17 +20398,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value&& std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_assignable::value + std::is_nothrow_move_assignable::value ) { // check that passed value is valid other.assert_invariant(); using std::swap; - swap(m_data.m_type, other.m_data.m_type); - swap(m_data.m_value, other.m_data.m_value); - json_base_class_t::operator=(std::move(other)); + swap(m_type, other.m_type); + swap(m_value, other.m_value); set_parents(); assert_invariant(); @@ -20480,6 +20418,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec ~basic_json() noexcept { assert_invariant(false); + m_value.destroy(m_type); } /// @} @@ -20519,7 +20458,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/type/ constexpr value_t type() const noexcept { - return m_data.m_type; + return m_type; } /// @brief return whether type is primitive @@ -20540,14 +20479,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_null/ constexpr bool is_null() const noexcept { - return m_data.m_type == value_t::null; + return m_type == value_t::null; } /// @brief return whether value is a boolean /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ constexpr bool is_boolean() const noexcept { - return m_data.m_type == value_t::boolean; + return m_type == value_t::boolean; } /// @brief return whether value is a number @@ -20561,63 +20500,63 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ constexpr bool is_number_integer() const noexcept { - return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; + return m_type == value_t::number_integer || m_type == value_t::number_unsigned; } /// @brief return whether value is an unsigned integer number /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ constexpr bool is_number_unsigned() const noexcept { - return m_data.m_type == value_t::number_unsigned; + return m_type == value_t::number_unsigned; } /// @brief return whether value is a floating-point number /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ constexpr bool is_number_float() const noexcept { - return m_data.m_type == value_t::number_float; + return m_type == value_t::number_float; } /// @brief return whether value is an object /// @sa https://json.nlohmann.me/api/basic_json/is_object/ constexpr bool is_object() const noexcept { - return m_data.m_type == value_t::object; + return m_type == value_t::object; } /// @brief return whether value is an array /// @sa https://json.nlohmann.me/api/basic_json/is_array/ constexpr bool is_array() const noexcept { - return m_data.m_type == value_t::array; + return m_type == value_t::array; } /// @brief return whether value is a string /// @sa https://json.nlohmann.me/api/basic_json/is_string/ constexpr bool is_string() const noexcept { - return m_data.m_type == value_t::string; + return m_type == value_t::string; } /// @brief return whether value is a binary array /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ constexpr bool is_binary() const noexcept { - return m_data.m_type == value_t::binary; + return m_type == value_t::binary; } /// @brief return whether value is discarded /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ constexpr bool is_discarded() const noexcept { - return m_data.m_type == value_t::discarded; + return m_type == value_t::discarded; } /// @brief return the type of the JSON value (implicit) /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ constexpr operator value_t() const noexcept { - return m_data.m_type; + return m_type; } /// @} @@ -20632,7 +20571,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (JSON_HEDLEY_LIKELY(is_boolean())) { - return m_data.m_value.boolean; + return m_value.boolean; } JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); @@ -20641,97 +20580,97 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// get a pointer to the value (object) object_t* get_impl_ptr(object_t* /*unused*/) noexcept { - return is_object() ? m_data.m_value.object : nullptr; + return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { - return is_object() ? m_data.m_value.object : nullptr; + return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) array_t* get_impl_ptr(array_t* /*unused*/) noexcept { - return is_array() ? m_data.m_value.array : nullptr; + return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { - return is_array() ? m_data.m_value.array : nullptr; + return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) string_t* get_impl_ptr(string_t* /*unused*/) noexcept { - return is_string() ? m_data.m_value.string : nullptr; + return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { - return is_string() ? m_data.m_value.string : nullptr; + return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { - return is_boolean() ? &m_data.m_value.boolean : nullptr; + return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { - return is_boolean() ? &m_data.m_value.boolean : nullptr; + return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { - return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { - return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { - return is_number_float() ? &m_data.m_value.number_float : nullptr; + return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { - return is_number_float() ? &m_data.m_value.number_float : nullptr; + return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (binary) binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept { - return is_binary() ? m_data.m_value.binary : nullptr; + return is_binary() ? m_value.binary : nullptr; } /// get a pointer to the value (binary) constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept { - return is_binary() ? m_data.m_value.binary : nullptr; + return is_binary() ? m_value.binary : nullptr; } /*! @@ -21114,7 +21053,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) detail::negation>, #endif -#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI +#if defined(JSON_HAS_CPP_17) detail::negation>, #endif detail::is_detected_lazy @@ -21151,6 +21090,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + //////////////////// // element access // //////////////////// @@ -21168,7 +21108,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return set_parent(m_data.m_value.array->at(idx)); + return set_parent(m_value.array->at(idx)); } JSON_CATCH (std::out_of_range&) { @@ -21191,7 +21131,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return m_data.m_value.array->at(idx); + return m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { @@ -21215,8 +21155,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(key); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(key); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -21235,8 +21175,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(std::forward(key)); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(std::forward(key)); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -21253,8 +21193,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(key); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(key); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -21273,8 +21213,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(std::forward(key)); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(std::forward(key)); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -21288,8 +21228,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value.array = create(); + m_type = value_t::array; + m_value.array = create(); assert_invariant(); } @@ -21297,17 +21237,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_array())) { // fill up array with null values if given idx is outside range - if (idx >= m_data.m_value.array->size()) + if (idx >= m_value.array->size()) { #if JSON_DIAGNOSTICS // remember array size & capacity before resizing - const auto old_size = m_data.m_value.array->size(); - const auto old_capacity = m_data.m_value.array->capacity(); + const auto old_size = m_value.array->size(); + const auto old_capacity = m_value.array->capacity(); #endif - m_data.m_value.array->resize(idx + 1); + m_value.array->resize(idx + 1); #if JSON_DIAGNOSTICS - if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -21321,7 +21261,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec assert_invariant(); } - return m_data.m_value.array->operator[](idx); + return m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -21334,7 +21274,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) { - return m_data.m_value.array->operator[](idx); + return m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -21347,15 +21287,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value.object = create(); + m_type = value_t::object; + m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_data.m_value.object->emplace(std::move(key), nullptr); + auto result = m_value.object->emplace(std::move(key), nullptr); return set_parent(result.first->second); } @@ -21369,8 +21309,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_data.m_value.object->find(key); - JSON_ASSERT(it != m_data.m_value.object->end()); + auto it = m_value.object->find(key); + JSON_ASSERT(it != m_value.object->end()); return it->second; } @@ -21400,15 +21340,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value.object = create(); + m_type = value_t::object; + m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_data.m_value.object->emplace(std::forward(key), nullptr); + auto result = m_value.object->emplace(std::forward(key), nullptr); return set_parent(result.first->second); } @@ -21424,8 +21364,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_data.m_value.object->find(std::forward(key)); - JSON_ASSERT(it != m_data.m_value.object->end()); + auto it = m_value.object->find(std::forward(key)); + JSON_ASSERT(it != m_value.object->end()); return it->second; } @@ -21662,7 +21602,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_data.m_type) + switch (m_type) { case value_t::boolean: case value_t::number_float: @@ -21679,32 +21619,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.string); - std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); - m_data.m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.binary); - std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); - m_data.m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; } - m_data.m_type = value_t::null; + m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); + result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); + result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -21732,7 +21672,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_data.m_type) + switch (m_type) { case value_t::boolean: case value_t::number_float: @@ -21750,33 +21690,33 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.string); - std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); - m_data.m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.binary); - std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); - m_data.m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; } - m_data.m_type = value_t::null; + m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, + result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, + result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; } @@ -21801,7 +21741,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - return m_data.m_value.object->erase(std::forward(key)); + return m_value.object->erase(std::forward(key)); } template < typename KeyType, detail::enable_if_t < @@ -21814,10 +21754,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - const auto it = m_data.m_value.object->find(std::forward(key)); - if (it != m_data.m_value.object->end()) + const auto it = m_value.object->find(std::forward(key)); + if (it != m_value.object->end()) { - m_data.m_value.object->erase(it); + m_value.object->erase(it); return 1; } return 0; @@ -21855,7 +21795,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); } - m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast(idx)); + m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else { @@ -21865,6 +21805,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + //////////// // lookup // //////////// @@ -21880,7 +21821,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(key); + result.m_it.object_iterator = m_value.object->find(key); } return result; @@ -21894,7 +21835,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(key); + result.m_it.object_iterator = m_value.object->find(key); } return result; @@ -21910,7 +21851,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_value.object->find(std::forward(key)); } return result; @@ -21926,7 +21867,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_value.object->find(std::forward(key)); } return result; @@ -21937,7 +21878,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(const typename object_t::key_type& key) const { // return 0 for all nonobject types - return is_object() ? m_data.m_value.object->count(key) : 0; + return is_object() ? m_value.object->count(key) : 0; } /// @brief returns the number of occurrences of a key in a JSON object @@ -21947,14 +21888,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(KeyType && key) const { // return 0 for all nonobject types - return is_object() ? m_data.m_value.object->count(std::forward(key)) : 0; + return is_object() ? m_value.object->count(std::forward(key)) : 0; } /// @brief check the existence of an element in a JSON object /// @sa https://json.nlohmann.me/api/basic_json/contains/ bool contains(const typename object_t::key_type& key) const { - return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); + return is_object() && m_value.object->find(key) != m_value.object->end(); } /// @brief check the existence of an element in a JSON object @@ -21963,7 +21904,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::is_usable_as_basic_json_key_type::value, int> = 0> bool contains(KeyType && key) const { - return is_object() && m_data.m_value.object->find(std::forward(key)) != m_data.m_value.object->end(); + return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); } /// @brief check the existence of an element in a JSON object given a JSON pointer @@ -21982,6 +21923,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + /////////////// // iterators // /////////////// @@ -22120,6 +22062,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + ////////////// // capacity // ////////////// @@ -22131,7 +22074,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/empty/ bool empty() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::null: { @@ -22142,13 +22085,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::empty() - return m_data.m_value.array->empty(); + return m_value.array->empty(); } case value_t::object: { // delegate call to object_t::empty() - return m_data.m_value.object->empty(); + return m_value.object->empty(); } case value_t::string: @@ -22170,7 +22113,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/size/ size_type size() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::null: { @@ -22181,13 +22124,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::size() - return m_data.m_value.array->size(); + return m_value.array->size(); } case value_t::object: { // delegate call to object_t::size() - return m_data.m_value.object->size(); + return m_value.object->size(); } case value_t::string: @@ -22209,18 +22152,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/max_size/ size_type max_size() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::array: { // delegate call to array_t::max_size() - return m_data.m_value.array->max_size(); + return m_value.array->max_size(); } case value_t::object: { // delegate call to object_t::max_size() - return m_data.m_value.object->max_size(); + return m_value.object->max_size(); } case value_t::null: @@ -22241,6 +22184,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + /////////////// // modifiers // /////////////// @@ -22252,53 +22196,53 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/clear/ void clear() noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::number_integer: { - m_data.m_value.number_integer = 0; + m_value.number_integer = 0; break; } case value_t::number_unsigned: { - m_data.m_value.number_unsigned = 0; + m_value.number_unsigned = 0; break; } case value_t::number_float: { - m_data.m_value.number_float = 0.0; + m_value.number_float = 0.0; break; } case value_t::boolean: { - m_data.m_value.boolean = false; + m_value.boolean = false; break; } case value_t::string: { - m_data.m_value.string->clear(); + m_value.string->clear(); break; } case value_t::binary: { - m_data.m_value.binary->clear(); + m_value.binary->clear(); break; } case value_t::array: { - m_data.m_value.array->clear(); + m_value.array->clear(); break; } case value_t::object: { - m_data.m_value.object->clear(); + m_value.object->clear(); break; } @@ -22322,15 +22266,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value = value_t::array; + m_type = value_t::array; + m_value = value_t::array; assert_invariant(); } // add element to array (move semantics) - const auto old_capacity = m_data.m_value.array->capacity(); - m_data.m_value.array->push_back(std::move(val)); - set_parent(m_data.m_value.array->back(), old_capacity); + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(std::move(val)); + set_parent(m_value.array->back(), old_capacity); // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor } @@ -22355,15 +22299,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value = value_t::array; + m_type = value_t::array; + m_value = value_t::array; assert_invariant(); } // add element to array - const auto old_capacity = m_data.m_value.array->capacity(); - m_data.m_value.array->push_back(val); - set_parent(m_data.m_value.array->back(), old_capacity); + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(val); + set_parent(m_value.array->back(), old_capacity); } /// @brief add an object to an array @@ -22387,13 +22331,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value = value_t::object; + m_type = value_t::object; + m_value = value_t::object; assert_invariant(); } // add element to object - auto res = m_data.m_value.object->insert(val); + auto res = m_value.object->insert(val); set_parent(res.first->second); } @@ -22443,15 +22387,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value = value_t::array; + m_type = value_t::array; + m_value = value_t::array; assert_invariant(); } // add element to array (perfect forwarding) - const auto old_capacity = m_data.m_value.array->capacity(); - m_data.m_value.array->emplace_back(std::forward(args)...); - return set_parent(m_data.m_value.array->back(), old_capacity); + const auto old_capacity = m_value.array->capacity(); + m_value.array->emplace_back(std::forward(args)...); + return set_parent(m_value.array->back(), old_capacity); } /// @brief add an object to an object if key does not exist @@ -22468,13 +22412,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value = value_t::object; + m_type = value_t::object; + m_value = value_t::object; assert_invariant(); } // add element to array (perfect forwarding) - auto res = m_data.m_value.object->emplace(std::forward(args)...); + auto res = m_value.object->emplace(std::forward(args)...); set_parent(res.first->second); // create result iterator and set iterator to the result of emplace @@ -22492,14 +22436,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec iterator insert_iterator(const_iterator pos, Args&& ... args) { iterator result(this); - JSON_ASSERT(m_data.m_value.array != nullptr); + JSON_ASSERT(m_value.array != nullptr); - auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); - m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); - result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; + auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_value.array->begin() + insert_pos; // This could have been written as: - // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. set_parents(); @@ -22626,7 +22570,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); } - m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); } /// @brief updates a JSON object from another object, overwriting existing keys @@ -22643,8 +22587,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value.object = create(); + m_type = value_t::object; + m_value.object = create(); assert_invariant(); } @@ -22669,16 +22613,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (merge_objects && it.value().is_object()) { - auto it2 = m_data.m_value.object->find(it.key()); - if (it2 != m_data.m_value.object->end()) + auto it2 = m_value.object->find(it.key()); + if (it2 != m_value.object->end()) { it2->second.update(it.value(), true); continue; } } - m_data.m_value.object->operator[](it.key()) = it.value(); + m_value.object->operator[](it.key()) = it.value(); #if JSON_DIAGNOSTICS - m_data.m_value.object->operator[](it.key()).m_parent = this; + m_value.object->operator[](it.key()).m_parent = this; #endif } } @@ -22688,12 +22632,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void swap(reference other) noexcept ( std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value ) { - std::swap(m_data.m_type, other.m_data.m_type); - std::swap(m_data.m_value, other.m_data.m_value); + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); set_parents(); other.set_parents(); @@ -22705,7 +22649,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec friend void swap(reference left, reference right) noexcept ( std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value ) { @@ -22714,13 +22658,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(array_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) { using std::swap; - swap(*(m_data.m_value.array), other); + swap(*(m_value.array), other); } else { @@ -22730,13 +22674,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(object_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { using std::swap; - swap(*(m_data.m_value.object), other); + swap(*(m_value.object), other); } else { @@ -22746,13 +22690,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(string_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for strings if (JSON_HEDLEY_LIKELY(is_string())) { using std::swap; - swap(*(m_data.m_value.string), other); + swap(*(m_value.string), other); } else { @@ -22762,13 +22706,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(binary_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for strings if (JSON_HEDLEY_LIKELY(is_binary())) { using std::swap; - swap(*(m_data.m_value.binary), other); + swap(*(m_value.binary), other); } else { @@ -22784,7 +22728,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_binary())) { using std::swap; - swap(*(m_data.m_value.binary), other); + swap(*(m_value.binary), other); } else { @@ -22812,31 +22756,31 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec switch (lhs_type) \ { \ case value_t::array: \ - return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ + return (*lhs.m_value.array) op (*rhs.m_value.array); \ \ case value_t::object: \ - return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ + return (*lhs.m_value.object) op (*rhs.m_value.object); \ \ case value_t::null: \ return (null_result); \ \ case value_t::string: \ - return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ + return (*lhs.m_value.string) op (*rhs.m_value.string); \ \ case value_t::boolean: \ - return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ + return (lhs.m_value.boolean) op (rhs.m_value.boolean); \ \ case value_t::number_integer: \ - return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ + return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \ \ case value_t::number_unsigned: \ - return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ + return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \ \ case value_t::number_float: \ - return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ + return (lhs.m_value.number_float) op (rhs.m_value.number_float); \ \ case value_t::binary: \ - return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ + return (*lhs.m_value.binary) op (*rhs.m_value.binary); \ \ case value_t::discarded: \ default: \ @@ -22845,27 +22789,27 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ + return static_cast(lhs.m_value.number_integer) op rhs.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ { \ - return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_integer); \ + return lhs.m_value.number_float op static_cast(rhs.m_value.number_integer); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ + return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_unsigned); \ + return lhs.m_value.number_float op static_cast(rhs.m_value.number_unsigned); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ { \ - return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ + return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \ } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_data.m_value.number_integer op static_cast(rhs.m_data.m_value.number_unsigned); \ + return lhs.m_value.number_integer op static_cast(rhs.m_value.number_unsigned); \ } \ else if(compares_unordered(lhs, rhs))\ {\ @@ -22882,8 +22826,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // an operation is computed as an odd number of inverses of others static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept { - if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) - || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) + if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number()) + || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number())) { return true; } @@ -23227,6 +23171,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #endif // JSON_NO_IO /// @} + ///////////////////// // deserialization // ///////////////////// @@ -23383,7 +23328,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_HEDLEY_RETURNS_NON_NULL const char* type_name() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::null: return "null"; @@ -23407,43 +23352,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } } + JSON_PRIVATE_UNLESS_TESTED: ////////////////////// // member variables // ////////////////////// - struct data - { - /// the type of the current element - value_t m_type = value_t::null; + /// the type of the current element + value_t m_type = value_t::null; - /// the value of the current element - json_value m_value = {}; - - data(const value_t v) - : m_type(v), m_value(v) - { - } - - data(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - } - - data() noexcept = default; - data(data&&) noexcept = default; - data(const data&) noexcept = delete; - data& operator=(data&&) noexcept = delete; - data& operator=(const data&) noexcept = delete; - - ~data() noexcept - { - m_value.destroy(m_type); - } - }; - - data m_data = {}; + /// the value of the current element + json_value m_value = {}; #if JSON_DIAGNOSTICS /// a pointer to a parent value (for debugging purposes) @@ -23624,6 +23543,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); } + JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) static basic_json from_cbor(detail::span_input_adapter&& i, @@ -23747,6 +23667,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return res ? result : basic_json(value_t::discarded); } + /// @brief create a JSON value from an input in BJData format /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ template @@ -23969,7 +23890,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // make sure the top element of the pointer exists - json_pointer const top_pointer = ptr.top(); + json_pointer top_pointer = ptr.top(); if (top_pointer != ptr) { result.at(top_pointer); @@ -23981,7 +23902,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // parent must exist when performing patch add per RFC6902 specs basic_json& parent = result.at(ptr); - switch (parent.m_data.m_type) + switch (parent.m_type) { case value_t::null: case value_t::object: @@ -24027,7 +23948,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec }; // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [this, & result](json_pointer & ptr) + const auto operation_remove = [this, &result](json_pointer & ptr) { // get reference to parent of JSON pointer ptr const auto last_path = ptr.back(); @@ -24070,13 +23991,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec bool string_type) -> basic_json & { // find value - auto it = val.m_data.m_value.object->find(member); + auto it = val.m_value.object->find(member); // context-sensitive error message const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) + if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) { // NOLINTNEXTLINE(performance-inefficient-string-concatenation) JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); @@ -24131,7 +24052,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec json_pointer from_ptr(from_path); // the "from" location must exist - use at() - basic_json const v = result.at(from_ptr); + basic_json v = result.at(from_ptr); // The move operation is functionally identical to a // "remove" operation on the "from" location, followed @@ -24148,7 +24069,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const json_pointer from_ptr(from_path); // the "from" location must exist - use at() - basic_json const v = result.at(from_ptr); + basic_json v = result.at(from_ptr); // The copy is functionally identical to an "add" // operation at the target location using the value @@ -24390,11 +24311,7 @@ inline namespace json_literals /// @brief user-defined string literal for JSON values /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ JSON_HEDLEY_NON_NULL(1) -#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - inline nlohmann::json operator ""_json(const char* s, std::size_t n) -#else - inline nlohmann::json operator "" _json(const char* s, std::size_t n) -#endif +inline nlohmann::json operator "" _json(const char* s, std::size_t n) { return nlohmann::json::parse(s, s + n); } @@ -24402,11 +24319,7 @@ JSON_HEDLEY_NON_NULL(1) /// @brief user-defined string literal for JSON pointer /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ JSON_HEDLEY_NON_NULL(1) -#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n) -#else - inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -#endif +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) { return nlohmann::json::json_pointer(std::string(s, n)); } @@ -24425,7 +24338,7 @@ namespace std // NOLINT(cert-dcl58-cpp) /// @brief hash value for JSON objects /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct hash // NOLINT(cert-dcl58-cpp) +struct hash { std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const { @@ -24458,8 +24371,8 @@ struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', /// @brief exchanges the values of two JSON objects /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ NLOHMANN_BASIC_JSON_TPL_DECLARATION -inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) - is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) +inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name) + is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression) is_nothrow_move_assignable::value) { j1.swap(j2); @@ -24470,13 +24383,8 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC } // namespace std #if JSON_USE_GLOBAL_UDLS - #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) - using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) - #else - using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) - using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) - #endif + using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) + using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) #endif // #include @@ -24520,7 +24428,6 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC #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 diff --git a/app/src/main/cpp/libcxx b/app/src/main/cpp/libcxx new file mode 160000 index 0000000..12c8f4e --- /dev/null +++ b/app/src/main/cpp/libcxx @@ -0,0 +1 @@ +Subproject commit 12c8f4e93f196a700137e983dcceeac43cf807f2 diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp index b902e43..034ad45 100644 --- a/app/src/main/cpp/main.cpp +++ b/app/src/main/cpp/main.cpp @@ -4,15 +4,15 @@ #include #include "zygisk.hpp" -#include "dobby.h" +#include "shadowhook.h" #include "json.hpp" +#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__) + #define DEX_FILE_PATH "/data/adb/modules/playintegrityfix/classes.dex" #define PROP_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json" -#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__) - static std::string FIRST_API_LEVEL, SECURITY_PATCH; typedef void (*T_Callback)(void *, const char *, const char *, uint32_t); @@ -58,14 +58,39 @@ my_system_property_read_callback(const prop_info *pi, T_Callback callback, void } static void doHook() { - void *handle = DobbySymbolResolver("libc.so", "__system_property_read_callback"); + shadowhook_init(SHADOWHOOK_MODE_UNIQUE, false); + void *handle = shadowhook_hook_sym_name( + "libc.so", + "__system_property_read_callback", + reinterpret_cast(my_system_property_read_callback), + reinterpret_cast(&o_system_property_read_callback) + ); if (handle == nullptr) { LOGD("Couldn't find '__system_property_read_callback' handle. Report to @chiteroman"); return; } LOGD("Found '__system_property_read_callback' handle at %p", handle); - DobbyHook(handle, reinterpret_cast(my_system_property_read_callback), - reinterpret_cast(&o_system_property_read_callback)); +} + +static void sendVector(int fd, const std::vector &vec) { + // Send the size of the vector + size_t size = vec.size(); + write(fd, &size, sizeof(size_t)); + + // Send the vector data + write(fd, vec.data(), size); +} + +static std::vector receiveVector(int fd) { + // Receive the size of the vector + size_t size; + read(fd, &size, sizeof(size_t)); + + // Receive the vector data + std::vector vec(size); + read(fd, vec.data(), size); + + return vec; } class PlayIntegrityFix : public zygisk::ModuleBase { @@ -99,47 +124,32 @@ public: return; } - ssize_t size; - char buffer[10000]; int fd = api->connectCompanion(); - size = read(fd, buffer, sizeof(buffer)); - - if (size > 0) { - moduleDex.insert(moduleDex.end(), buffer, buffer + size); - } else { - LOGD("Couldn't load classes.dex file in memory"); - close(fd); - api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); - return; - } - - lseek(fd, 0, SEEK_SET); - - size = read(fd, buffer, sizeof(buffer)); - - if (size > 0) { - jsonStr.insert(jsonStr.end(), buffer, buffer + size); - } else { - LOGD("Couldn't load pif.json file in memory"); - } + dexVector = receiveVector(fd); + propVector = receiveVector(fd); close(fd); - LOGD("Received 'classes.dex' file from socket: %d bytes", - static_cast(moduleDex.size())); + LOGD("Read from file descriptor file 'classes.dex' -> %d bytes", + static_cast(dexVector.size())); + LOGD("Read from file descriptor file 'pif.json' -> %d bytes", + static_cast(propVector.size())); - LOGD("Received 'pif.json' file from socket: %d bytes", static_cast(jsonStr.size())); + if (dexVector.empty() || propVector.empty()) api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); } void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override { - if (moduleDex.empty()) return; + if (dexVector.empty() || propVector.empty()) return; readJson(); inject(); doHook(); + + dexVector.clear(); + propVector.clear(); } void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override { @@ -149,11 +159,11 @@ public: private: zygisk::Api *api = nullptr; JNIEnv *env = nullptr; - std::vector moduleDex; - std::string jsonStr; + std::vector dexVector, propVector; void readJson() { - nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false); + std::string data(propVector.cbegin(), propVector.cend()); + nlohmann::json json = nlohmann::json::parse(data, nullptr, false, true); auto getStringFromJson = [&json](const std::string &key) { return json.contains(key) && !json[key].is_null() ? json[key].get() @@ -162,8 +172,6 @@ private: SECURITY_PATCH = getStringFromJson("SECURITY_PATCH"); FIRST_API_LEVEL = getStringFromJson("FIRST_API_LEVEL"); - - json.clear(); } void inject() { @@ -177,8 +185,8 @@ private: auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader"); auto dexClInit = env->GetMethodID(dexClClass, "", "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); - auto buffer = env->NewDirectByteBuffer(moduleDex.data(), - static_cast(moduleDex.size())); + auto buffer = env->NewDirectByteBuffer(dexVector.data(), + static_cast(dexVector.size())); auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader); LOGD("load class"); @@ -192,15 +200,13 @@ private: LOGD("read json"); auto readProps = env->GetStaticMethodID(entryClass, "readJson", "(Ljava/lang/String;)V"); - auto javaStr = env->NewStringUTF(jsonStr.c_str()); + std::string data(propVector.cbegin(), propVector.cend()); + auto javaStr = env->NewStringUTF(data.c_str()); env->CallStaticVoidMethod(entryClass, readProps, javaStr); LOGD("call init"); auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V"); env->CallStaticVoidMethod(entryClass, entryInit); - - moduleDex.clear(); - jsonStr.clear(); } }; @@ -210,13 +216,17 @@ static void companion(int fd) { std::vector dexVector((std::istreambuf_iterator(dex)), std::istreambuf_iterator()); - std::vector propVector((std::istreambuf_iterator(prop)), std::istreambuf_iterator()); - write(fd, dexVector.data(), dexVector.size()); - lseek(fd, 0, SEEK_SET); - write(fd, propVector.data(), propVector.size()); + dex.close(); + prop.close(); + + sendVector(fd, dexVector); + sendVector(fd, propVector); + + dexVector.clear(); + propVector.clear(); } REGISTER_ZYGISK_MODULE(PlayIntegrityFix) diff --git a/app/src/main/cpp/shadowhook/arch/arm/sh_a32.c b/app/src/main/cpp/shadowhook/arch/arm/sh_a32.c new file mode 100644 index 0000000..d71e4f8 --- /dev/null +++ b/app/src/main/cpp/shadowhook/arch/arm/sh_a32.c @@ -0,0 +1,446 @@ +// Copyright (c) 2021-2022 ByteDance Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +// Created by Kelun Cai (caikelun@bytedance.com) on 2021-04-11. + +#include "sh_a32.h" + +#include +#include +#include + +#include "sh_log.h" + +// https://developer.arm.com/documentation/ddi0406/latest +// https://developer.arm.com/documentation/ddi0597/latest + +typedef enum { + IGNORED = 0, + B_A1, + BX_A1, + BL_IMM_A1, + BLX_IMM_A2, + ADD_REG_A1, + ADD_REG_PC_A1, + SUB_REG_A1, + SUB_REG_PC_A1, + ADR_A1, + ADR_A2, + MOV_REG_A1, + MOV_REG_PC_A1, + LDR_LIT_A1, + LDR_LIT_PC_A1, + LDRB_LIT_A1, + LDRD_LIT_A1, + LDRH_LIT_A1, + LDRSB_LIT_A1, + LDRSH_LIT_A1, + LDR_REG_A1, + LDR_REG_PC_A1, + LDRB_REG_A1, + LDRD_REG_A1, + LDRH_REG_A1, + LDRSB_REG_A1, + LDRSH_REG_A1 +} sh_a32_type_t; + +static sh_a32_type_t sh_a32_get_type(uint32_t inst) { + if (((inst & 0x0F000000u) == 0x0A000000) && ((inst & 0xF0000000) != 0xF0000000)) + return B_A1; + else if (((inst & 0x0FFFFFFFu) == 0x012FFF1F) && ((inst & 0xF0000000) != 0xF0000000)) + return BX_A1; + else if (((inst & 0x0F000000u) == 0x0B000000) && ((inst & 0xF0000000) != 0xF0000000)) + return BL_IMM_A1; + else if ((inst & 0xFE000000) == 0xFA000000) + return BLX_IMM_A2; + else if (((inst & 0x0FE00010u) == 0x00800000) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x0010F000u) != 0x0010F000) && ((inst & 0x000F0000u) != 0x000D0000) && + (((inst & 0x000F0000u) == 0x000F0000) || ((inst & 0x0000000Fu) == 0x0000000F))) + return ((inst & 0x0000F000u) == 0x0000F000) ? ADD_REG_PC_A1 : ADD_REG_A1; + else if (((inst & 0x0FE00010u) == 0x00400000) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x0010F000u) != 0x0010F000) && ((inst & 0x000F0000u) != 0x000D0000) && + (((inst & 0x000F0000u) == 0x000F0000) || ((inst & 0x0000000Fu) == 0x0000000F))) + return ((inst & 0x0000F000u) == 0x0000F000) ? SUB_REG_PC_A1 : SUB_REG_A1; + else if (((inst & 0x0FFF0000u) == 0x028F0000) && ((inst & 0xF0000000) != 0xF0000000)) + return ADR_A1; + else if (((inst & 0x0FFF0000u) == 0x024F0000) && ((inst & 0xF0000000) != 0xF0000000)) + return ADR_A2; + else if (((inst & 0x0FEF001Fu) == 0x01A0000F) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x0010F000u) != 0x0010F000) && + (!(((inst & 0x0000F000u) == 0x0000F000) && ((inst & 0x00000FF0u) != 0x00000000)))) + return ((inst & 0x0000F000u) == 0x0000F000) ? MOV_REG_PC_A1 : MOV_REG_A1; + else if (((inst & 0x0F7F0000u) == 0x051F0000) && ((inst & 0xF0000000) != 0xF0000000)) + return ((inst & 0x0000F000u) == 0x0000F000) ? LDR_LIT_PC_A1 : LDR_LIT_A1; + else if (((inst & 0x0F7F0000u) == 0x055F0000) && ((inst & 0xF0000000) != 0xF0000000)) + return LDRB_LIT_A1; + else if (((inst & 0x0F7F00F0u) == 0x014F00D0) && ((inst & 0xF0000000) != 0xF0000000)) + return LDRD_LIT_A1; + else if (((inst & 0x0F7F00F0u) == 0x015F00B0) && ((inst & 0xF0000000) != 0xF0000000)) + return LDRH_LIT_A1; + else if (((inst & 0x0F7F00F0u) == 0x015F00D0) && ((inst & 0xF0000000) != 0xF0000000)) + return LDRSB_LIT_A1; + else if (((inst & 0x0F7F00F0u) == 0x015F00F0) && ((inst & 0xF0000000) != 0xF0000000)) + return LDRSH_LIT_A1; + else if (((inst & 0x0E5F0010u) == 0x061F0000) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x01200000u) != 0x00200000)) + return ((inst & 0x0000F000u) == 0x0000F000) ? LDR_REG_PC_A1 : LDR_REG_A1; + else if (((inst & 0x0E5F0010u) == 0x065F0000) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x01200000u) != 0x00200000)) + return LDRB_REG_A1; + else if (((inst & 0x0E5F0FF0u) == 0x000F00D0) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x01200000u) != 0x00200000)) + return LDRD_REG_A1; + else if (((inst & 0x0E5F0FF0u) == 0x001F00B0) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x01200000u) != 0x00200000)) + return LDRH_REG_A1; + else if (((inst & 0x0E5F0FF0u) == 0x001F00D0) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x01200000u) != 0x00200000)) + return LDRSB_REG_A1; + else if (((inst & 0x0E5F0FF0u) == 0x001F00F0) && ((inst & 0xF0000000) != 0xF0000000) && + ((inst & 0x01200000u) != 0x00200000)) + return LDRSH_REG_A1; + else + return IGNORED; +} + +size_t sh_a32_get_rewrite_inst_len(uint32_t inst) { + static uint8_t map[] = { + 4, // IGNORED + 12, // B_A1 + 12, // BX_A1 + 16, // BL_IMM_A1 + 16, // BLX_IMM_A2 + 32, // ADD_REG_A1 + 32, // ADD_REG_PC_A1 + 32, // SUB_REG_A1 + 32, // SUB_REG_PC_A1 + 12, // ADR_A1 + 12, // ADR_A2 + 32, // MOV_REG_A1 + 12, // MOV_REG_PC_A1 + 24, // LDR_LIT_A1 + 36, // LDR_LIT_PC_A1 + 24, // LDRB_LIT_A1 + 24, // LDRD_LIT_A1 + 24, // LDRH_LIT_A1 + 24, // LDRSB_LIT_A1 + 24, // LDRSH_LIT_A1 + 32, // LDR_REG_A1 + 36, // LDR_REG_PC_A1 + 32, // LDRB_REG_A1 + 32, // LDRD_REG_A1 + 32, // LDRH_REG_A1 + 32, // LDRSB_REG_A1 + 32 // LDRSH_REG_A1 + }; + + return (size_t)(map[sh_a32_get_type(inst)]); +} + +static bool sh_a32_is_addr_need_fix(uintptr_t addr, sh_a32_rewrite_info_t *rinfo) { + return (rinfo->overwrite_start_addr <= addr && addr < rinfo->overwrite_end_addr); +} + +static uintptr_t sh_a32_fix_addr(uintptr_t addr, sh_a32_rewrite_info_t *rinfo) { + if (rinfo->overwrite_start_addr <= addr && addr < rinfo->overwrite_end_addr) { + uintptr_t cursor_addr = rinfo->overwrite_start_addr; + size_t offset = 0; + for (size_t i = 0; i < rinfo->rewrite_inst_lens_cnt; i++) { + if (cursor_addr >= addr) break; + cursor_addr += 4; + offset += rinfo->rewrite_inst_lens[i]; + } + uintptr_t fixed_addr = (uintptr_t)rinfo->rewrite_buf + offset; + SH_LOG_INFO("a32 rewrite: fix addr %" PRIxPTR " -> %" PRIxPTR, addr, fixed_addr); + return fixed_addr; + } + + return addr; +} + +static size_t sh_a32_rewrite_b(uint32_t *buf, uint32_t inst, uintptr_t pc, sh_a32_type_t type, + sh_a32_rewrite_info_t *rinfo) { + uint32_t cond; + if (type == B_A1 || type == BL_IMM_A1 || type == BX_A1) + cond = SH_UTIL_GET_BITS_32(inst, 31, 28); + else + // type == BLX_IMM_A2 + cond = 0xE; // 1110 None (AL) + + uint32_t addr; + if (type == B_A1 || type == BL_IMM_A1) { + uint32_t imm24 = SH_UTIL_GET_BITS_32(inst, 23, 0); + uint32_t imm32 = SH_UTIL_SIGN_EXTEND_32(imm24 << 2u, 26u); + addr = pc + imm32; // arm -> arm + } else if (type == BLX_IMM_A2) { + uint32_t h = SH_UTIL_GET_BIT_32(inst, 24); + uint32_t imm24 = SH_UTIL_GET_BITS_32(inst, 23, 0); + uint32_t imm32 = SH_UTIL_SIGN_EXTEND_32((imm24 << 2u) | (h << 1u), 26u); + addr = SH_UTIL_SET_BIT0(pc + imm32); // arm -> thumb + } else { + // type == BX_A1 + // BX PC + // PC must be even, and the "arm" instruction must be at a 4-byte aligned address, + // so the instruction set must keep "arm" unchanged. + addr = pc; // arm -> arm + } + addr = sh_a32_fix_addr(addr, rinfo); + + size_t idx = 0; + if (type == BL_IMM_A1 || type == BLX_IMM_A2) { + buf[idx++] = 0x028FE008u | (cond << 28u); // ADD LR, PC, #8 + } + buf[idx++] = 0x059FF000u | (cond << 28u); // LDR PC, [PC, #0] + buf[idx++] = 0xEA000000; // B #0 + buf[idx++] = addr; + return idx * 4; // 12 or 16 +} + +static size_t sh_a32_rewrite_add_or_sub(uint32_t *buf, uint32_t inst, uintptr_t pc) { + // ADD{S} , , PC{, } or ADD{S} , PC, {, } + // SUB{S} , , PC{, } or SUB{S} , PC, {, } + uint32_t cond = SH_UTIL_GET_BITS_32(inst, 31, 28); + uint32_t rn = SH_UTIL_GET_BITS_32(inst, 19, 16); + uint32_t rm = SH_UTIL_GET_BITS_32(inst, 3, 0); + uint32_t rd = SH_UTIL_GET_BITS_32(inst, 15, 12); + + uint32_t rx; // r0 - r3 + for (rx = 3;; --rx) + if (rx != rn && rx != rm && rx != rd) break; + + if (rd == 0xF) // Rd == PC + { + uint32_t ry; // r0 - r4 + for (ry = 4;; --ry) + if (ry != rn && ry != rm && ry != rd && ry != rx) break; + + buf[0] = 0x0A000000u | (cond << 28u); // B #0 + buf[1] = 0xEA000005; // B #20 + buf[2] = 0xE92D8000 | (1u << rx) | (1u << ry); // PUSH {Rx, Ry, PC} + buf[3] = 0xE59F0008 | (rx << 12u); // LDR Rx, [PC, #8] + if (rn == 0xF) + // Rn == PC + buf[4] = + (inst & 0x0FF00FFFu) | 0xE0000000 | (ry << 12u) | (rx << 16u); // ADD/SUB Ry, Rx, Rm{, } + else + // Rm == PC + buf[4] = (inst & 0x0FFF0FF0u) | 0xE0000000 | (ry << 12u) | rx; // ADD/SUB Ry, Rn, Rx{, } + buf[5] = 0xE58D0008 | (ry << 12u); // STR Ry, [SP, #8] + buf[6] = 0xE8BD8000 | (1u << rx) | (1u << ry); // POP {Rx, Ry, PC} + buf[7] = pc; + return 32; + } else { + buf[0] = 0x0A000000u | (cond << 28u); // B #0 + buf[1] = 0xEA000005; // B #20 + buf[2] = 0xE52D0004 | (rx << 12u); // PUSH {Rx} + buf[3] = 0xE59F0008 | (rx << 12u); // LDR Rx, [PC, #8] + if (rn == 0xF) + // Rn == PC + buf[4] = (inst & 0x0FF0FFFFu) | 0xE0000000 | (rx << 16u); // ADD/SUB{S} Rd, Rx, Rm{, } + else + // Rm == PC + buf[4] = (inst & 0x0FFFFFF0u) | 0xE0000000 | rx; // ADD/SUB{S} Rd, Rn, Rx{, } + buf[5] = 0xE49D0004 | (rx << 12u); // POP {Rx} + buf[6] = 0xEA000000; // B #0 + buf[7] = pc; + return 32; + } +} + +static size_t sh_a32_rewrite_adr(uint32_t *buf, uint32_t inst, uintptr_t pc, sh_a32_type_t type, + sh_a32_rewrite_info_t *rinfo) { + uint32_t cond = SH_UTIL_GET_BITS_32(inst, 31, 28); + uint32_t rd = SH_UTIL_GET_BITS_32(inst, 15, 12); // r0 - r15 + uint32_t imm12 = SH_UTIL_GET_BITS_32(inst, 11, 0); + uint32_t imm32 = sh_util_arm_expand_imm(imm12); + uint32_t addr = (type == ADR_A1 ? (SH_UTIL_ALIGN_4(pc) + imm32) : (SH_UTIL_ALIGN_4(pc) - imm32)); + if (sh_a32_is_addr_need_fix(addr, rinfo)) return 0; // rewrite failed + + buf[0] = 0x059F0000u | (cond << 28u) | (rd << 12u); // LDR Rd, [PC, #0] + buf[1] = 0xEA000000; // B #0 + buf[2] = addr; + return 12; +} + +static size_t sh_a32_rewrite_mov(uint32_t *buf, uint32_t inst, uintptr_t pc) { + // MOV{S} , PC + uint32_t cond = SH_UTIL_GET_BITS_32(inst, 31, 28); + uint32_t rd = SH_UTIL_GET_BITS_32(inst, 15, 12); + uint32_t rx = (rd == 0) ? 1 : 0; + + if (rd == 0xF) // Rd == PC (MOV PC, PC) + { + buf[0] = 0x059FF000u | (cond << 28u); // LDR PC, [PC, #0] + buf[1] = 0xEA000000; // B #0 + buf[2] = pc; + return 12; + } else { + buf[0] = 0x0A000000u | (cond << 28u); // B #0 + buf[1] = 0xEA000005; // B #20 + buf[2] = 0xE52D0004 | (rx << 12u); // PUSH {Rx} + buf[3] = 0xE59F0008 | (rx << 12u); // LDR Rx, [PC, #8] + buf[4] = (inst & 0x0FFFFFF0u) | 0xE0000000 | rx; // MOV{S} Rd, Rx{, #/RRX} + buf[5] = 0xE49D0004 | (rx << 12u); // POP {Rx} + buf[6] = 0xEA000000; // B #0 + buf[7] = pc; + return 32; + } +} + +static size_t sh_a32_rewrite_ldr_lit(uint32_t *buf, uint32_t inst, uintptr_t pc, sh_a32_type_t type, + sh_a32_rewrite_info_t *rinfo) { + uint32_t cond = SH_UTIL_GET_BITS_32(inst, 31, 28); + uint32_t u = SH_UTIL_GET_BIT_32(inst, 23); + uint32_t rt = SH_UTIL_GET_BITS_16(inst, 15, 12); + + uint32_t imm32; + if (type == LDR_LIT_A1 || type == LDR_LIT_PC_A1 || type == LDRB_LIT_A1) + imm32 = SH_UTIL_GET_BITS_32(inst, 11, 0); + else + imm32 = (SH_UTIL_GET_BITS_32(inst, 11, 8) << 4u) + SH_UTIL_GET_BITS_32(inst, 3, 0); + uint32_t addr = (u ? (SH_UTIL_ALIGN_4(pc) + imm32) : (SH_UTIL_ALIGN_4(pc) - imm32)); + if (sh_a32_is_addr_need_fix(addr, rinfo)) return 0; // rewrite failed + + if (type == LDR_LIT_PC_A1 && rt == 0xF) { + // Rt == PC + buf[0] = 0x0A000000u | (cond << 28u); // B #0 + buf[1] = 0xEA000006; // B #24 + buf[2] = 0xE92D0003; // PUSH {R0, R1} + buf[3] = 0xE59F0000; // LDR R0, [PC, #0] + buf[4] = 0xEA000000; // B #0 + buf[5] = addr; // + buf[6] = 0xE5900000; // LDR R0, [R0] + buf[7] = 0xE58D0004; // STR R0, [SP, #4] + buf[8] = 0xE8BD8001; // POP {R0, PC} + return 36; + } else { + buf[0] = 0x0A000000u | (cond << 28u); // B #0 + buf[1] = 0xEA000003; // B #12 + buf[2] = 0xE59F0000 | (rt << 12u); // LDR Rt, [PC, #0] + buf[3] = 0xEA000000; // B #0 + buf[4] = addr; // +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch" + switch (type) { + case LDR_LIT_A1: + buf[5] = 0xE5900000 | (rt << 16u) | (rt << 12u); // LDR Rt, [Rt] + break; + case LDRB_LIT_A1: + buf[5] = 0xE5D00000 | (rt << 16u) | (rt << 12u); // LDRB Rt, [Rt] + break; + case LDRD_LIT_A1: + buf[5] = 0xE1C000D0 | (rt << 16u) | (rt << 12u); // LDRD Rt, [Rt] + break; + case LDRH_LIT_A1: + buf[5] = 0xE1D000B0 | (rt << 16u) | (rt << 12u); // LDRH Rt, [Rt] + break; + case LDRSB_LIT_A1: + buf[5] = 0xE1D000D0 | (rt << 16u) | (rt << 12u); // LDRSB Rt, [Rt] + break; + case LDRSH_LIT_A1: + buf[5] = 0xE1D000F0 | (rt << 16u) | (rt << 12u); // LDRSH Rt, [Rt] + break; + } +#pragma clang diagnostic pop + return 24; + } +} + +static size_t sh_a32_rewrite_ldr_reg(uint32_t *buf, uint32_t inst, uintptr_t pc, sh_a32_type_t type) { + // LDR , [PC,+/-{, }]{!} + // ...... + uint32_t cond = SH_UTIL_GET_BITS_32(inst, 31, 28); + uint32_t rt = SH_UTIL_GET_BITS_16(inst, 15, 12); + uint32_t rt2 = rt + 1; + uint32_t rm = SH_UTIL_GET_BITS_16(inst, 3, 0); + uint32_t rx; // r0 - r3 + for (rx = 3;; --rx) + if (rx != rt && rx != rt2 && rx != rm) break; + + if (type == LDR_REG_PC_A1 && rt == 0xF) { + // Rt == PC + uint32_t ry; // r0 - r4 + for (ry = 4;; --ry) + if (ry != rt && ry != rt2 && ry != rm && ry != rx) break; + + buf[0] = 0x0A000000u | (cond << 28u); // B #0 + buf[1] = 0xEA000006; // B #24 + buf[2] = 0xE92D8000 | (1u << rx) | (1u << ry); // PUSH {Rx, Ry, PC} + buf[3] = 0xE59F0000 | (rx << 12u); // LDR Rx, [PC, #8] + buf[4] = 0xEA000000; // B #0 + buf[5] = pc; + buf[6] = + (inst & 0x0FF00FFFu) | 0xE0000000 | (rx << 16u) | (ry << 12u); // LDRxx Ry, [Rx],+/-Rm{, } + buf[7] = 0xE58D0008 | (ry << 12u); // STR Ry, [SP, #8] + buf[8] = 0xE8BD8000 | (1u << rx) | (1u << ry); // POP {Rx, Ry, PC} + return 36; + } else { + buf[0] = 0x0A000000u | (cond << 28u); // B #0 + buf[1] = 0xEA000005; // B #20 + buf[2] = 0xE52D0004 | (rx << 12u); // PUSH {Rx} + buf[3] = 0xE59F0000 | (rx << 12u); // LDR Rx, [PC, #0] + buf[4] = 0xEA000000; // B #0 + buf[5] = pc; + buf[6] = (inst & 0x0FF0FFFFu) | 0xE0000000 | (rx << 16u); // LDRxx Rt, [Rx],+/-Rm{, } + buf[7] = 0xE49D0004 | (rx << 12u); // POP {Rx} + return 32; + } +} + +size_t sh_a32_rewrite(uint32_t *buf, uint32_t inst, uintptr_t pc, sh_a32_rewrite_info_t *rinfo) { + sh_a32_type_t type = sh_a32_get_type(inst); + SH_LOG_INFO("a32 rewrite: type %d, inst %" PRIx32, type, inst); + + // We will only overwrite 4 to 8 bytes on A32, so PC cannot be in the coverage. + // In this case, the add/sub/mov/ldr_reg instruction does not need to consider + // the problem of PC in the coverage area when rewriting. + + if (type == B_A1 || type == BX_A1 || type == BL_IMM_A1 || type == BLX_IMM_A2) + return sh_a32_rewrite_b(buf, inst, pc, type, rinfo); + else if (type == ADD_REG_A1 || type == ADD_REG_PC_A1 || type == SUB_REG_A1 || type == SUB_REG_PC_A1) + return sh_a32_rewrite_add_or_sub(buf, inst, pc); + else if (type == ADR_A1 || type == ADR_A2) + return sh_a32_rewrite_adr(buf, inst, pc, type, rinfo); + else if (type == MOV_REG_A1 || type == MOV_REG_PC_A1) + return sh_a32_rewrite_mov(buf, inst, pc); + else if (type == LDR_LIT_A1 || type == LDR_LIT_PC_A1 || type == LDRB_LIT_A1 || type == LDRD_LIT_A1 || + type == LDRH_LIT_A1 || type == LDRSB_LIT_A1 || type == LDRSH_LIT_A1) + return sh_a32_rewrite_ldr_lit(buf, inst, pc, type, rinfo); + else if (type == LDR_REG_A1 || type == LDR_REG_PC_A1 || type == LDRB_REG_A1 || type == LDRD_REG_A1 || + type == LDRH_REG_A1 || type == LDRSB_REG_A1 || type == LDRSH_REG_A1) + return sh_a32_rewrite_ldr_reg(buf, inst, pc, type); + else { + // IGNORED + buf[0] = inst; + return 4; + } +} + +size_t sh_a32_absolute_jump(uint32_t *buf, uintptr_t addr) { + buf[0] = 0xE51FF004; // LDR PC, [PC, #-4] + buf[1] = addr; + return 8; +} + +size_t sh_a32_relative_jump(uint32_t *buf, uintptr_t addr, uintptr_t pc) { + buf[0] = 0xEA000000 | (((addr - pc) & 0x03FFFFFFu) >> 2u); // B