From 4a38a98e2e62419e51801228839f13a6181dbc15 Mon Sep 17 00:00:00 2001 From: Allan CORNET Date: Fri, 5 Jan 2024 20:18:18 +0100 Subject: [PATCH] update and fix after cherry-picks --- .github/workflows/ccpp.yml | 2 +- modules/commons/CMakeLists.txt | 2 +- .../src/include/nlohmann/adl_serializer.hpp | 30 +- .../nlohmann/byte_container_with_subtype.hpp | 59 +- .../include/nlohmann/detail/abi_macros.hpp | 85 +- .../nlohmann/detail/conversions/from_json.hpp | 563 +-- .../nlohmann/detail/conversions/to_chars.hpp | 1719 ++++--- .../nlohmann/detail/conversions/to_json.hpp | 355 +- .../include/nlohmann/detail/exceptions.hpp | 209 +- .../src/include/nlohmann/detail/hash.hpp | 129 +- .../nlohmann/detail/input/binary_reader.hpp | 3889 ++++++++------- .../nlohmann/detail/input/input_adapters.hpp | 397 +- .../nlohmann/detail/input/json_sax.hpp | 385 +- .../include/nlohmann/detail/input/lexer.hpp | 1952 ++++---- .../include/nlohmann/detail/input/parser.hpp | 436 +- .../nlohmann/detail/input/position_t.hpp | 10 +- .../detail/iterators/internal_iterator.hpp | 7 +- .../nlohmann/detail/iterators/iter_impl.hpp | 729 +-- .../detail/iterators/iteration_proxy.hpp | 201 +- .../detail/iterators/iterator_traits.hpp | 33 +- .../iterators/json_reverse_iterator.hpp | 51 +- .../detail/iterators/primitive_iterator.hpp | 63 +- .../detail/json_custom_base_class.hpp | 17 +- .../include/nlohmann/detail/json_pointer.hpp | 920 ++-- .../src/include/nlohmann/detail/json_ref.hpp | 57 +- .../include/nlohmann/detail/macro_scope.hpp | 973 ++-- .../include/nlohmann/detail/macro_unscope.hpp | 26 +- .../nlohmann/detail/meta/cpp_future.hpp | 110 +- .../include/nlohmann/detail/meta/detected.hpp | 40 +- .../nlohmann/detail/meta/identity_tag.hpp | 8 +- .../include/nlohmann/detail/meta/is_sax.hpp | 154 +- .../include/nlohmann/detail/meta/std_fs.hpp | 10 +- .../nlohmann/detail/meta/type_traits.hpp | 812 ++-- .../include/nlohmann/detail/meta/void_t.hpp | 9 +- .../nlohmann/detail/output/binary_writer.hpp | 2199 ++++----- .../detail/output/output_adapters.hpp | 108 +- .../nlohmann/detail/output/serializer.hpp | 1146 ++--- .../include/nlohmann/detail/string_concat.hpp | 160 +- .../include/nlohmann/detail/string_escape.hpp | 39 +- .../src/include/nlohmann/detail/value_t.hpp | 49 +- modules/commons/src/include/nlohmann/json.hpp | 4185 +++++++++-------- .../commons/src/include/nlohmann/json_fwd.hpp | 34 +- .../src/include/nlohmann/ordered_map.hpp | 264 +- .../nlohmann/thirdparty/hedley/hedley.hpp | 2441 +++++----- modules/control_system/functions/@ss/ss.m | 186 - modules/control_system/functions/@tf/inv.m | 22 - modules/control_system/functions/@tf/minus.m | 98 - .../control_system/functions/@tf/mrdivide.m | 72 - modules/control_system/functions/@tf/mtimes.m | 62 - modules/control_system/functions/@tf/plus.m | 99 - .../control_system/functions/@tf/subsasgn.m | 95 - .../control_system/functions/@tf/subsref.m | 54 - modules/control_system/functions/@tf/tf.m | 179 - modules/control_system/functions/bode.m | 218 - modules/control_system/functions/zero.m | 65 - modules/control_system/module.iss | 25 - modules/control_system/tests/test_tf_uminus.m | 24 - .../@DisplayFormatOptions/subsasgn.m | 87 - modules/core/help/en_US/xml/exit.xml | 40 - modules/core/help/en_US/xml/quit.xml | 77 - modules/core/tests/test_exit.m | 39 - modules/core/tests/test_exit/finish.m | 3 - modules/core/tests/test_exit/script_exit.m | 3 - modules/double/help/en_US/xml/double.xml | 89 - modules/double/help/en_US/xml/flintmax.xml | 72 - .../tests/test_swapbytes.m | 59 - modules/engine/help/en_US/xml/finish.xml | 53 - modules/engine/help/en_US/xml/startup.xml | 55 - modules/engine/src/cpp/RunFinishScripts.cpp | 60 - modules/engine/src/cpp/RunStartupScripts.cpp | 60 - .../engine/src/include/RunFinishScripts.hpp | 21 - .../engine/src/include/RunStartupScripts.hpp | 16 - .../functions/@MException/subsref.m | 57 - .../tests/test_function_anonymous.m | 106 - .../help/en_US/xml/private_functions.xml | 69 - .../test_private/test_private_1/ex_test_1.m | 12 - .../test_private_1/private/findprivate.m | 6 - .../test_private/test_private_2/ex_test_2.m | 12 - .../test_private_2/private/findprivate.m | 6 - .../test_private_2/private/toto.m | 14 - .../tests/test_private_functions.m | 22 - modules/geometry/tests/test_rotx.m | 31 - modules/geometry/tests/test_roty.m | 27 - modules/geometry/tests/test_rotz.m | 27 - modules/graphics/functions/fill.m | 63 - modules/graphics/functions/grid.m | 96 - modules/graphics/functions/patch.m | 344 -- modules/graphics/functions/pie.m | 210 - modules/graphics/help/en_US/xml/pie.xml | 151 - modules/gui/src/cpp/QtMainWindow.cpp | 530 --- .../hdf5/tests/test_savenh5_function_handle.m | 54 - modules/integer/help/en_US/xml/int16.xml | 73 - modules/integer/help/en_US/xml/int32.xml | 74 - modules/integer/help/en_US/xml/int64.xml | 85 - modules/integer/help/en_US/xml/int8.xml | 73 - modules/integer/help/en_US/xml/uint16.xml | 74 - modules/integer/help/en_US/xml/uint32.xml | 75 - modules/integer/help/en_US/xml/uint64.xml | 88 - modules/integer/help/en_US/xml/uint8.xml | 73 - modules/integer/tests/test_integer.m | 36 +- modules/integer/tests/test_integer_minus.m | 28 - modules/integer/tests/test_integer_plus.m | 24 - modules/integer/tests/test_intmax.m | 2 - modules/integer/tests/test_intmin.m | 2 - .../help/en_US/xml/numeric_types.xml | 167 - modules/modules.m.in | 81 - modules/modules.m.vc | 81 - modules/modules_manager/CMakeLists.txt | 137 - .../src/c/nlsModules_manager.vcxproj | 266 -- .../src/cpp/GatewaysManager.cpp | 182 - .../test_MPI_Send_Recv_anonymous_function.m | 35 - modules/operators/functions/__subsref__.m | 27 - modules/operators/help/en_US/xml/subsasgn.xml | 76 - modules/operators/tests/test_subsasgn.m | 47 - modules/operators/tests/test_subsref.m | 32 - modules/single/help/en_US/xml/single.xml | 78 - modules/special_functions/CMakeLists.txt | 120 - modules/special_functions/etc/startup.m | 12 - .../stream_manager/help/en_US/xml/fprintf.xml | 222 - modules/stream_manager/tests/test_fprintf.m | 40 - modules/string/help/en_US/xml/sprintf.xml | 176 - .../trigonometric_functions/functions/cosd.m | 13 - .../trigonometric_functions/functions/sind.m | 30 - .../trigonometric_functions/tests/test_cosd.m | 27 - .../tests/test_cospi.m | 22 - .../tests/test_sinpi.m | 22 - .../webtools/functions/@weboptions/subsasgn.m | 234 - .../webtools/functions/@weboptions/subsref.m | 57 - .../functions/@weboptions/weboptions.m | 257 - 129 files changed, 12568 insertions(+), 19417 deletions(-) delete mode 100644 modules/control_system/functions/@ss/ss.m delete mode 100644 modules/control_system/functions/@tf/inv.m delete mode 100644 modules/control_system/functions/@tf/minus.m delete mode 100644 modules/control_system/functions/@tf/mrdivide.m delete mode 100644 modules/control_system/functions/@tf/mtimes.m delete mode 100644 modules/control_system/functions/@tf/plus.m delete mode 100644 modules/control_system/functions/@tf/subsasgn.m delete mode 100644 modules/control_system/functions/@tf/subsref.m delete mode 100644 modules/control_system/functions/@tf/tf.m delete mode 100644 modules/control_system/functions/bode.m delete mode 100644 modules/control_system/functions/zero.m delete mode 100644 modules/control_system/module.iss delete mode 100644 modules/control_system/tests/test_tf_uminus.m delete mode 100644 modules/core/functions/@DisplayFormatOptions/subsasgn.m delete mode 100644 modules/core/help/en_US/xml/exit.xml delete mode 100644 modules/core/help/en_US/xml/quit.xml delete mode 100644 modules/core/tests/test_exit.m delete mode 100644 modules/core/tests/test_exit/finish.m delete mode 100644 modules/core/tests/test_exit/script_exit.m delete mode 100644 modules/double/help/en_US/xml/double.xml delete mode 100644 modules/double/help/en_US/xml/flintmax.xml delete mode 100644 modules/elementary_functions/tests/test_swapbytes.m delete mode 100644 modules/engine/help/en_US/xml/finish.xml delete mode 100644 modules/engine/help/en_US/xml/startup.xml delete mode 100644 modules/engine/src/cpp/RunFinishScripts.cpp delete mode 100644 modules/engine/src/cpp/RunStartupScripts.cpp delete mode 100644 modules/engine/src/include/RunFinishScripts.hpp delete mode 100644 modules/engine/src/include/RunStartupScripts.hpp delete mode 100644 modules/error_manager/functions/@MException/subsref.m delete mode 100644 modules/function_handle/tests/test_function_anonymous.m delete mode 100644 modules/functions_manager/help/en_US/xml/private_functions.xml delete mode 100644 modules/functions_manager/tests/test_private/test_private_1/ex_test_1.m delete mode 100644 modules/functions_manager/tests/test_private/test_private_1/private/findprivate.m delete mode 100644 modules/functions_manager/tests/test_private/test_private_2/ex_test_2.m delete mode 100644 modules/functions_manager/tests/test_private/test_private_2/private/findprivate.m delete mode 100644 modules/functions_manager/tests/test_private/test_private_2/private/toto.m delete mode 100644 modules/functions_manager/tests/test_private_functions.m delete mode 100644 modules/geometry/tests/test_rotx.m delete mode 100644 modules/geometry/tests/test_roty.m delete mode 100644 modules/geometry/tests/test_rotz.m delete mode 100644 modules/graphics/functions/fill.m delete mode 100644 modules/graphics/functions/grid.m delete mode 100644 modules/graphics/functions/patch.m delete mode 100644 modules/graphics/functions/pie.m delete mode 100644 modules/graphics/help/en_US/xml/pie.xml delete mode 100644 modules/gui/src/cpp/QtMainWindow.cpp delete mode 100644 modules/hdf5/tests/test_savenh5_function_handle.m delete mode 100644 modules/integer/help/en_US/xml/int16.xml delete mode 100644 modules/integer/help/en_US/xml/int32.xml delete mode 100644 modules/integer/help/en_US/xml/int64.xml delete mode 100644 modules/integer/help/en_US/xml/int8.xml delete mode 100644 modules/integer/help/en_US/xml/uint16.xml delete mode 100644 modules/integer/help/en_US/xml/uint32.xml delete mode 100644 modules/integer/help/en_US/xml/uint64.xml delete mode 100644 modules/integer/help/en_US/xml/uint8.xml delete mode 100644 modules/interpreter/help/en_US/xml/numeric_types.xml delete mode 100644 modules/modules.m.in delete mode 100644 modules/modules.m.vc delete mode 100644 modules/modules_manager/CMakeLists.txt delete mode 100644 modules/modules_manager/src/c/nlsModules_manager.vcxproj delete mode 100644 modules/modules_manager/src/cpp/GatewaysManager.cpp delete mode 100644 modules/mpi/tests/test_MPI_Send_Recv_anonymous_function.m delete mode 100644 modules/operators/functions/__subsref__.m delete mode 100644 modules/operators/help/en_US/xml/subsasgn.xml delete mode 100644 modules/operators/tests/test_subsasgn.m delete mode 100644 modules/operators/tests/test_subsref.m delete mode 100644 modules/single/help/en_US/xml/single.xml delete mode 100644 modules/special_functions/CMakeLists.txt delete mode 100644 modules/special_functions/etc/startup.m delete mode 100644 modules/stream_manager/help/en_US/xml/fprintf.xml delete mode 100644 modules/string/help/en_US/xml/sprintf.xml delete mode 100644 modules/trigonometric_functions/functions/cosd.m delete mode 100644 modules/trigonometric_functions/functions/sind.m delete mode 100644 modules/trigonometric_functions/tests/test_cosd.m delete mode 100644 modules/trigonometric_functions/tests/test_cospi.m delete mode 100644 modules/trigonometric_functions/tests/test_sinpi.m delete mode 100644 modules/webtools/functions/@weboptions/subsasgn.m delete mode 100644 modules/webtools/functions/@weboptions/subsref.m delete mode 100644 modules/webtools/functions/@weboptions/weboptions.m diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 98b146778b..35ca061956 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -208,7 +208,7 @@ jobs: Fedora: runs-on: ubuntu-latest - container: fedora:37 + container: fedora:39 timeout-minutes: 120 needs: Jammy diff --git a/modules/commons/CMakeLists.txt b/modules/commons/CMakeLists.txt index fcd4a11ed6..9822e6fcde 100644 --- a/modules/commons/CMakeLists.txt +++ b/modules/commons/CMakeLists.txt @@ -21,7 +21,7 @@ add_library(${module_library_name} ${COMMONS_SRC}) if(WIN32) target_compile_definitions(${module_library_name} PUBLIC "NLSCOMMONS_EXPORTS") endif() -target_compile_definitions(${module_library_name} PRIVATE FMT_EXPORT) +target_compile_definitions(${module_library_name} PRIVATE FMT_HEADER_ONLY FMT_LIB_EXPORT) set(COMMONS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/include ${CMAKE_CURRENT_SOURCE_DIR}/src/fmt/include) target_include_directories( diff --git a/modules/commons/src/include/nlohmann/adl_serializer.hpp b/modules/commons/src/include/nlohmann/adl_serializer.hpp index 56a606c0f6..a63496daaa 100644 --- a/modules/commons/src/include/nlohmann/adl_serializer.hpp +++ b/modules/commons/src/include/nlohmann/adl_serializer.hpp @@ -18,35 +18,39 @@ NLOHMANN_JSON_NAMESPACE_BEGIN /// @sa https://json.nlohmann.me/api/adl_serializer/ -template -struct adl_serializer +template struct adl_serializer { /// @brief convert a JSON value to any value type /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ - template - static auto from_json(BasicJsonType && j, TargetType& val) noexcept( + template + static auto + from_json(BasicJsonType&& j, TargetType& val) noexcept( noexcept(::nlohmann::from_json(std::forward(j), val))) - -> decltype(::nlohmann::from_json(std::forward(j), val), void()) + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) { ::nlohmann::from_json(std::forward(j), val); } /// @brief convert a JSON value to any value type /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ - template - static auto from_json(BasicJsonType && j) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), detail::identity_tag {}))) - -> decltype(::nlohmann::from_json(std::forward(j), detail::identity_tag {})) + template + static auto + from_json(BasicJsonType&& j) noexcept(noexcept( + ::nlohmann::from_json(std::forward(j), detail::identity_tag {}))) + -> decltype(::nlohmann::from_json( + std::forward(j), detail::identity_tag {})) { - return ::nlohmann::from_json(std::forward(j), detail::identity_tag {}); + return ::nlohmann::from_json( + std::forward(j), detail::identity_tag {}); } /// @brief convert any value type to a JSON value /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ - template - static auto to_json(BasicJsonType& j, TargetType && val) noexcept( + template + static auto + to_json(BasicJsonType& j, TargetType&& val) noexcept( noexcept(::nlohmann::to_json(j, std::forward(val)))) - -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) { ::nlohmann::to_json(j, std::forward(val)); } diff --git a/modules/commons/src/include/nlohmann/byte_container_with_subtype.hpp b/modules/commons/src/include/nlohmann/byte_container_with_subtype.hpp index 91382cd682..b16ea82075 100644 --- a/modules/commons/src/include/nlohmann/byte_container_with_subtype.hpp +++ b/modules/commons/src/include/nlohmann/byte_container_with_subtype.hpp @@ -18,56 +18,58 @@ NLOHMANN_JSON_NAMESPACE_BEGIN /// @brief an internal type for a backed binary type /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ -template -class byte_container_with_subtype : public BinaryType +template class byte_container_with_subtype : public BinaryType { - public: +public: using container_type = BinaryType; using subtype_type = std::uint64_t; /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ - byte_container_with_subtype() noexcept(noexcept(container_type())) - : container_type() - {} + byte_container_with_subtype() noexcept(noexcept(container_type())) : container_type() { } /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) : container_type(b) - {} + { + } /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) : container_type(std::move(b)) - {} + { + } /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ - byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) - : container_type(b) - , m_subtype(subtype_) - , m_has_subtype(true) - {} + byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept( + noexcept(container_type(b))) + : container_type(b), m_subtype(subtype_), m_has_subtype(true) + { + } /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ - byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - , m_subtype(subtype_) - , m_has_subtype(true) - {} + byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept( + noexcept(container_type(std::move(b)))) + : container_type(std::move(b)), m_subtype(subtype_), m_has_subtype(true) + { + } - bool operator==(const byte_container_with_subtype& rhs) const + bool + operator==(const byte_container_with_subtype& rhs) const { - return std::tie(static_cast(*this), m_subtype, m_has_subtype) == - std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); + return std::tie(static_cast(*this), m_subtype, m_has_subtype) + == std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); } - bool operator!=(const byte_container_with_subtype& rhs) const + bool + operator!=(const byte_container_with_subtype& rhs) const { return !(rhs == *this); } /// @brief sets the binary subtype /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ - void set_subtype(subtype_type subtype_) noexcept + void + set_subtype(subtype_type subtype_) noexcept { m_subtype = subtype_; m_has_subtype = true; @@ -75,27 +77,30 @@ class byte_container_with_subtype : public BinaryType /// @brief return the binary subtype /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ - constexpr subtype_type subtype() const noexcept + constexpr subtype_type + subtype() const noexcept { return m_has_subtype ? m_subtype : static_cast(-1); } /// @brief return whether the value has a subtype /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ - constexpr bool has_subtype() const noexcept + constexpr bool + has_subtype() const noexcept { return m_has_subtype; } /// @brief clears the binary subtype /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ - void clear_subtype() noexcept + void + clear_subtype() noexcept { m_subtype = 0; m_has_subtype = false; } - private: +private: subtype_type m_subtype = 0; bool m_has_subtype = false; }; diff --git a/modules/commons/src/include/nlohmann/detail/abi_macros.hpp b/modules/commons/src/include/nlohmann/detail/abi_macros.hpp index f48b9eb1d5..b75cbe51c1 100644 --- a/modules/commons/src/include/nlohmann/detail/abi_macros.hpp +++ b/modules/commons/src/include/nlohmann/detail/abi_macros.hpp @@ -11,90 +11,83 @@ // This file contains all macro definitions affecting or depending on the ABI #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK - #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) - #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 - #warning "Already included a different version of the library!" - #endif - #endif +#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) \ + && defined(NLOHMANN_JSON_VERSION_PATCH) +#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 \ + || NLOHMANN_JSON_VERSION_PATCH != 3 +#warning "Already included a different version of the library!" +#endif +#endif #endif -#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) #ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 +#define JSON_DIAGNOSTICS 0 #endif #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #endif #if JSON_DIAGNOSTICS - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag #else - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS #endif #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp #else - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON #endif #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION - #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 #endif // Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi##a##b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) -#define NLOHMANN_JSON_ABI_TAGS \ - NLOHMANN_JSON_ABI_TAGS_CONCAT( \ - NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT(NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) // Construct the namespace version component -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ - _v ## major ## _ ## minor ## _ ## patch -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) _v##major##_##minor##_##patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) #if NLOHMANN_JSON_NAMESPACE_NO_VERSION #define NLOHMANN_JSON_NAMESPACE_VERSION #else -#define NLOHMANN_JSON_NAMESPACE_VERSION \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ - NLOHMANN_JSON_VERSION_MINOR, \ - NLOHMANN_JSON_VERSION_PATCH) +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT( \ + NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH) #endif // Combine namespace components -#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b -#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ - NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a##b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) #ifndef NLOHMANN_JSON_NAMESPACE -#define NLOHMANN_JSON_NAMESPACE \ - nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION) #endif #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN -#define NLOHMANN_JSON_NAMESPACE_BEGIN \ - namespace nlohmann \ - { \ - inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) \ - { +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION) { #endif #ifndef NLOHMANN_JSON_NAMESPACE_END -#define NLOHMANN_JSON_NAMESPACE_END \ - } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ - } // namespace nlohmann +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann #endif diff --git a/modules/commons/src/include/nlohmann/detail/conversions/from_json.hpp b/modules/commons/src/include/nlohmann/detail/conversions/from_json.hpp index aa2f0cbf4c..34e2b02da8 100644 --- a/modules/commons/src/include/nlohmann/detail/conversions/from_json.hpp +++ b/modules/commons/src/include/nlohmann/detail/conversions/from_json.hpp @@ -30,200 +30,206 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { -template -inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +template +inline void +from_json(const BasicJsonType& j, typename std::nullptr_t& n) { - if (JSON_HEDLEY_UNLIKELY(!j.is_null())) - { - JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { + JSON_THROW( + type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); } n = nullptr; } // overloads for basic_json template parameters -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < std::is_arithmetic::value&& - !std::is_same::value, - int > = 0 > -void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } +template ::value + && !std::is_same::value, + int> + = 0> +void +get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) { + case value_t::number_unsigned: { + val = static_cast( + *j.template get_ptr()); + break; + } + case value_t::number_integer: { + val = static_cast( + *j.template get_ptr()); + break; + } + case value_t::number_float: { + val = static_cast( + *j.template get_ptr()); + break; + } - case value_t::null: - case value_t::object: - case value_t::array: - case value_t::string: - case value_t::boolean: - case value_t::binary: - case value_t::discarded: - default: - JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW( + type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } -template -inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +template +inline void +from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { - if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) - { - JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { + JSON_THROW( + type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); } b = *j.template get_ptr(); } -template -inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +template +inline void +from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { + JSON_THROW( + type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr(); } -template < - typename BasicJsonType, typename StringType, - enable_if_t < - std::is_assignable::value - && is_detected_exact::value - && !std::is_same::value - && !is_json_ref::value, int > = 0 > -inline void from_json(const BasicJsonType& j, StringType& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); +template ::value + && is_detected_exact::value + && !std::is_same::value + && !is_json_ref::value, + int> + = 0> +inline void +from_json(const BasicJsonType& j, StringType& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { + JSON_THROW( + type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr(); } -template -inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +template +inline void +from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { get_arithmetic_value(j, val); } -template -inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +template +inline void +from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) { get_arithmetic_value(j, val); } -template -inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +template +inline void +from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) { get_arithmetic_value(j, val); } #if !JSON_DISABLE_ENUM_SERIALIZATION -template::value, int> = 0> -inline void from_json(const BasicJsonType& j, EnumType& e) +template ::value, int> = 0> +inline void +from_json(const BasicJsonType& j, EnumType& e) { typename std::underlying_type::type val; get_arithmetic_value(j, val); e = static_cast(val); } -#endif // JSON_DISABLE_ENUM_SERIALIZATION +#endif // JSON_DISABLE_ENUM_SERIALIZATION // forward_list doesn't have an insert method -template::value, int> = 0> -inline void from_json(const BasicJsonType& j, std::forward_list& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); +template ::value, int> = 0> +inline void +from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.clear(); - std::transform(j.rbegin(), j.rend(), - std::front_inserter(l), [](const BasicJsonType & i) - { - return i.template get(); - }); + std::transform(j.rbegin(), j.rend(), std::front_inserter(l), + [](const BasicJsonType& i) { return i.template get(); }); } // valarray doesn't have an insert method -template::value, int> = 0> -inline void from_json(const BasicJsonType& j, std::valarray& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); +template ::value, int> = 0> +inline void +from_json(const BasicJsonType& j, std::valarray& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.resize(j.size()); std::transform(j.begin(), j.end(), std::begin(l), - [](const BasicJsonType & elem) - { - return elem.template get(); - }); + [](const BasicJsonType& elem) { return elem.template get(); }); } -template -auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) --> decltype(j.template get(), void()) +template +auto +from_json(const BasicJsonType& j, + T (&arr) + [N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + -> decltype(j.template get(), void()) { - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get(); } } -template -inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +template +inline void +from_json_array_impl( + const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { arr = *j.template get_ptr(); } -template -auto from_json_array_impl(const BasicJsonType& j, std::array& arr, - priority_tag<2> /*unused*/) --> decltype(j.template get(), void()) +template +auto +from_json_array_impl(const BasicJsonType& j, std::array& arr, priority_tag<2> /*unused*/) + -> decltype(j.template get(), void()) { - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get(); } } -template::value, - int> = 0> -auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) --> decltype( - arr.reserve(std::declval()), - j.template get(), - void()) +template ::value, int> + = 0> +auto +from_json_array_impl( + const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) + -> decltype(arr.reserve(std::declval()), + j.template get(), void()) { using std::end; ConstructibleArrayType ret; ret.reserve(j.size()); - std::transform(j.begin(), j.end(), - std::inserter(ret, end(ret)), [](const BasicJsonType & i) - { + std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) { // get() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get(); @@ -231,20 +237,17 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p arr = std::move(ret); } -template::value, - int> = 0> -inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, - priority_tag<0> /*unused*/) +template ::value, int> + = 0> +inline void +from_json_array_impl( + const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<0> /*unused*/) { using std::end; ConstructibleArrayType ret; - std::transform( - j.begin(), j.end(), std::inserter(ret, end(ret)), - [](const BasicJsonType & i) - { + std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) { // get() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get(); @@ -252,76 +255,81 @@ inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr = std::move(ret); } -template < typename BasicJsonType, typename ConstructibleArrayType, - enable_if_t < - is_constructible_array_type::value&& - !is_constructible_object_type::value&& - !is_constructible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) --> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), -j.template get(), -void()) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); +template ::value + && !is_constructible_object_type::value + && !is_constructible_string_type::value + && !std::is_same::value + && !is_basic_json::value, + int> + = 0> +auto +from_json(const BasicJsonType& j, ConstructibleArrayType& arr) + -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), + j.template get(), void()) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } from_json_array_impl(j, arr, priority_tag<3> {}); } -template < typename BasicJsonType, typename T, std::size_t... Idx > -std::array from_json_inplace_array_impl(BasicJsonType&& j, - identity_tag> /*unused*/, index_sequence /*unused*/) +template +std::array +from_json_inplace_array_impl(BasicJsonType&& j, + identity_tag> /*unused*/, index_sequence /*unused*/) { return { { std::forward(j).at(Idx).template get()... } }; } -template < typename BasicJsonType, typename T, std::size_t N > -auto from_json(BasicJsonType&& j, identity_tag> tag) --> decltype(from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {})) +template +auto +from_json(BasicJsonType&& j, identity_tag> tag) + -> decltype(from_json_inplace_array_impl( + std::forward(j), tag, make_index_sequence {})) { - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } - return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {}); + return from_json_inplace_array_impl( + std::forward(j), tag, make_index_sequence {}); } -template -inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) +template +inline void +from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) { - if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) - { - JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { + JSON_THROW( + type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); } bin = *j.template get_ptr(); } -template::value, int> = 0> -inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +template ::value, int> + = 0> +inline void +from_json(const BasicJsonType& j, ConstructibleObjectType& obj) { - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { + JSON_THROW( + type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); } ConstructibleObjectType ret; const auto* inner_object = j.template get_ptr(); using value_type = typename ConstructibleObjectType::value_type; - std::transform( - inner_object->begin(), inner_object->end(), - std::inserter(ret, ret.begin()), - [](typename BasicJsonType::object_t::value_type const & p) - { - return value_type(p.first, p.second.template get()); - }); + std::transform(inner_object->begin(), inner_object->end(), std::inserter(ret, ret.begin()), + [](typename BasicJsonType::object_t::value_type const& p) { + return value_type( + p.first, p.second.template get()); + }); obj = std::move(ret); } @@ -329,140 +337,154 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) // (BooleanType, etc..); note: Is it really necessary to provide explicit // overloads for boolean_t etc. in case of a custom BooleanType which is not // an arithmetic type? -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < - std::is_arithmetic::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value, - int > = 0 > -inline void from_json(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::boolean: - { - val = static_cast(*j.template get_ptr()); - break; - } +template ::value + && !std::is_same::value + && !std::is_same::value + && !std::is_same::value + && !std::is_same::value, + int> + = 0> +inline void +from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) { + case value_t::number_unsigned: { + val = static_cast( + *j.template get_ptr()); + break; + } + case value_t::number_integer: { + val = static_cast( + *j.template get_ptr()); + break; + } + case value_t::number_float: { + val = static_cast( + *j.template get_ptr()); + break; + } + case value_t::boolean: { + val = static_cast( + *j.template get_ptr()); + break; + } - case value_t::null: - case value_t::object: - case value_t::array: - case value_t::string: - case value_t::binary: - case value_t::discarded: - default: - JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW( + type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } -template -std::tuple from_json_tuple_impl_base(BasicJsonType&& j, index_sequence /*unused*/) +template +std::tuple +from_json_tuple_impl_base(BasicJsonType&& j, index_sequence /*unused*/) { return std::make_tuple(std::forward(j).at(Idx).template get()...); } -template < typename BasicJsonType, class A1, class A2 > -std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<0> /*unused*/) +template +std::pair +from_json_tuple_impl( + BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<0> /*unused*/) { - return {std::forward(j).at(0).template get(), - std::forward(j).at(1).template get()}; + return { std::forward(j).at(0).template get(), + std::forward(j).at(1).template get() }; } -template -inline void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) +template +inline void +from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) { - p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); + p = from_json_tuple_impl( + std::forward(j), identity_tag> {}, priority_tag<0> {}); } -template -std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<2> /*unused*/) +template +std::tuple +from_json_tuple_impl( + BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<2> /*unused*/) { - return from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); + return from_json_tuple_impl_base( + std::forward(j), index_sequence_for {}); } -template -inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) +template +inline void +from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) { - t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); + t = from_json_tuple_impl_base( + std::forward(j), index_sequence_for {}); } -template -auto from_json(BasicJsonType&& j, TupleRelated&& t) --> decltype(from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {})) +template +auto +from_json(BasicJsonType&& j, TupleRelated&& t) -> decltype(from_json_tuple_impl( + std::forward(j), std::forward(t), priority_tag<3> {})) { - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } - return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {}); + return from_json_tuple_impl( + std::forward(j), std::forward(t), priority_tag<3> {}); } -template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -inline void from_json(const BasicJsonType& j, std::map& m) +template ::value>> +inline void +from_json(const BasicJsonType& j, std::map& m) { - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); + for (const auto& p : j) { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } } -template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -inline void from_json(const BasicJsonType& j, std::unordered_map& m) +template ::value>> +inline void +from_json(const BasicJsonType& j, std::unordered_map& m) { - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); + for (const auto& p : j) { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { + JSON_THROW( + type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM -template -inline void from_json(const BasicJsonType& j, std_fs::path& p) +template +inline void +from_json(const BasicJsonType& j, std_fs::path& p) { - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { + JSON_THROW( + type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } p = *j.template get_ptr(); } @@ -470,16 +492,17 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p) struct from_json_fn { - template - auto operator()(const BasicJsonType& j, T&& val) const - noexcept(noexcept(from_json(j, std::forward(val)))) - -> decltype(from_json(j, std::forward(val))) + template + auto + operator()(const BasicJsonType& j, T&& val) const + noexcept(noexcept(from_json(j, std::forward(val)))) + -> decltype(from_json(j, std::forward(val))) { return from_json(j, std::forward(val)); } }; -} // namespace detail +} // namespace detail #ifndef JSON_HAS_CPP_17 /// namespace to hold default `from_json` function @@ -491,7 +514,7 @@ namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-n JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) detail::static_const::value; #ifndef JSON_HAS_CPP_17 -} // namespace +} // namespace #endif NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/conversions/to_chars.hpp b/modules/commons/src/include/nlohmann/detail/conversions/to_chars.hpp index e10741c923..4e8f84a3ed 100644 --- a/modules/commons/src/include/nlohmann/detail/conversions/to_chars.hpp +++ b/modules/commons/src/include/nlohmann/detail/conversions/to_chars.hpp @@ -10,7 +10,7 @@ #pragma once #include // array -#include // signbit, isfinite +#include // signbit, isfinite #include // intN_t, uintN_t #include // memcpy, memmove #include // numeric_limits @@ -19,8 +19,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /*! @brief implements the Grisu2 algorithm for binary to decimal floating-point @@ -41,1013 +40,997 @@ For a detailed description of the algorithm see: Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation, PLDI 1996 */ -namespace dtoa_impl -{ +namespace dtoa_impl { -template -Target reinterpret_bits(const Source source) -{ - static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + template + Target + reinterpret_bits(const Source source) + { + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); - Target target; - std::memcpy(&target, &source, sizeof(Source)); - return target; -} + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; + } -struct diyfp // f * 2^e -{ - static constexpr int kPrecision = 64; // = q + struct diyfp // f * 2^e + { + static constexpr int kPrecision = 64; // = q - std::uint64_t f = 0; - int e = 0; + std::uint64_t f = 0; + int e = 0; - constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) { } - /*! - @brief returns x - y - @pre x.e == y.e and x.f >= y.f - */ - static diyfp sub(const diyfp& x, const diyfp& y) noexcept - { - JSON_ASSERT(x.e == y.e); - JSON_ASSERT(x.f >= y.f); + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp + sub(const diyfp& x, const diyfp& y) noexcept + { + JSON_ASSERT(x.e == y.e); + JSON_ASSERT(x.f >= y.f); - return {x.f - y.f, x.e}; - } + return { x.f - y.f, x.e }; + } - /*! - @brief returns x * y - @note The result is rounded. (Only the upper q bits are returned.) - */ - static diyfp mul(const diyfp& x, const diyfp& y) noexcept - { - static_assert(kPrecision == 64, "internal error"); + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp + mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); - // Computes: - // f = round((x.f * y.f) / 2^q) - // e = x.e + y.e + q + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q - // Emulate the 64-bit * 64-bit multiplication: - // - // p = u * v - // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) - // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) - // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) - // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) - // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) - // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) - // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) - // - // (Since Q might be larger than 2^32 - 1) - // - // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) - // - // (Q_hi + H does not overflow a 64-bit int) - // - // = p_lo + 2^64 p_hi + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 + // (u_hi v_hi ) = (p0 ) + 2^32 ((p1 ) + (p2 )) + + // 2^64 (p3 ) = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + + // (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) = (p0_lo ) + 2^32 + // (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) = (p0_lo + // ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 + // (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi - const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; - const std::uint64_t u_hi = x.f >> 32u; - const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; - const std::uint64_t v_hi = y.f >> 32u; + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; - const std::uint64_t p0 = u_lo * v_lo; - const std::uint64_t p1 = u_lo * v_hi; - const std::uint64_t p2 = u_hi * v_lo; - const std::uint64_t p3 = u_hi * v_hi; + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; - const std::uint64_t p0_hi = p0 >> 32u; - const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; - const std::uint64_t p1_hi = p1 >> 32u; - const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; - const std::uint64_t p2_hi = p2 >> 32u; + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; - std::uint64_t Q = p0_hi + p1_lo + p2_lo; + std::uint64_t Q = p0_hi + p1_lo + p2_lo; - // The full product might now be computed as - // - // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) - // p_lo = p0_lo + (Q << 32) - // - // But in this particular case here, the full p_lo is not required. - // Effectively we only need to add the highest bit in p_lo to p_hi (and - // Q_hi + 1 does not overflow). + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). - Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + Q += std::uint64_t { 1 } << (64u - 32u - 1u); // round, ties up - const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); - return {h, x.e + y.e + 64}; - } + return { h, x.e + y.e + 64 }; + } - /*! - @brief normalize x such that the significand is >= 2^(q-1) - @pre x.f != 0 - */ - static diyfp normalize(diyfp x) noexcept - { - JSON_ASSERT(x.f != 0); + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp + normalize(diyfp x) noexcept + { + JSON_ASSERT(x.f != 0); + + while ((x.f >> 63u) == 0) { + x.f <<= 1u; + x.e--; + } - while ((x.f >> 63u) == 0) + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp + normalize_to(const diyfp& x, const int target_exponent) noexcept { - x.f <<= 1u; - x.e--; + const int delta = x.e - target_exponent; + + JSON_ASSERT(delta >= 0); + JSON_ASSERT(((x.f << delta) >> delta) == x.f); + + return { x.f << delta, target_exponent }; } + }; - return x; - } + struct boundaries + { + diyfp w; + diyfp minus; + diyfp plus; + }; /*! - @brief normalize x such that the result has the exponent E - @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + Compute the (normalized) diyfp representing the input number 'value' and its + boundaries. + + @pre value must be finite and positive */ - static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + template + boundaries + compute_boundaries(FloatType value) { - const int delta = x.e - target_exponent; + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); - JSON_ASSERT(delta >= 0); - JSON_ASSERT(((x.f << delta) >> delta) == x.f); + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) - return {x.f << delta, target_exponent}; - } -}; + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); -struct boundaries -{ - diyfp w; - diyfp minus; - diyfp plus; -}; + constexpr int kPrecision + = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t { 1 } << (kPrecision - 1); // = 2^(p-1) -/*! -Compute the (normalized) diyfp representing the input number 'value' and its -boundaries. + using bits_type = + typename std::conditional::type; -@pre value must be finite and positive -*/ -template -boundaries compute_boundaries(FloatType value) -{ - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); + const auto bits = static_cast(reinterpret_bits(value)); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); - // Convert the IEEE representation into a diyfp. - // - // If v is denormal: - // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) - // If v is normalized: - // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + const bool is_denormal = E == 0; + const diyfp v + = is_denormal ? diyfp(F, kMinExp) : diyfp(F + kHiddenBit, static_cast(E) - kBias); - static_assert(std::numeric_limits::is_iec559, - "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ - constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) - constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); - constexpr int kMinExp = 1 - kBias; - constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + const bool lower_boundary_is_closer = F == 0 && E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) - using bits_type = typename std::conditional::type; + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); - const auto bits = static_cast(reinterpret_bits(value)); - const std::uint64_t E = bits >> (kPrecision - 1); - const std::uint64_t F = bits & (kHiddenBit - 1); + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); - const bool is_denormal = E == 0; - const diyfp v = is_denormal - ? diyfp(F, kMinExp) - : diyfp(F + kHiddenBit, static_cast(E) - kBias); + return { diyfp::normalize(v), w_minus, w_plus }; + } - // Compute the boundaries m- and m+ of the floating-point value - // v = f * 2^e. + // Given normalized diyfp w, Grisu needs to find a (normalized) cached + // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies + // within a certain range [alpha, gamma] (Definition 3.2 from [1]) // - // Determine v- and v+, the floating-point predecessor and successor if v, - // respectively. + // alpha <= e = e_c + e_w + q <= gamma // - // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) - // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // or // - // v+ = v + 2^e + // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q + // <= f_c * f_w * 2^gamma // - // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ - // between m- and m+ round to v, regardless of how the input rounding - // algorithm breaks ties. + // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies // - // ---+-------------+-------------+-------------+-------------+--- (A) - // v- m- v m+ v+ + // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma // - // -----------------+------+------+-------------+-------------+--- (B) - // v- m- v m+ v+ - - const bool lower_boundary_is_closer = F == 0 && E > 1; - const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); - const diyfp m_minus = lower_boundary_is_closer - ? diyfp(4 * v.f - 1, v.e - 2) // (B) - : diyfp(2 * v.f - 1, v.e - 1); // (A) - - // Determine the normalized w+ = m+. - const diyfp w_plus = diyfp::normalize(m_plus); - - // Determine w- = m- such that e_(w-) = e_(w+). - const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); - - return {diyfp::normalize(v), w_minus, w_plus}; -} - -// Given normalized diyfp w, Grisu needs to find a (normalized) cached -// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies -// within a certain range [alpha, gamma] (Definition 3.2 from [1]) -// -// alpha <= e = e_c + e_w + q <= gamma -// -// or -// -// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q -// <= f_c * f_w * 2^gamma -// -// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies -// -// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma -// -// or -// -// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) -// -// The choice of (alpha,gamma) determines the size of the table and the form of -// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well -// in practice: -// -// The idea is to cut the number c * w = f * 2^e into two parts, which can be -// processed independently: An integral part p1, and a fractional part p2: -// -// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e -// = (f div 2^-e) + (f mod 2^-e) * 2^e -// = p1 + p2 * 2^e -// -// The conversion of p1 into decimal form requires a series of divisions and -// modulos by (a power of) 10. These operations are faster for 32-bit than for -// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be -// achieved by choosing -// -// -e >= 32 or e <= -32 := gamma -// -// In order to convert the fractional part -// -// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... -// -// into decimal form, the fraction is repeatedly multiplied by 10 and the digits -// d[-i] are extracted in order: -// -// (10 * p2) div 2^-e = d[-1] -// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... -// -// The multiplication by 10 must not overflow. It is sufficient to choose -// -// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. -// -// Since p2 = f mod 2^-e < 2^-e, -// -// -e <= 60 or e >= -60 := alpha - -constexpr int kAlpha = -60; -constexpr int kGamma = -32; - -struct cached_power // c = f * 2^e ~= 10^k -{ - std::uint64_t f; - int e; - int k; -}; - -/*! -For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached -power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c -satisfies (Definition 3.2 from [1]) - - alpha <= e_c + e + q <= gamma. -*/ -inline cached_power get_cached_power_for_binary_exponent(int e) -{ - // Now + // or // - // alpha <= e_c + e + q <= gamma (1) - // ==> f_c * 2^alpha <= c * 2^e * 2^q + // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) // - // and since the c's are normalized, 2^(q-1) <= f_c, + // The choice of (alpha,gamma) determines the size of the table and the form of + // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well + // in practice: // - // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) - // ==> 2^(alpha - e - 1) <= c + // The idea is to cut the number c * w = f * 2^e into two parts, which can be + // processed independently: An integral part p1, and a fractional part p2: // - // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e + // = (f div 2^-e) + (f mod 2^-e) * 2^e + // = p1 + p2 * 2^e // - // k = ceil( log_10( 2^(alpha - e - 1) ) ) - // = ceil( (alpha - e - 1) * log_10(2) ) + // The conversion of p1 into decimal form requires a series of divisions and + // modulos by (a power of) 10. These operations are faster for 32-bit than for + // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be + // achieved by choosing // - // From the paper: - // "In theory the result of the procedure could be wrong since c is rounded, - // and the computation itself is approximated [...]. In practice, however, - // this simple function is sufficient." + // -e >= 32 or e <= -32 := gamma // - // For IEEE double precision floating-point numbers converted into - // normalized diyfp's w = f * 2^e, with q = 64, + // In order to convert the fractional part // - // e >= -1022 (min IEEE exponent) - // -52 (p - 1) - // -52 (p - 1, possibly normalize denormal IEEE numbers) - // -11 (normalize the diyfp) - // = -1137 + // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... // - // and + // into decimal form, the fraction is repeatedly multiplied by 10 and the digits + // d[-i] are extracted in order: // - // e <= +1023 (max IEEE exponent) - // -52 (p - 1) - // -11 (normalize the diyfp) - // = 960 + // (10 * p2) div 2^-e = d[-1] + // (10 * p2) mod 2^-e = d[-2] / 10^1 + ... // - // This binary exponent range [-1137,960] results in a decimal exponent - // range [-307,324]. One does not need to store a cached power for each - // k in this range. For each such k it suffices to find a cached power - // such that the exponent of the product lies in [alpha,gamma]. - // This implies that the difference of the decimal exponents of adjacent - // table entries must be less than or equal to + // The multiplication by 10 must not overflow. It is sufficient to choose // - // floor( (gamma - alpha) * log_10(2) ) = 8. + // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. // - // (A smaller distance gamma-alpha would require a larger table.) - - // NB: - // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + // Since p2 = f mod 2^-e < 2^-e, + // + // -e <= 60 or e >= -60 := alpha - constexpr int kCachedPowersMinDecExp = -300; - constexpr int kCachedPowersDecStep = 8; + constexpr int kAlpha = -60; + constexpr int kGamma = -32; - static constexpr std::array kCachedPowers = + struct cached_power // c = f * 2^e ~= 10^k { - { - { 0xAB70FE17C79AC6CA, -1060, -300 }, - { 0xFF77B1FCBEBCDC4F, -1034, -292 }, - { 0xBE5691EF416BD60C, -1007, -284 }, - { 0x8DD01FAD907FFC3C, -980, -276 }, - { 0xD3515C2831559A83, -954, -268 }, - { 0x9D71AC8FADA6C9B5, -927, -260 }, - { 0xEA9C227723EE8BCB, -901, -252 }, - { 0xAECC49914078536D, -874, -244 }, - { 0x823C12795DB6CE57, -847, -236 }, - { 0xC21094364DFB5637, -821, -228 }, - { 0x9096EA6F3848984F, -794, -220 }, - { 0xD77485CB25823AC7, -768, -212 }, - { 0xA086CFCD97BF97F4, -741, -204 }, - { 0xEF340A98172AACE5, -715, -196 }, - { 0xB23867FB2A35B28E, -688, -188 }, - { 0x84C8D4DFD2C63F3B, -661, -180 }, - { 0xC5DD44271AD3CDBA, -635, -172 }, - { 0x936B9FCEBB25C996, -608, -164 }, - { 0xDBAC6C247D62A584, -582, -156 }, - { 0xA3AB66580D5FDAF6, -555, -148 }, - { 0xF3E2F893DEC3F126, -529, -140 }, - { 0xB5B5ADA8AAFF80B8, -502, -132 }, - { 0x87625F056C7C4A8B, -475, -124 }, - { 0xC9BCFF6034C13053, -449, -116 }, - { 0x964E858C91BA2655, -422, -108 }, - { 0xDFF9772470297EBD, -396, -100 }, - { 0xA6DFBD9FB8E5B88F, -369, -92 }, - { 0xF8A95FCF88747D94, -343, -84 }, - { 0xB94470938FA89BCF, -316, -76 }, - { 0x8A08F0F8BF0F156B, -289, -68 }, - { 0xCDB02555653131B6, -263, -60 }, - { 0x993FE2C6D07B7FAC, -236, -52 }, - { 0xE45C10C42A2B3B06, -210, -44 }, - { 0xAA242499697392D3, -183, -36 }, - { 0xFD87B5F28300CA0E, -157, -28 }, - { 0xBCE5086492111AEB, -130, -20 }, - { 0x8CBCCC096F5088CC, -103, -12 }, - { 0xD1B71758E219652C, -77, -4 }, - { 0x9C40000000000000, -50, 4 }, - { 0xE8D4A51000000000, -24, 12 }, - { 0xAD78EBC5AC620000, 3, 20 }, - { 0x813F3978F8940984, 30, 28 }, - { 0xC097CE7BC90715B3, 56, 36 }, - { 0x8F7E32CE7BEA5C70, 83, 44 }, - { 0xD5D238A4ABE98068, 109, 52 }, - { 0x9F4F2726179A2245, 136, 60 }, - { 0xED63A231D4C4FB27, 162, 68 }, - { 0xB0DE65388CC8ADA8, 189, 76 }, - { 0x83C7088E1AAB65DB, 216, 84 }, - { 0xC45D1DF942711D9A, 242, 92 }, - { 0x924D692CA61BE758, 269, 100 }, - { 0xDA01EE641A708DEA, 295, 108 }, - { 0xA26DA3999AEF774A, 322, 116 }, - { 0xF209787BB47D6B85, 348, 124 }, - { 0xB454E4A179DD1877, 375, 132 }, - { 0x865B86925B9BC5C2, 402, 140 }, - { 0xC83553C5C8965D3D, 428, 148 }, - { 0x952AB45CFA97A0B3, 455, 156 }, - { 0xDE469FBD99A05FE3, 481, 164 }, - { 0xA59BC234DB398C25, 508, 172 }, - { 0xF6C69A72A3989F5C, 534, 180 }, - { 0xB7DCBF5354E9BECE, 561, 188 }, - { 0x88FCF317F22241E2, 588, 196 }, - { 0xCC20CE9BD35C78A5, 614, 204 }, - { 0x98165AF37B2153DF, 641, 212 }, - { 0xE2A0B5DC971F303A, 667, 220 }, - { 0xA8D9D1535CE3B396, 694, 228 }, - { 0xFB9B7CD9A4A7443C, 720, 236 }, - { 0xBB764C4CA7A44410, 747, 244 }, - { 0x8BAB8EEFB6409C1A, 774, 252 }, - { 0xD01FEF10A657842C, 800, 260 }, - { 0x9B10A4E5E9913129, 827, 268 }, - { 0xE7109BFBA19C0C9D, 853, 276 }, - { 0xAC2820D9623BF429, 880, 284 }, - { 0x80444B5E7AA7CF85, 907, 292 }, - { 0xBF21E44003ACDD2D, 933, 300 }, - { 0x8E679C2F5E44FF8F, 960, 308 }, - { 0xD433179D9C8CB841, 986, 316 }, - { 0x9E19DB92B4E31BA9, 1013, 324 }, - } + std::uint64_t f; + int e; + int k; }; - // This computation gives exactly the same results for k as - // k = ceil((kAlpha - e - 1) * 0.30102999566398114) - // for |e| <= 1500, but doesn't require floating-point operations. - // NB: log_10(2) ~= 78913 / 2^18 - JSON_ASSERT(e >= -1500); - JSON_ASSERT(e <= 1500); - const int f = kAlpha - e - 1; - const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + /*! + For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached + power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c + satisfies (Definition 3.2 from [1]) - const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; - JSON_ASSERT(index >= 0); - JSON_ASSERT(static_cast(index) < kCachedPowers.size()); + alpha <= e_c + e + q <= gamma. + */ + inline cached_power + get_cached_power_for_binary_exponent(int e) + { + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) - const cached_power cached = kCachedPowers[static_cast(index)]; - JSON_ASSERT(kAlpha <= cached.e + e + 64); - JSON_ASSERT(kGamma >= cached.e + e + 64); + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. - return cached; -} + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; -/*! -For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. -For n == 0, returns 1 and sets pow10 := 1. -*/ -inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) -{ - // LCOV_EXCL_START - if (n >= 1000000000) - { - pow10 = 1000000000; - return 10; - } - // LCOV_EXCL_STOP - if (n >= 100000000) - { - pow10 = 100000000; - return 9; - } - if (n >= 10000000) - { - pow10 = 10000000; - return 8; - } - if (n >= 1000000) - { - pow10 = 1000000; - return 7; - } - if (n >= 100000) - { - pow10 = 100000; - return 6; - } - if (n >= 10000) - { - pow10 = 10000; - return 5; - } - if (n >= 1000) - { - pow10 = 1000; - return 4; - } - if (n >= 100) - { - pow10 = 100; - return 3; - } - if (n >= 10) - { - pow10 = 10; - return 2; + static constexpr std::array kCachedPowers = { { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + } }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + JSON_ASSERT(e >= -1500); + JSON_ASSERT(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + + const int index + = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + JSON_ASSERT(index >= 0); + JSON_ASSERT(static_cast(index) < kCachedPowers.size()); + + const cached_power cached = kCachedPowers[static_cast(index)]; + JSON_ASSERT(kAlpha <= cached.e + e + 64); + JSON_ASSERT(kGamma >= cached.e + e + 64); + + return cached; } - pow10 = 1; - return 1; -} - -inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, - std::uint64_t rest, std::uint64_t ten_k) -{ - JSON_ASSERT(len >= 1); - JSON_ASSERT(dist <= delta); - JSON_ASSERT(rest <= delta); - JSON_ASSERT(ten_k > 0); - - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // ten_k - // <------> - // <---- rest ----> - // --------------[------------------+----+--------------]-------------- - // w V - // = buf * 10^k - // - // ten_k represents a unit-in-the-last-place in the decimal representation - // stored in buf. - // Decrement buf by ten_k while this takes buf closer to w. + /*! + For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. + For n == 0, returns 1 and sets pow10 := 1. + */ + inline int + find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) + { + // LCOV_EXCL_START + if (n >= 1000000000) { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + if (n >= 100000000) { + pow10 = 100000000; + return 9; + } + if (n >= 10000000) { + pow10 = 10000000; + return 8; + } + if (n >= 1000000) { + pow10 = 1000000; + return 7; + } + if (n >= 100000) { + pow10 = 100000; + return 6; + } + if (n >= 10000) { + pow10 = 10000; + return 5; + } + if (n >= 1000) { + pow10 = 1000; + return 4; + } + if (n >= 100) { + pow10 = 100; + return 3; + } + if (n >= 10) { + pow10 = 10; + return 2; + } - // The tests are written in this order to avoid overflow in unsigned - // integer arithmetic. + pow10 = 1; + return 1; + } - while (rest < dist - && delta - rest >= ten_k - && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) + inline void + grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, + std::uint64_t ten_k) { - JSON_ASSERT(buf[len - 1] != '0'); - buf[len - 1]--; - rest += ten_k; + JSON_ASSERT(len >= 1); + JSON_ASSERT(dist <= delta); + JSON_ASSERT(rest <= delta); + JSON_ASSERT(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist && delta - rest >= ten_k + && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) { + JSON_ASSERT(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } } -} - -/*! -Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. -M- and M+ must be normalized and share the same exponent -60 <= e <= -32. -*/ -inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, - diyfp M_minus, diyfp w, diyfp M_plus) -{ - static_assert(kAlpha >= -60, "internal error"); - static_assert(kGamma <= -32, "internal error"); - // Generates the digits (and the exponent) of a decimal floating-point - // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's - // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. - // - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // Grisu2 generates the digits of M+ from left to right and stops as soon as - // V is in [M-,M+]. + /*! + Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. + M- and M+ must be normalized and share the same exponent -60 <= e <= -32. + */ + inline void + grisu2_digit_gen( + char* buffer, int& length, int& decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus) + { + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); - JSON_ASSERT(M_plus.e >= kAlpha); - JSON_ASSERT(M_plus.e <= kGamma); + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. - std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) - std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + JSON_ASSERT(M_plus.e >= kAlpha); + JSON_ASSERT(M_plus.e <= kGamma); - // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): - // - // M+ = f * 2^e - // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e - // = ((p1 ) * 2^-e + (p2 )) * 2^e - // = p1 + p2 * 2^e + std::uint64_t delta + = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist + = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e) - const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e - auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) - std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + const diyfp one(std::uint64_t { 1 } << -M_plus.e, M_plus.e); - // 1) - // - // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + auto p1 = static_cast( + M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e - JSON_ASSERT(p1 > 0); + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] - std::uint32_t pow10{}; - const int k = find_largest_pow10(p1, pow10); + JSON_ASSERT(p1 > 0); - // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) - // - // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) - // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) - // - // M+ = p1 + p2 * 2^e - // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e - // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e - // = d[k-1] * 10^(k-1) + ( rest) * 2^e - // - // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) - // - // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] - // - // but stop as soon as - // - // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + std::uint32_t pow10 {}; + const int k = find_largest_pow10(p1, pow10); - int n = k; - while (n > 0) - { - // Invariants: - // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) - // pow10 = 10^(n-1) <= p1 < 10^n - // - const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) - const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) // - // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e - // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e // - // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) // - p1 = r; - n--; + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] // - // M+ = buffer * 10^n + (p1 + p2 * 2^e) - // pow10 = 10^n + // but stop as soon as // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e - // Now check if enough digits have been generated. - // Compute - // - // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e - // - // Note: - // Since rest and delta share the same exponent e, it suffices to - // compare the significands. - const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; - if (rest <= delta) - { - // V = buffer * 10^n, with M- <= V <= M+. - - decimal_exponent += n; - - // We may now just stop. But instead look if the buffer could be - // decremented to bring V closer to w. + int n = k; + while (n > 0) { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) // - // pow10 = 10^n is now 1 ulp in the decimal representation V. - // The rounding procedure works with diyfp's with an implicit - // exponent of e. + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d // - // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n // - const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; - grisu2_round(buffer, length, dist, delta, rest, ten_n); - return; + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t { p1 } << -one.e) + p2; + if (rest <= delta) { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t { pow10 } << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. } - pow10 /= 10; + // 2) // - // pow10 = 10^(n-1) <= p1 < 10^n - // Invariants restored. - } - - // 2) - // - // The digits of the integral part have been generated: - // - // M+ = d[k-1]...d[1]d[0] + p2 * 2^e - // = buffer + p2 * 2^e - // - // Now generate the digits of the fractional part p2 * 2^e. - // - // Note: - // No decimal point is generated: the exponent is adjusted instead. - // - // p2 actually represents the fraction - // - // p2 * 2^e - // = p2 / 2^-e - // = d[-1] / 10^1 + d[-2] / 10^2 + ... - // - // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) - // - // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m - // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) - // - // using - // - // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) - // = ( d) * 2^-e + ( r) - // - // or - // 10^m * p2 * 2^e = d + r * 2^e - // - // i.e. - // - // M+ = buffer + p2 * 2^e - // = buffer + 10^-m * (d + r * 2^e) - // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e - // - // and stop as soon as 10^-m * r * 2^e <= delta * 2^e - - JSON_ASSERT(p2 > delta); - - int m = 0; - for (;;) - { - // Invariant: - // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e - // = buffer * 10^-m + 10^-m * (p2 ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e // - JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); - p2 *= 10; - const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e - const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // Now generate the digits of the fractional part p2 * 2^e. // - // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) - // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // Note: + // No decimal point is generated: the exponent is adjusted instead. // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // p2 actually represents the fraction // - // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... // - p2 = r; - m++; + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) // - // M+ = buffer * 10^-m + 10^-m * p2 * 2^e - // Invariant restored. - - // Check if enough digits have been generated. + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) // - // 10^-m * p2 * 2^e <= delta * 2^e - // p2 * 2^e <= 10^m * delta * 2^e - // p2 <= 10^m * delta - delta *= 10; - dist *= 10; - if (p2 <= delta) - { - break; + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + JSON_ASSERT(p2 > delta); + + int m = 0; + for (;;) { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod + // 2^-e)) * 2^e + // + JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) { + break; + } } - } - // V = buffer * 10^-m, with M- <= V <= M+. + // V = buffer * 10^-m, with M- <= V <= M+. - decimal_exponent -= m; + decimal_exponent -= m; - // 1 ulp in the decimal representation is now 10^-m. - // Since delta and dist are now scaled by 10^m, we need to do the - // same with ulp in order to keep the units in sync. - // - // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e - // - const std::uint64_t ten_m = one.f; - grisu2_round(buffer, length, dist, delta, p2, ten_m); + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); - // By construction this algorithm generates the shortest possible decimal - // number (Loitsch, Theorem 6.2) which rounds back to w. - // For an input number of precision p, at least - // - // N = 1 + ceil(p * log_10(2)) - // - // decimal digits are sufficient to identify all binary floating-point - // numbers (Matula, "In-and-Out conversions"). - // This implies that the algorithm does not produce more than N decimal - // digits. - // - // N = 17 for p = 53 (IEEE double precision) - // N = 9 for p = 24 (IEEE single precision) -} + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) + } -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -JSON_HEDLEY_NON_NULL(1) -inline void grisu2(char* buf, int& len, int& decimal_exponent, - diyfp m_minus, diyfp v, diyfp m_plus) -{ - JSON_ASSERT(m_plus.e == m_minus.e); - JSON_ASSERT(m_plus.e == v.e); + /*! + v = buf * 10^decimal_exponent + len is the length of the buffer (number of decimal digits) + The buffer must be large enough, i.e. >= max_digits10. + */ + JSON_HEDLEY_NON_NULL(1) + inline void + grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus) + { + JSON_ASSERT(m_plus.e == m_minus.e); + JSON_ASSERT(m_plus.e == v.e); - // --------(-----------------------+-----------------------)-------- (A) - // m- v m+ - // - // --------------------(-----------+-----------------------)-------- (B) - // m- v m+ - // - // First scale v (and m- and m+) such that the exponent is in the range - // [alpha, gamma]. + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. - const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); - const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k - // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] - const diyfp w = diyfp::mul(v, c_minus_k); - const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); - const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); - // ----(---+---)---------------(---+---)---------------(---+---)---- - // w- w w+ - // = c*m- = c*v = c*m+ - // - // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and - // w+ are now off by a small amount. - // In fact: - // - // w - v * 10^k < 1 ulp - // - // To account for this inaccuracy, add resp. subtract 1 ulp. - // - // --------+---[---------------(---+---)---------------]---+-------- - // w- M- w M+ w+ - // - // Now any number in [M-, M+] (bounds included) will round to w when input, - // regardless of how the input rounding algorithm breaks ties. - // - // And digit_gen generates the shortest possible such number in [M-, M+]. - // Note that this does not mean that Grisu2 always generates the shortest - // possible number in the interval (m-, m+). - const diyfp M_minus(w_minus.f + 1, w_minus.e); - const diyfp M_plus (w_plus.f - 1, w_plus.e ); + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus(w_plus.f - 1, w_plus.e); - decimal_exponent = -cached.k; // = -(-k) = k + decimal_exponent = -cached.k; // = -(-k) = k - grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); -} + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); + } -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -template -JSON_HEDLEY_NON_NULL(1) -void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) -{ - static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, - "internal error: not enough precision"); + /*! + v = buf * 10^decimal_exponent + len is the length of the buffer (number of decimal digits) + The buffer must be large enough, i.e. >= max_digits10. + */ + template + JSON_HEDLEY_NON_NULL(1) + void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) + { + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); - // If the neighbors (and boundaries) of 'value' are always computed for double-precision - // numbers, all float's can be recovered using strtod (and strtof). However, the resulting - // decimal representations are not exactly "short". - // - // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) - // says "value is converted to a string as if by std::sprintf in the default ("C") locale" - // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' - // does. - // On the other hand, the documentation for 'std::to_chars' requires that "parsing the - // representation using the corresponding std::from_chars function recovers value exactly". That - // indicates that single precision floating-point numbers should be recovered using - // 'std::strtof'. - // - // 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 the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' + // (https://en.cppreference.com/w/cpp/utility/to_chars) says "value is converted to a string + // as if by std::sprintf in the default ("C") locale" and since sprintf promotes floats to + // doubles, I think this is exactly what 'std::to_chars' does. On the other hand, the + // documentation for 'std::to_chars' requires that "parsing the representation using the + // corresponding std::from_chars function recovers value exactly". That indicates that + // single precision floating-point numbers should be recovered using 'std::strtof'. + // + // 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) const boundaries w = compute_boundaries(static_cast(value)); #else - const boundaries w = compute_boundaries(value); + const boundaries w = compute_boundaries(value); #endif - grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); -} - -/*! -@brief appends a decimal representation of e to buf -@return a pointer to the element following the exponent. -@pre -1000 < e < 1000 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* append_exponent(char* buf, int e) -{ - JSON_ASSERT(e > -1000); - JSON_ASSERT(e < 1000); - - if (e < 0) - { - e = -e; - *buf++ = '-'; - } - else - { - *buf++ = '+'; + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); } - auto k = static_cast(e); - if (k < 10) - { - // Always print at least two digits in the exponent. - // This is for compatibility with printf("%g"). - *buf++ = '0'; - *buf++ = static_cast('0' + k); - } - else if (k < 100) - { - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - else + /*! + @brief appends a decimal representation of e to buf + @return a pointer to the element following the exponent. + @pre -1000 < e < 1000 + */ + JSON_HEDLEY_NON_NULL(1) + JSON_HEDLEY_RETURNS_NON_NULL + inline char* + append_exponent(char* buf, int e) { - *buf++ = static_cast('0' + k / 100); - k %= 100; - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); + JSON_ASSERT(e > -1000); + JSON_ASSERT(e < 1000); + + if (e < 0) { + e = -e; + *buf++ = '-'; + } else { + *buf++ = '+'; + } + + auto k = static_cast(e); + if (k < 10) { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } else if (k < 100) { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } else { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + + return buf; } - return buf; -} + /*! + @brief prettify v = buf * 10^decimal_exponent -/*! -@brief prettify v = buf * 10^decimal_exponent + If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point + notation. Otherwise it will be printed in exponential notation. -If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point -notation. Otherwise it will be printed in exponential notation. + @pre min_exp < 0 + @pre max_exp > 0 + */ + JSON_HEDLEY_NON_NULL(1) + JSON_HEDLEY_RETURNS_NON_NULL + inline char* + format_buffer(char* buf, int len, int decimal_exponent, int min_exp, int max_exp) + { + JSON_ASSERT(min_exp < 0); + JSON_ASSERT(max_exp > 0); -@pre min_exp < 0 -@pre max_exp > 0 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* format_buffer(char* buf, int len, int decimal_exponent, - int min_exp, int max_exp) -{ - JSON_ASSERT(min_exp < 0); - JSON_ASSERT(max_exp > 0); + const int k = len; + const int n = len + decimal_exponent; - const int k = len; - const int n = len + decimal_exponent; + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. - // v = buf * 10^(n-k) - // k is the length of the buffer (number of decimal digits) - // n is the position of the decimal point relative to the start of the buffer. + if (k <= n && n <= max_exp) { + // digits[000] + // len <= max_exp + 2 - if (k <= n && n <= max_exp) - { - // digits[000] - // len <= max_exp + 2 + std::memset(buf + k, '0', static_cast(n) - static_cast(k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (static_cast(n) + 2); + } - std::memset(buf + k, '0', static_cast(n) - static_cast(k)); - // Make it look like a floating-point number (#362, #378) - buf[n + 0] = '.'; - buf[n + 1] = '0'; - return buf + (static_cast(n) + 2); - } + if (0 < n && n <= max_exp) { + // dig.its + // len <= max_digits10 + 1 - if (0 < n && n <= max_exp) - { - // dig.its - // len <= max_digits10 + 1 + JSON_ASSERT(k > n); - JSON_ASSERT(k > n); + std::memmove(buf + (static_cast(n) + 1), buf + n, + static_cast(k) - static_cast(n)); + buf[n] = '.'; + return buf + (static_cast(k) + 1U); + } - std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); - buf[n] = '.'; - return buf + (static_cast(k) + 1U); - } + if (min_exp < n && n <= 0) { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 - if (min_exp < n && n <= 0) - { - // 0.[000]digits - // len <= 2 + (-min_exp - 1) + max_digits10 - - std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); - buf[0] = '0'; - buf[1] = '.'; - std::memset(buf + 2, '0', static_cast(-n)); - return buf + (2U + static_cast(-n) + static_cast(k)); - } + std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2U + static_cast(-n) + static_cast(k)); + } - if (k == 1) - { - // dE+123 - // len <= 1 + 5 + if (k == 1) { + // dE+123 + // len <= 1 + 5 - buf += 1; - } - else - { - // d.igitsE+123 - // len <= max_digits10 + 1 + 5 + buf += 1; + } else { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 - std::memmove(buf + 2, buf + 1, static_cast(k) - 1); - buf[1] = '.'; - buf += 1 + static_cast(k); - } + std::memmove(buf + 2, buf + 1, static_cast(k) - 1); + buf[1] = '.'; + buf += 1 + static_cast(k); + } - *buf++ = 'e'; - return append_exponent(buf, n - 1); -} + *buf++ = 'e'; + return append_exponent(buf, n - 1); + } -} // namespace dtoa_impl +} // namespace dtoa_impl /*! @brief generates a decimal representation of the floating-point number value in [first, last). @@ -1059,17 +1042,15 @@ format. Returns an iterator pointing past-the-end of the decimal representation. @note The buffer must be large enough. @note The result is NOT null-terminated. */ -template +template JSON_HEDLEY_NON_NULL(1, 2) -JSON_HEDLEY_RETURNS_NON_NULL -char* to_chars(char* first, const char* last, FloatType value) +JSON_HEDLEY_RETURNS_NON_NULL char* to_chars(char* first, const char* last, FloatType value) { static_cast(last); // maybe unused - fix warning JSON_ASSERT(std::isfinite(value)); // Use signbit(value) instead of (value < 0) since signbit works for -0. - if (std::signbit(value)) - { + if (std::signbit(value)) { value = -value; *first++ = '-'; } @@ -1114,5 +1095,5 @@ char* to_chars(char* first, const char* last, FloatType value) return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); } -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/conversions/to_json.hpp b/modules/commons/src/include/nlohmann/detail/conversions/to_json.hpp index e39b7797dd..db5611e3b2 100644 --- a/modules/commons/src/include/nlohmann/detail/conversions/to_json.hpp +++ b/modules/commons/src/include/nlohmann/detail/conversions/to_json.hpp @@ -25,8 +25,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { ////////////////// // constructors // @@ -39,13 +38,13 @@ namespace detail * https://github.com/nlohmann/json/issues/2865 for more information. */ -template struct external_constructor; +template struct external_constructor; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + 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; @@ -54,11 +53,11 @@ struct external_constructor } }; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + 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; @@ -66,8 +65,9 @@ struct external_constructor j.assert_invariant(); } - template - static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + 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; @@ -75,10 +75,12 @@ struct external_constructor j.assert_invariant(); } - template < typename BasicJsonType, typename CompatibleStringType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleStringType& str) + template ::value, + int> + = 0> + static void + construct(BasicJsonType& j, const CompatibleStringType& str) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::string; @@ -87,11 +89,11 @@ struct external_constructor } }; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) + 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; @@ -99,8 +101,9 @@ struct external_constructor j.assert_invariant(); } - template - static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) + 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; @@ -109,11 +112,11 @@ struct external_constructor } }; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + 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; @@ -122,11 +125,11 @@ struct external_constructor } }; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + 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; @@ -135,11 +138,11 @@ struct external_constructor } }; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + 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; @@ -148,11 +151,11 @@ struct external_constructor } }; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + 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; @@ -161,8 +164,9 @@ struct external_constructor j.assert_invariant(); } - template - static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + 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; @@ -171,46 +175,48 @@ struct external_constructor j.assert_invariant(); } - template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + template ::value, int> + = 0> + static void + construct(BasicJsonType& j, const CompatibleArrayType& arr) { using std::begin; using std::end; j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; - j.m_data.m_value.array = j.template create(begin(arr), end(arr)); + j.m_data.m_value.array + = j.template create(begin(arr), end(arr)); j.set_parents(); j.assert_invariant(); } - template - static void construct(BasicJsonType& j, const std::vector& arr) + 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()); - for (const bool x : arr) - { + for (const bool x : arr) { j.m_data.m_value.array->push_back(x); j.set_parent(j.m_data.m_value.array->back()); } j.assert_invariant(); } - template::value, int> = 0> - static void construct(BasicJsonType& j, const std::valarray& arr) + template ::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()); - if (arr.size() > 0) - { + if (arr.size() > 0) { std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); } j.set_parents(); @@ -218,11 +224,11 @@ struct external_constructor } }; -template<> -struct external_constructor +template <> struct external_constructor { - template - static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + 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; @@ -231,8 +237,9 @@ struct external_constructor j.assert_invariant(); } - template - static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + 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; @@ -241,16 +248,20 @@ struct external_constructor j.assert_invariant(); } - template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < !std::is_same::value, int > = 0 > - static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + template ::value, + int> + = 0> + static void + construct(BasicJsonType& j, const CompatibleObjectType& obj) { using std::begin; using std::end; j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::object; - j.m_data.m_value.object = j.template create(begin(obj), end(obj)); + j.m_data.m_value.object + = j.template create(begin(obj), end(obj)); j.set_parents(); j.assert_invariant(); } @@ -260,160 +271,209 @@ struct external_constructor // to_json // ///////////// -template::value, int> = 0> -inline void to_json(BasicJsonType& j, T b) noexcept +template ::value, int> = 0> +inline void +to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); } -template < typename BasicJsonType, typename BoolRef, - enable_if_t < - ((std::is_same::reference, BoolRef>::value - && !std::is_same ::reference, typename BasicJsonType::boolean_t&>::value) - || (std::is_same::const_reference, BoolRef>::value - && !std::is_same ::const_reference>, - typename BasicJsonType::boolean_t >::value)) - && std::is_convertible::value, int > = 0 > -inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept -{ - external_constructor::construct(j, static_cast(b)); +template ::reference, BoolRef>::value + && !std::is_same::reference, + typename BasicJsonType::boolean_t&>::value) + || (std::is_same::const_reference, BoolRef>::value + && !std::is_same::const_reference>, + typename BasicJsonType::boolean_t>::value)) + && std::is_convertible::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, const BoolRef& b) noexcept +{ + external_constructor::construct( + j, static_cast(b)); } -template::value, int> = 0> -inline void to_json(BasicJsonType& j, const CompatibleString& s) +template ::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor::construct(j, s); } -template -inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +template +inline void +to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) { external_constructor::construct(j, std::move(s)); } -template::value, int> = 0> -inline void to_json(BasicJsonType& j, FloatType val) noexcept +template ::value, int> = 0> +inline void +to_json(BasicJsonType& j, FloatType val) noexcept { - external_constructor::construct(j, static_cast(val)); + external_constructor::construct( + j, static_cast(val)); } -template::value, int> = 0> -inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +template ::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { - external_constructor::construct(j, static_cast(val)); + external_constructor::construct( + j, static_cast(val)); } -template::value, int> = 0> -inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +template ::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { - external_constructor::construct(j, static_cast(val)); + external_constructor::construct( + j, static_cast(val)); } #if !JSON_DISABLE_ENUM_SERIALIZATION -template::value, int> = 0> -inline void to_json(BasicJsonType& j, EnumType e) noexcept +template ::value, int> = 0> +inline void +to_json(BasicJsonType& j, EnumType e) noexcept { using underlying_type = typename std::underlying_type::type; external_constructor::construct(j, static_cast(e)); } -#endif // JSON_DISABLE_ENUM_SERIALIZATION +#endif // JSON_DISABLE_ENUM_SERIALIZATION -template -inline void to_json(BasicJsonType& j, const std::vector& e) +template +inline void +to_json(BasicJsonType& j, const std::vector& e) { external_constructor::construct(j, e); } -template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < is_compatible_array_type::value&& - !is_compatible_object_type::value&& - !is_compatible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +template ::value + && !is_compatible_object_type::value + && !is_compatible_string_type::value + && !std::is_same::value + && !is_basic_json::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor::construct(j, arr); } -template -inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) +template +inline void +to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) { external_constructor::construct(j, bin); } -template::value, int> = 0> -inline void to_json(BasicJsonType& j, const std::valarray& arr) +template ::value, int> = 0> +inline void +to_json(BasicJsonType& j, const std::valarray& arr) { external_constructor::construct(j, std::move(arr)); } -template -inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +template +inline void +to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { external_constructor::construct(j, std::move(arr)); } -template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > -inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +template ::value + && !is_basic_json::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor::construct(j, obj); } -template -inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +template +inline void +to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { external_constructor::construct(j, std::move(obj)); } -template < - typename BasicJsonType, typename T, std::size_t N, - enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - int > = 0 > -inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +template :: + value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + int> + = 0> +inline void +to_json(BasicJsonType& j, + const T (&arr) + [N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { external_constructor::construct(j, arr); } -template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > -inline void to_json(BasicJsonType& j, const std::pair& p) +template ::value + && std::is_constructible::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, const std::pair& p) { j = { p.first, p.second }; } // for https://github.com/nlohmann/json/pull/1134 -template>::value, int> = 0> -inline void to_json(BasicJsonType& j, const T& b) -{ - j = { {b.key(), b.value()} }; +template >::value, + int> + = 0> +inline void +to_json(BasicJsonType& j, const T& b) +{ + j = { { b.key(), b.value() } }; } -template -inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +template +inline void +to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) { j = { std::get(t)... }; } -template::value, int > = 0> -inline void to_json(BasicJsonType& j, const T& t) +template ::value, int> = 0> +inline void +to_json(BasicJsonType& j, const T& t) { to_json_tuple_impl(j, t, make_index_sequence::value> {}); } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM -template -inline void to_json(BasicJsonType& j, const std_fs::path& p) +template +inline void +to_json(BasicJsonType& j, const std_fs::path& p) { j = p.string(); } @@ -421,14 +481,15 @@ inline void to_json(BasicJsonType& j, const std_fs::path& p) struct to_json_fn { - template - auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) - -> decltype(to_json(j, std::forward(val)), void()) + template + auto + operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) { return to_json(j, std::forward(val)); } }; -} // namespace detail +} // namespace detail #ifndef JSON_HAS_CPP_17 /// namespace to hold default `to_json` function @@ -440,7 +501,7 @@ namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-n JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) detail::static_const::value; #ifndef JSON_HAS_CPP_17 -} // namespace +} // namespace #endif NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/exceptions.hpp b/modules/commons/src/include/nlohmann/detail/exceptions.hpp index 5974d7be2b..7f1fa1d283 100644 --- a/modules/commons/src/include/nlohmann/detail/exceptions.hpp +++ b/modules/commons/src/include/nlohmann/detail/exceptions.hpp @@ -11,7 +11,7 @@ #include // nullptr_t #include // exception #if JSON_DIAGNOSTICS - #include // accumulate +#include // accumulate #endif #include // runtime_error #include // to_string @@ -26,8 +26,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { //////////////// // exceptions // @@ -37,9 +36,10 @@ namespace detail /// @sa https://json.nlohmann.me/api/basic_json/exception/ class exception : public std::exception { - public: +public: /// returns the explanatory string - const char* what() const noexcept override + const char* + what() const noexcept override { return m.what(); } @@ -47,78 +47,73 @@ class exception : public std::exception /// the id of the exception const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) - protected: +protected: JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) + exception(int id_, const char* what_arg) + : id(id_), m(what_arg) { } // NOLINT(bugprone-throw-keyword-missing) - static std::string name(const std::string& ename, int id_) + static std::string + name(const std::string& ename, int id_) { return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); } - static std::string diagnostics(std::nullptr_t /*leaf_element*/) + static std::string + diagnostics(std::nullptr_t /*leaf_element*/) { return ""; } - template - static std::string diagnostics(const BasicJsonType* leaf_element) + template + static std::string + diagnostics(const BasicJsonType* leaf_element) { #if JSON_DIAGNOSTICS std::vector tokens; - for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) - { - switch (current->m_parent->type()) - { - case value_t::array: - { - for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) - { - if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) - { - tokens.emplace_back(std::to_string(i)); - break; - } + for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; + current = current->m_parent) { + switch (current->m_parent->type()) { + case value_t::array: { + for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) { + if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) { + tokens.emplace_back(std::to_string(i)); + break; } - break; } + break; + } - case value_t::object: - { - for (const auto& element : *current->m_parent->m_data.m_value.object) - { - if (&element.second == current) - { - tokens.emplace_back(element.first.c_str()); - break; - } + case value_t::object: { + for (const auto& element : *current->m_parent->m_data.m_value.object) { + if (&element.second == current) { + tokens.emplace_back(element.first.c_str()); + break; } - break; } + break; + } - case value_t::null: // LCOV_EXCL_LINE - case value_t::string: // LCOV_EXCL_LINE - case value_t::boolean: // LCOV_EXCL_LINE - case value_t::number_integer: // LCOV_EXCL_LINE - case value_t::number_unsigned: // LCOV_EXCL_LINE - case value_t::number_float: // LCOV_EXCL_LINE - case value_t::binary: // LCOV_EXCL_LINE - case value_t::discarded: // LCOV_EXCL_LINE - default: // LCOV_EXCL_LINE - break; // LCOV_EXCL_LINE + case value_t::null: // LCOV_EXCL_LINE + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + break; // LCOV_EXCL_LINE } } - if (tokens.empty()) - { + if (tokens.empty()) { return ""; } - auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, - [](const std::string & a, const std::string & b) - { - return concat(a, '/', detail::escape(b)); - }); + auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string {}, + [](const std::string& a, const std::string& b) { + return concat(a, '/', detail::escape(b)); + }); return concat('(', str, ") "); #else static_cast(leaf_element); @@ -126,7 +121,7 @@ class exception : public std::exception #endif } - private: +private: /// an exception object as storage for error messages std::runtime_error m; }; @@ -135,7 +130,7 @@ class exception : public std::exception /// @sa https://json.nlohmann.me/api/basic_json/parse_error/ class parse_error : public exception { - public: +public: /*! @brief create a parse error exception @param[in] id_ the id of the exception @@ -145,21 +140,25 @@ class parse_error : public exception @param[in] what_arg the explanatory string @return parse_error object */ - template::value, int> = 0> - static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) + 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); - return {id_, pos.chars_read_total, w.c_str()}; + 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) + 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); - return {id_, byte_, w.c_str()}; + (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), ": ", + exception::diagnostics(context), what_arg); + return { id_, byte_, w.c_str() }; } /*! @@ -173,14 +172,17 @@ class parse_error : public exception */ const std::size_t byte; - private: +private: parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} + : exception(id_, what_arg), byte(byte_) + { + } - static std::string position_string(const position_t& pos) + static std::string + position_string(const position_t& pos) { - return concat(" at line ", std::to_string(pos.lines_read + 1), - ", column ", std::to_string(pos.chars_read_current_line)); + return concat(" at line ", std::to_string(pos.lines_read + 1), ", column ", + std::to_string(pos.chars_read_current_line)); } }; @@ -188,70 +190,81 @@ class parse_error : public exception /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ class invalid_iterator : public exception { - public: - template::value, int> = 0> - static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) +public: + 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); - return {id_, w.c_str()}; + const std::string w = concat( + exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); + return { id_, w.c_str() }; } - private: +private: JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} + invalid_iterator(int id_, const char* what_arg) : exception(id_, what_arg) { } }; /// @brief exception indicating executing a member function with a wrong type /// @sa https://json.nlohmann.me/api/basic_json/type_error/ class type_error : public exception { - public: - template::value, int> = 0> - static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) +public: + 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); - return {id_, w.c_str()}; + const std::string w + = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); + return { id_, w.c_str() }; } - private: +private: JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} + type_error(int id_, const char* what_arg) : exception(id_, what_arg) { } }; /// @brief exception indicating access out of the defined range /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ class out_of_range : public exception { - public: - template::value, int> = 0> - static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) +public: + 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); - return {id_, w.c_str()}; + const std::string w = concat( + exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); + return { id_, w.c_str() }; } - private: +private: JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) { } }; /// @brief exception indicating other library errors /// @sa https://json.nlohmann.me/api/basic_json/other_error/ class other_error : public exception { - public: - template::value, int> = 0> - static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) +public: + 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); - return {id_, w.c_str()}; + const std::string w = concat( + exception::name("other_error", id_), exception::diagnostics(context), what_arg); + return { id_, w.c_str() }; } - private: +private: JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} + other_error(int id_, const char* what_arg) : exception(id_, what_arg) { } }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/hash.hpp b/modules/commons/src/include/nlohmann/detail/hash.hpp index 4464e8e67b..75e6d414f5 100644 --- a/modules/commons/src/include/nlohmann/detail/hash.hpp +++ b/modules/commons/src/include/nlohmann/detail/hash.hpp @@ -16,11 +16,11 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { // boost::hash_combine -inline std::size_t combine(std::size_t seed, std::size_t h) noexcept +inline std::size_t +combine(std::size_t seed, std::size_t h) noexcept { seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); return seed; @@ -37,8 +37,9 @@ null, 0, 0U, and false, etc. @param j JSON value to hash @return hash value of j */ -template -std::size_t hash(const BasicJsonType& j) +template +std::size_t +hash(const BasicJsonType& j) { using string_t = typename BasicJsonType::string_t; using number_integer_t = typename BasicJsonType::number_integer_t; @@ -46,84 +47,72 @@ std::size_t hash(const BasicJsonType& j) using number_float_t = typename BasicJsonType::number_float_t; const auto type = static_cast(j.type()); - switch (j.type()) - { - case BasicJsonType::value_t::null: - case BasicJsonType::value_t::discarded: - { - return combine(type, 0); - } + switch (j.type()) { + case BasicJsonType::value_t::null: + case BasicJsonType::value_t::discarded: { + return combine(type, 0); + } - case BasicJsonType::value_t::object: - { - auto seed = combine(type, j.size()); - for (const auto& element : j.items()) - { - const auto h = std::hash {}(element.key()); - seed = combine(seed, h); - seed = combine(seed, hash(element.value())); - } - return seed; + case BasicJsonType::value_t::object: { + auto seed = combine(type, j.size()); + for (const auto& element : j.items()) { + const auto h = std::hash {}(element.key()); + seed = combine(seed, h); + seed = combine(seed, hash(element.value())); } + return seed; + } - case BasicJsonType::value_t::array: - { - auto seed = combine(type, j.size()); - for (const auto& element : j) - { - seed = combine(seed, hash(element)); - } - return seed; + case BasicJsonType::value_t::array: { + auto seed = combine(type, j.size()); + for (const auto& element : j) { + seed = combine(seed, hash(element)); } + return seed; + } - case BasicJsonType::value_t::string: - { - const auto h = std::hash {}(j.template get_ref()); - return combine(type, h); - } + case BasicJsonType::value_t::string: { + const auto h = std::hash {}(j.template get_ref()); + return combine(type, h); + } - case BasicJsonType::value_t::boolean: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } + case BasicJsonType::value_t::boolean: { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } - case BasicJsonType::value_t::number_integer: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } + case BasicJsonType::value_t::number_integer: { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } - case BasicJsonType::value_t::number_unsigned: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } + case BasicJsonType::value_t::number_unsigned: { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } - case BasicJsonType::value_t::number_float: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } + case BasicJsonType::value_t::number_float: { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } - case BasicJsonType::value_t::binary: - { - auto seed = combine(type, j.get_binary().size()); - const auto h = std::hash {}(j.get_binary().has_subtype()); - seed = combine(seed, h); - seed = combine(seed, static_cast(j.get_binary().subtype())); - for (const auto byte : j.get_binary()) - { - seed = combine(seed, std::hash {}(byte)); - } - return seed; + case BasicJsonType::value_t::binary: { + auto seed = combine(type, j.get_binary().size()); + const auto h = std::hash {}(j.get_binary().has_subtype()); + seed = combine(seed, h); + seed = combine(seed, static_cast(j.get_binary().subtype())); + for (const auto byte : j.get_binary()) { + seed = combine(seed, std::hash {}(byte)); } + return seed; + } - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - return 0; // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT( + false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return 0; // LCOV_EXCL_LINE } } -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/input/binary_reader.hpp b/modules/commons/src/include/nlohmann/detail/input/binary_reader.hpp index a6e100e761..6684b31bb6 100644 --- a/modules/commons/src/include/nlohmann/detail/input/binary_reader.hpp +++ b/modules/commons/src/include/nlohmann/detail/input/binary_reader.hpp @@ -32,15 +32,14 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /// how to treat CBOR tags enum class cbor_tag_handler_t { - error, ///< throw a parse_error exception in case of a tag - ignore, ///< ignore tags - store ///< store tags as binary type + error, ///< throw a parse_error exception in case of a tag + ignore, ///< ignore tags + store ///< store tags as binary type }; /*! @@ -50,7 +49,8 @@ enum class cbor_tag_handler_t @note from https://stackoverflow.com/a/1001328/266378 */ -static inline bool little_endianness(int num = 1) noexcept +static inline bool +little_endianness(int num = 1) noexcept { return *reinterpret_cast(&num) == 1; } @@ -62,7 +62,8 @@ static inline bool little_endianness(int num = 1) noexcept /*! @brief deserialization of CBOR, MessagePack, and UBJSON values */ -template> +template > class binary_reader { using number_integer_t = typename BasicJsonType::number_integer_t; @@ -74,22 +75,29 @@ class binary_reader using char_type = typename InputAdapterType::char_type; using char_int_type = typename char_traits::int_type; - public: +public: /*! @brief create a binary reader @param[in] adapter input adapter to read from */ - explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) + explicit binary_reader( + InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept + : ia(std::move(adapter)), input_format(format) { (void)detail::is_sax_static_asserts {}; } // make class move-only binary_reader(const binary_reader&) = delete; - binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - binary_reader& operator=(const binary_reader&) = delete; - binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + binary_reader(binary_reader&&) + = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + binary_reader& + operator=(const binary_reader&) + = delete; + binary_reader& + operator=(binary_reader&&) + = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) ~binary_reader() = default; /*! @@ -101,61 +109,59 @@ class binary_reader @return whether parsing was successful */ JSON_HEDLEY_NON_NULL(3) - bool sax_parse(const input_format_t format, - json_sax_t* sax_, - const bool strict = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + bool + sax_parse(const input_format_t format, json_sax_t* sax_, const bool strict = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { sax = sax_; bool result = false; - switch (format) - { - case input_format_t::bson: - result = parse_bson_internal(); - break; + switch (format) { + case input_format_t::bson: + result = parse_bson_internal(); + break; - case input_format_t::cbor: - result = parse_cbor_internal(true, tag_handler); - break; + case input_format_t::cbor: + result = parse_cbor_internal(true, tag_handler); + break; - case input_format_t::msgpack: - result = parse_msgpack_internal(); - break; + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; - case input_format_t::ubjson: - case input_format_t::bjdata: - result = parse_ubjson_internal(); - break; + case input_format_t::ubjson: + case input_format_t::bjdata: + result = parse_ubjson_internal(); + break; - case input_format_t::json: // LCOV_EXCL_LINE - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // LCOV_EXCL_LINE } // strict mode: next byte must be EOF - if (result && strict) - { - if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) - { + if (result && strict) { + if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) { get_ignore_noop(); - } - else - { + } else { get(); } - if (JSON_HEDLEY_UNLIKELY(current != char_traits::eof())) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, - exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); + if (JSON_HEDLEY_UNLIKELY(current != char_traits::eof())) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(110, chars_read, + exception_message(input_format, + concat("expected end of input; last byte: 0x", get_token_string()), + "value"), + nullptr)); } } return result; } - private: +private: ////////// // BSON // ////////// @@ -164,18 +170,17 @@ class binary_reader @brief Reads in a BSON-object and passes it to the SAX-parser. @return whether a valid BSON-value was passed to the SAX parser */ - bool parse_bson_internal() + bool + parse_bson_internal() { - std::int32_t document_size{}; + std::int32_t document_size {}; get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) - { + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/ false))) { return false; } @@ -189,18 +194,16 @@ class binary_reader @return `true` if the \x00-byte indicating the end of the string was encountered before the EOF; false` indicates an unexpected EOF. */ - bool get_bson_cstr(string_t& result) + bool + get_bson_cstr(string_t& result) { auto out = std::back_inserter(result); - while (true) - { + while (true) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) { return false; } - if (current == 0x00) - { + if (current == 0x00) { return true; } *out++ = static_cast(current); @@ -218,17 +221,22 @@ class binary_reader @pre len >= 1 @return `true` if the string was successfully parsed */ - template - bool get_bson_string(const NumberType len, string_t& result) + template + bool + get_bson_string(const NumberType len, string_t& result) { - if (JSON_HEDLEY_UNLIKELY(len < 1)) - { + if (JSON_HEDLEY_UNLIKELY(len < 1)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message(input_format_t::bson, + concat("string length must be at least 1, is ", std::to_string(len)), + "string"), + nullptr)); } - return get_string(input_format_t::bson, len - static_cast(1), result) && get() != char_traits::eof(); + return get_string(input_format_t::bson, len - static_cast(1), result) + && get() != char_traits::eof(); } /*! @@ -240,18 +248,22 @@ class binary_reader @pre len >= 0 @return `true` if the byte array was successfully parsed */ - template - bool get_bson_binary(const NumberType len, binary_t& result) + template + bool + get_bson_binary(const NumberType len, binary_t& result) { - if (JSON_HEDLEY_UNLIKELY(len < 0)) - { + if (JSON_HEDLEY_UNLIKELY(len < 0)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message(input_format_t::bson, + concat("byte array length cannot be negative, is ", std::to_string(len)), + "binary"), + nullptr)); } // All BSON binary values have a subtype - std::uint8_t subtype{}; + std::uint8_t subtype {}; get_number(input_format_t::bson, subtype); result.set_subtype(subtype); @@ -268,71 +280,79 @@ class binary_reader Unsupported BSON record type 0x... @return whether a valid BSON-object/array was passed to the SAX parser */ - bool parse_bson_element_internal(const char_int_type element_type, - const std::size_t element_type_parse_position) + bool + parse_bson_element_internal( + const char_int_type element_type, const std::size_t element_type_parse_position) { - switch (element_type) + switch (element_type) { + case 0x01: // double { - case 0x01: // double - { - double number{}; - return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); - } + double number {}; + return get_number(input_format_t::bson, number) + && sax->number_float(static_cast(number), ""); + } - case 0x02: // string - { - std::int32_t len{}; - string_t value; - return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); - } + case 0x02: // string + { + std::int32_t len {}; + string_t value; + return get_number(input_format_t::bson, len) + && get_bson_string(len, value) && sax->string(value); + } - case 0x03: // object - { - return parse_bson_internal(); - } + case 0x03: // object + { + return parse_bson_internal(); + } - case 0x04: // array - { - return parse_bson_array(); - } + case 0x04: // array + { + return parse_bson_array(); + } - case 0x05: // binary - { - std::int32_t len{}; - binary_t value; - return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); - } + case 0x05: // binary + { + std::int32_t len {}; + binary_t value; + return get_number(input_format_t::bson, len) + && get_bson_binary(len, value) && sax->binary(value); + } - case 0x08: // boolean - { - return sax->boolean(get() != 0); - } + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } - case 0x0A: // null - { - return sax->null(); - } + case 0x0A: // null + { + return sax->null(); + } - case 0x10: // int32 - { - std::int32_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } + case 0x10: // int32 + { + std::int32_t value {}; + return get_number(input_format_t::bson, value) + && sax->number_integer(value); + } - case 0x12: // int64 - { - std::int64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } + case 0x12: // int64 + { + std::int64_t value {}; + return get_number(input_format_t::bson, value) + && sax->number_integer(value); + } - default: // anything else not supported (yet) - { - 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()}; - 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)); - } + default: // anything else not supported (yet) + { + 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() }; + 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)); + } } } @@ -348,30 +368,27 @@ class binary_reader array (@a is_array == true). @return whether a valid BSON-object/array was passed to the SAX parser */ - bool parse_bson_element_list(const bool is_array) + bool + parse_bson_element_list(const bool is_array) { string_t key; - while (auto element_type = get()) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) - { + while (auto element_type = get()) { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) { return false; } const std::size_t element_type_parse_position = chars_read; - if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) - { + if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) { return false; } - if (!is_array && !sax->key(key)) - { + if (!is_array && !sax->key(key)) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) - { + if (JSON_HEDLEY_UNLIKELY( + !parse_bson_element_internal(element_type, element_type_parse_position))) { return false; } @@ -386,18 +403,17 @@ class binary_reader @brief Reads an array from the BSON input and passes it to the SAX-parser. @return whether a valid BSON-array was passed to the SAX parser */ - bool parse_bson_array() + bool + parse_bson_array() { - std::int32_t document_size{}; + std::int32_t document_size {}; get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) - { + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/ true))) { return false; } @@ -416,483 +432,491 @@ class binary_reader @return whether a valid CBOR value was passed to the SAX parser */ - bool parse_cbor_internal(const bool get_char, - const cbor_tag_handler_t tag_handler) + bool + parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler) { - switch (get_char ? get() : current) - { - // EOF - case char_traits::eof(): - return unexpect_eof(input_format_t::cbor, "value"); - - // Integer 0x00..0x17 (0..23) - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - return sax->number_unsigned(static_cast(current)); - - case 0x18: // Unsigned integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x19: // Unsigned integer (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x1A: // Unsigned integer (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } + switch (get_char ? get() : current) { + // EOF + case char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number {}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - case 0x1B: // Unsigned integer (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - // Negative integer -1-0x00..-1-0x17 (-1..-24) - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - return sax->number_integer(static_cast(0x20 - 1 - current)); - - case 0x38: // Negative integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number {}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - case 0x39: // Negative integer -1-n (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number {}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number {}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - - static_cast(number)); - } - - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: // Binary data (one-byte uint8_t for n follows) - case 0x59: // Binary data (two-byte uint16_t for n follow) - case 0x5A: // Binary data (four-byte uint32_t for n follow) - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - case 0x5F: // Binary data (indefinite length) - { - binary_t b; - return get_cbor_binary(b) && sax->binary(b); - } + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number {}; + return get_number(input_format_t::cbor, number) + && sax->number_integer(static_cast(-1) - number); + } - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - case 0x7F: // UTF-8 string (indefinite length) - { - string_t s; - return get_cbor_string(s) && sax->string(s); - } - - // array (0x00..0x17 data items follow) - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - return get_cbor_array( - conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0x98: // array (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number {}; + return get_number(input_format_t::cbor, number) + && sax->number_integer(static_cast(-1) - number); + } - case 0x99: // array (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number {}; + return get_number(input_format_t::cbor, number) + && sax->number_integer(static_cast(-1) - number); + } - case 0x9A: // array (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); - } + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number {}; + return get_number(input_format_t::cbor, number) + && sax->number_integer( + static_cast(-1) - static_cast(number)); + } - case 0x9B: // array (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); - } - - case 0x9F: // array (indefinite length) - return get_cbor_array(static_cast(-1), tag_handler); - - // map (0x00..0x17 pairs of data items follow) - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - return get_cbor_object(conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0xB8: // map (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: // Binary data (one-byte uint8_t for n follows) + case 0x59: // Binary data (two-byte uint16_t for n follow) + case 0x5A: // Binary data (four-byte uint32_t for n follow) + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + case 0x5F: // Binary data (indefinite length) + { + binary_t b; + return get_cbor_binary(b) && sax->binary(b); + } - case 0xB9: // map (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) && sax->string(s); + } - case 0xBA: // map (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); - } + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array( + conditional_static_cast(static_cast(current) & 0x1Fu), + tag_handler); + + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_array(static_cast(len), tag_handler); + } - case 0xBB: // map (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); - } - - case 0xBF: // map (indefinite length) - return get_cbor_object(static_cast(-1), tag_handler); - - case 0xC6: // tagged item - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD8: // tagged item (1 bytes follow) - case 0xD9: // tagged item (2 bytes follow) - case 0xDA: // tagged item (4 bytes follow) - case 0xDB: // tagged item (8 bytes follow) - { - switch (tag_handler) - { - case cbor_tag_handler_t::error: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); - } + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_array(static_cast(len), tag_handler); + } - case cbor_tag_handler_t::ignore: - { - // ignore binary subtype - switch (current) - { - case 0xD8: - { - std::uint8_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - case 0xD9: - { - std::uint16_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - case 0xDA: - { - std::uint32_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - case 0xDB: - { - std::uint64_t subtype_to_ignore{}; - get_number(input_format_t::cbor, subtype_to_ignore); - break; - } - default: - break; - } - return parse_cbor_internal(true, tag_handler); - } + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_array(conditional_static_cast(len), tag_handler); + } - case cbor_tag_handler_t::store: - { - binary_t b; - // use binary subtype and store in binary container - switch (current) - { - case 0xD8: - { - std::uint8_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - case 0xD9: - { - std::uint16_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - case 0xDA: - { - std::uint32_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - case 0xDB: - { - std::uint64_t subtype{}; - get_number(input_format_t::cbor, subtype); - b.set_subtype(detail::conditional_static_cast(subtype)); - break; - } - default: - return parse_cbor_internal(true, tag_handler); - } - get(); - return get_cbor_binary(b) && sax->binary(b); - } + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_array(conditional_static_cast(len), tag_handler); + } - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } + case 0x9F: // array (indefinite length) + return get_cbor_array(static_cast(-1), tag_handler); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object( + conditional_static_cast(static_cast(current) & 0x1Fu), + tag_handler); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_object(static_cast(len), tag_handler); + } - case 0xF4: // false - return sax->boolean(false); + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_object(static_cast(len), tag_handler); + } - case 0xF5: // true - return sax->boolean(true); + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_object(conditional_static_cast(len), tag_handler); + } - case 0xF6: // null - return sax->null(); + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len {}; + return get_number(input_format_t::cbor, len) + && get_cbor_object(conditional_static_cast(len), tag_handler); + } - case 0xF9: // Half-Precision Float (two-byte IEEE 754) - { - const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; + case 0xBF: // map (indefinite length) + return get_cbor_object(static_cast(-1), tag_handler); + + case 0xC6: // tagged item + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD8: // tagged item (1 bytes follow) + case 0xD9: // tagged item (2 bytes follow) + case 0xDA: // tagged item (4 bytes follow) + case 0xDB: // tagged item (8 bytes follow) + { + switch (tag_handler) { + case cbor_tag_handler_t::error: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message( + input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), + nullptr)); + } + + case cbor_tag_handler_t::ignore: { + // ignore binary subtype + switch (current) { + case 0xD8: { + std::uint8_t subtype_to_ignore {}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; } - const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; + case 0xD9: { + std::uint16_t subtype_to_ignore {}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; } - - const auto byte1 = static_cast(byte1_raw); - const auto byte2 = static_cast(byte2_raw); - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added - // to IEEE 754 in 2008, today's programming platforms often - // still only have limited support for them. It is very - // easy to include at least decoding support for them even - // without such support. An example of a small decoder for - // half-precision floating-point numbers in the C language - // is shown in Fig. 3. - const auto half = static_cast((byte1 << 8u) + byte2); - const double val = [&half] - { - const int exp = (half >> 10u) & 0x1Fu; - const unsigned int mant = half & 0x3FFu; - JSON_ASSERT(0 <= exp&& exp <= 32); - JSON_ASSERT(mant <= 1024); - switch (exp) - { - case 0: - return std::ldexp(mant, -24); - case 31: - return (mant == 0) - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - default: - return std::ldexp(mant + 1024, exp - 25); - } - }(); - return sax->number_float((half & 0x8000u) != 0 - ? static_cast(-val) - : static_cast(val), ""); + case 0xDA: { + std::uint32_t subtype_to_ignore {}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDB: { + std::uint64_t subtype_to_ignore {}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + default: + break; + } + return parse_cbor_internal(true, tag_handler); } - case 0xFA: // Single-Precision Float (four-byte IEEE 754) - { - float number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + case cbor_tag_handler_t::store: { + binary_t b; + // use binary subtype and store in binary container + switch (current) { + case 0xD8: { + std::uint8_t subtype {}; + get_number(input_format_t::cbor, subtype); + b.set_subtype( + detail::conditional_static_cast(subtype)); + break; + } + case 0xD9: { + std::uint16_t subtype {}; + get_number(input_format_t::cbor, subtype); + b.set_subtype( + detail::conditional_static_cast(subtype)); + break; + } + case 0xDA: { + std::uint32_t subtype {}; + get_number(input_format_t::cbor, subtype); + b.set_subtype( + detail::conditional_static_cast(subtype)); + break; + } + case 0xDB: { + std::uint64_t subtype {}; + get_number(input_format_t::cbor, subtype); + b.set_subtype( + detail::conditional_static_cast(subtype)); + break; + } + default: + return parse_cbor_internal(true, tag_handler); + } + get(); + return get_cbor_binary(b) && sax->binary(b); } - case 0xFB: // Double-Precision Float (eight-byte IEEE 754) - { - double number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE } + } - default: // anything else (0xFF is handled inside the other types) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) { + return false; } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp && exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 ? static_cast(-val) + : static_cast(val), + ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number {}; + return get_number(input_format_t::cbor, number) + && sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number {}; + return get_number(input_format_t::cbor, number) + && sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message( + input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), + nullptr)); + } } } @@ -907,88 +931,94 @@ class binary_reader @return whether string creation completed */ - bool get_cbor_string(string_t& result) + bool + get_cbor_string(string_t& result) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) { return false; } - switch (current) - { - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } + switch (current) { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: { + return get_string( + input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len {}; + return get_number(input_format_t::cbor, len) + && get_string(input_format_t::cbor, len, result); + } - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len {}; + return get_number(input_format_t::cbor, len) + && get_string(input_format_t::cbor, len, result); + } - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len {}; + return get_number(input_format_t::cbor, len) + && get_string(input_format_t::cbor, len, result); + } - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len {}; + return get_number(input_format_t::cbor, len) + && get_string(input_format_t::cbor, len, result); + } - case 0x7F: // UTF-8 string (indefinite length) - { - while (get() != 0xFF) - { - string_t chunk; - if (!get_cbor_string(chunk)) - { - return false; - } - result.append(chunk); + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) { + string_t chunk; + if (!get_cbor_string(chunk)) { + return false; } - return true; + result.append(chunk); } + return true; + } - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); - } + default: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(113, chars_read, + exception_message(input_format_t::cbor, + concat("expected length specification (0x60-0x7B) or indefinite string " + "type (0x7F); last byte: 0x", + last_token), + "string"), + nullptr)); + } } } @@ -1003,92 +1033,94 @@ class binary_reader @return whether byte array creation completed */ - bool get_cbor_binary(binary_t& result) + bool + get_cbor_binary(binary_t& result) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) { return false; } - switch (current) - { - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - { - return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } + switch (current) { + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: { + return get_binary( + input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } - case 0x58: // Binary data (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } + case 0x58: // Binary data (one-byte uint8_t for n follows) + { + std::uint8_t len {}; + return get_number(input_format_t::cbor, len) + && get_binary(input_format_t::cbor, len, result); + } - case 0x59: // Binary data (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } + case 0x59: // Binary data (two-byte uint16_t for n follow) + { + std::uint16_t len {}; + return get_number(input_format_t::cbor, len) + && get_binary(input_format_t::cbor, len, result); + } - case 0x5A: // Binary data (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } + case 0x5A: // Binary data (four-byte uint32_t for n follow) + { + std::uint32_t len {}; + return get_number(input_format_t::cbor, len) + && get_binary(input_format_t::cbor, len, result); + } - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + { + std::uint64_t len {}; + return get_number(input_format_t::cbor, len) + && get_binary(input_format_t::cbor, len, result); + } - case 0x5F: // Binary data (indefinite length) - { - while (get() != 0xFF) - { - binary_t chunk; - if (!get_cbor_binary(chunk)) - { - return false; - } - result.insert(result.end(), chunk.begin(), chunk.end()); + case 0x5F: // Binary data (indefinite length) + { + while (get() != 0xFF) { + binary_t chunk; + if (!get_cbor_binary(chunk)) { + return false; } - return true; + result.insert(result.end(), chunk.begin(), chunk.end()); } + return true; + } - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); - } + default: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(113, chars_read, + exception_message(input_format_t::cbor, + concat("expected length specification (0x40-0x5B) or indefinite binary " + "array type (0x5F); last byte: 0x", + last_token), + "binary"), + nullptr)); + } } } @@ -1098,30 +1130,22 @@ class binary_reader @param[in] tag_handler how CBOR tags should be treated @return whether array creation completed */ - bool get_cbor_array(const std::size_t len, - const cbor_tag_handler_t tag_handler) + bool + get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler) { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) { return false; } - if (len != static_cast(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { + if (len != static_cast(-1)) { + for (std::size_t i = 0; i < len; ++i) { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) - { + } else { + while (get() != 0xFF) { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) { return false; } } @@ -1136,45 +1160,34 @@ class binary_reader @param[in] tag_handler how CBOR tags should be treated @return whether object creation completed */ - bool get_cbor_object(const std::size_t len, - const cbor_tag_handler_t tag_handler) + bool + get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler) { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) { return false; } - if (len != 0) - { + if (len != 0) { string_t key; - if (len != static_cast(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { + if (len != static_cast(-1)) { + for (std::size_t i = 0; i < len; ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } key.clear(); } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { + } else { + while (get() != 0xFF) { + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } key.clear(); @@ -1192,374 +1205,385 @@ class binary_reader /*! @return whether a valid MessagePack value was passed to the SAX parser */ - bool parse_msgpack_internal() + bool + parse_msgpack_internal() { - switch (get()) - { - // EOF - case char_traits::eof(): - return unexpect_eof(input_format_t::msgpack, "value"); - - // positive fixint - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5C: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - return sax->number_unsigned(static_cast(current)); - - // fixmap - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - return get_msgpack_object(conditional_static_cast(static_cast(current) & 0x0Fu)); - - // fixarray - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9A: - case 0x9B: - case 0x9C: - case 0x9D: - case 0x9E: - case 0x9F: - return get_msgpack_array(conditional_static_cast(static_cast(current) & 0x0Fu)); - - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - case 0xD9: // str 8 - case 0xDA: // str 16 - case 0xDB: // str 32 - { - string_t s; - return get_msgpack_string(s) && sax->string(s); - } - - case 0xC0: // nil - return sax->null(); - - case 0xC2: // false - return sax->boolean(false); - - case 0xC3: // true - return sax->boolean(true); - - case 0xC4: // bin 8 - case 0xC5: // bin 16 - case 0xC6: // bin 32 - case 0xC7: // ext 8 - case 0xC8: // ext 16 - case 0xC9: // ext 32 - case 0xD4: // fixext 1 - case 0xD5: // fixext 2 - case 0xD6: // fixext 4 - case 0xD7: // fixext 8 - case 0xD8: // fixext 16 - { - binary_t b; - return get_msgpack_binary(b) && sax->binary(b); - } + switch (get()) { + // EOF + case char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object( + conditional_static_cast(static_cast(current) & 0x0Fu)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array( + conditional_static_cast(static_cast(current) & 0x0Fu)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) && sax->string(s); + } - case 0xCA: // float 32 - { - float number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xC4: // bin 8 + case 0xC5: // bin 16 + case 0xC6: // bin 32 + case 0xC7: // ext 8 + case 0xC8: // ext 16 + case 0xC9: // ext 32 + case 0xD4: // fixext 1 + case 0xD5: // fixext 2 + case 0xD6: // fixext 4 + case 0xD7: // fixext 8 + case 0xD8: // fixext 16 + { + binary_t b; + return get_msgpack_binary(b) && sax->binary(b); + } - case 0xCB: // float 64 - { - double number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } + case 0xCA: // float 32 + { + float number {}; + return get_number(input_format_t::msgpack, number) + && sax->number_float(static_cast(number), ""); + } - case 0xCC: // uint 8 - { - std::uint8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } + case 0xCB: // float 64 + { + double number {}; + return get_number(input_format_t::msgpack, number) + && sax->number_float(static_cast(number), ""); + } - case 0xCD: // uint 16 - { - std::uint16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } + case 0xCC: // uint 8 + { + std::uint8_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } - case 0xCE: // uint 32 - { - std::uint32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } + case 0xCD: // uint 16 + { + std::uint16_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } - case 0xCF: // uint 64 - { - std::uint64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } + case 0xCE: // uint 32 + { + std::uint32_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } - case 0xD0: // int 8 - { - std::int8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } + case 0xCF: // uint 64 + { + std::uint64_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } - case 0xD1: // int 16 - { - std::int16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } + case 0xD0: // int 8 + { + std::int8_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } - case 0xD2: // int 32 - { - std::int32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } + case 0xD1: // int 16 + { + std::int16_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } - case 0xD3: // int 64 - { - std::int64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } + case 0xD2: // int 32 + { + std::int32_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } - case 0xDC: // array 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } + case 0xD3: // int 64 + { + std::int64_t number {}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } - case 0xDD: // array 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast(len)); - } + case 0xDC: // array 16 + { + std::uint16_t len {}; + return get_number(input_format_t::msgpack, len) + && get_msgpack_array(static_cast(len)); + } - case 0xDE: // map 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } + case 0xDD: // array 32 + { + std::uint32_t len {}; + return get_number(input_format_t::msgpack, len) + && get_msgpack_array(conditional_static_cast(len)); + } - case 0xDF: // map 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast(len)); - } - - // negative fixint - case 0xE0: - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: - case 0xF0: - case 0xF1: - case 0xF2: - case 0xF3: - case 0xF4: - case 0xF5: - case 0xF6: - case 0xF7: - case 0xF8: - case 0xF9: - case 0xFA: - case 0xFB: - case 0xFC: - case 0xFD: - case 0xFE: - case 0xFF: - return sax->number_integer(static_cast(current)); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); - } + case 0xDE: // map 16 + { + std::uint16_t len {}; + return get_number(input_format_t::msgpack, len) + && get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len {}; + return get_number(input_format_t::msgpack, len) + && get_msgpack_object(conditional_static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message( + input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), + nullptr)); + } } } @@ -1573,76 +1597,83 @@ class binary_reader @return whether string creation completed */ - bool get_msgpack_string(string_t& result) + bool + get_msgpack_string(string_t& result) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) { return false; } - switch (current) - { - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - { - return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); - } + switch (current) { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: { + return get_string( + input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } - case 0xD9: // str 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } + case 0xD9: // str 8 + { + std::uint8_t len {}; + return get_number(input_format_t::msgpack, len) + && get_string(input_format_t::msgpack, len, result); + } - case 0xDA: // str 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } + case 0xDA: // str 16 + { + std::uint16_t len {}; + return get_number(input_format_t::msgpack, len) + && get_string(input_format_t::msgpack, len, result); + } - case 0xDB: // str 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } + case 0xDB: // str 32 + { + std::uint32_t len {}; + return get_number(input_format_t::msgpack, len) + && get_string(input_format_t::msgpack, len, result); + } - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); - } + default: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(113, chars_read, + exception_message(input_format_t::msgpack, + concat( + "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", + last_token), + "string"), + nullptr)); + } } } @@ -1656,110 +1687,109 @@ class binary_reader @return whether byte array creation completed */ - bool get_msgpack_binary(binary_t& result) + bool + get_msgpack_binary(binary_t& result) { // helper function to set the subtype - auto assign_and_return_true = [&result](std::int8_t subtype) - { + auto assign_and_return_true = [&result](std::int8_t subtype) { result.set_subtype(static_cast(subtype)); return true; }; - switch (current) + switch (current) { + case 0xC4: // bin 8 { - case 0xC4: // bin 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } + std::uint8_t len {}; + return get_number(input_format_t::msgpack, len) + && get_binary(input_format_t::msgpack, len, result); + } - case 0xC5: // bin 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } + case 0xC5: // bin 16 + { + std::uint16_t len {}; + return get_number(input_format_t::msgpack, len) + && get_binary(input_format_t::msgpack, len, result); + } - case 0xC6: // bin 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } + case 0xC6: // bin 32 + { + std::uint32_t len {}; + return get_number(input_format_t::msgpack, len) + && get_binary(input_format_t::msgpack, len, result); + } - case 0xC7: // ext 8 - { - std::uint8_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } + case 0xC7: // ext 8 + { + std::uint8_t len {}; + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, len) + && get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, len, result) + && assign_and_return_true(subtype); + } - case 0xC8: // ext 16 - { - std::uint16_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } + case 0xC8: // ext 16 + { + std::uint16_t len {}; + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, len) + && get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, len, result) + && assign_and_return_true(subtype); + } - case 0xC9: // ext 32 - { - std::uint32_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } + case 0xC9: // ext 32 + { + std::uint32_t len {}; + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, len) + && get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, len, result) + && assign_and_return_true(subtype); + } - case 0xD4: // fixext 1 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 1, result) && - assign_and_return_true(subtype); - } + case 0xD4: // fixext 1 + { + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, 1, result) + && assign_and_return_true(subtype); + } - case 0xD5: // fixext 2 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 2, result) && - assign_and_return_true(subtype); - } + case 0xD5: // fixext 2 + { + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, 2, result) + && assign_and_return_true(subtype); + } - case 0xD6: // fixext 4 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 4, result) && - assign_and_return_true(subtype); - } + case 0xD6: // fixext 4 + { + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, 4, result) + && assign_and_return_true(subtype); + } - case 0xD7: // fixext 8 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 8, result) && - assign_and_return_true(subtype); - } + case 0xD7: // fixext 8 + { + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, 8, result) + && assign_and_return_true(subtype); + } - case 0xD8: // fixext 16 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 16, result) && - assign_and_return_true(subtype); - } + case 0xD8: // fixext 16 + { + std::int8_t subtype {}; + return get_number(input_format_t::msgpack, subtype) + && get_binary(input_format_t::msgpack, 16, result) + && assign_and_return_true(subtype); + } - default: // LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE } } @@ -1767,17 +1797,15 @@ class binary_reader @param[in] len the length of the array @return whether array creation completed */ - bool get_msgpack_array(const std::size_t len) + bool + get_msgpack_array(const std::size_t len) { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) { return false; } - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { + for (std::size_t i = 0; i < len; ++i) { + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) { return false; } } @@ -1789,24 +1817,21 @@ class binary_reader @param[in] len the length of the object @return whether object creation completed */ - bool get_msgpack_object(const std::size_t len) + bool + get_msgpack_object(const std::size_t len) { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) { return false; } string_t key; - for (std::size_t i = 0; i < len; ++i) - { + for (std::size_t i = 0; i < len; ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) - { + if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) { return false; } key.clear(); @@ -1826,7 +1851,8 @@ class binary_reader @return whether a valid UBJSON value was passed to the SAX parser */ - bool parse_ubjson_internal(const bool get_char = true) + bool + parse_ubjson_internal(const bool get_char = true) { return get_ubjson_value(get_char ? get_ignore_noop() : current); } @@ -1845,146 +1871,122 @@ class binary_reader @return whether string creation completed */ - bool get_ubjson_string(string_t& result, const bool get_char = true) + bool + get_ubjson_string(string_t& result, const bool get_char = true) { - if (get_char) - { - get(); // TODO(niels): may we ignore N here? + if (get_char) { + get(); // TODO(niels): may we ignore N here? } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) { return false; } - switch (current) - { - case 'U': - { - std::uint8_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); - } + switch (current) { + case 'U': { + std::uint8_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - case 'i': - { - std::int8_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); - } + case 'i': { + std::int8_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - case 'I': - { - std::int16_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); - } + case 'I': { + std::int16_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - case 'l': - { - std::int32_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); - } + case 'l': { + std::int32_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - case 'L': - { - std::int64_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); - } + case 'L': { + std::int64_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - case 'u': - { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint16_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); + case 'u': { + if (input_format != input_format_t::bjdata) { + break; } + std::uint16_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - case 'm': - { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint32_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); + case 'm': { + if (input_format != input_format_t::bjdata) { + break; } + std::uint32_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - case 'M': - { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint64_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result); + case 'M': { + if (input_format != input_format_t::bjdata) { + break; } + std::uint64_t len {}; + return get_number(input_format, len) && get_string(input_format, len, result); + } - default: - break; + default: + break; } auto last_token = get_token_string(); std::string message; - if (input_format != input_format_t::bjdata) - { - message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; - } - else - { - message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; + if (input_format != input_format_t::bjdata) { + message + = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; + } else { + message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + + last_token; } - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create( + 113, chars_read, exception_message(input_format, message, "string"), nullptr)); } /*! @param[out] dim an integer vector storing the ND array dimensions @return whether reading ND array size vector is successful */ - bool get_ubjson_ndarray_size(std::vector& dim) + bool + get_ubjson_ndarray_size(std::vector& dim) { std::pair size_and_type; size_t dimlen = 0; bool no_ndarray = true; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) - { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) { return false; } - if (size_and_type.first != npos) - { - if (size_and_type.second != 0) - { - if (size_and_type.second != 'N') - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) - { + if (size_and_type.first != npos) { + if (size_and_type.second != 0) { + if (size_and_type.second != 'N') { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY( + !get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) { return false; } dim.push_back(dimlen); } } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) - { + } else { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) { return false; } dim.push_back(dimlen); } } - } - else - { - while (current != ']') - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) - { + } else { + while (current != ']') { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) { return false; } dim.push_back(dimlen); @@ -2005,216 +2007,218 @@ class binary_reader @return whether size determination completed */ - bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) + bool + get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) { - if (prefix == 0) - { + if (prefix == 0) { prefix = get_ignore_noop(); } - switch (prefix) - { - case 'U': - { - std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - result = static_cast(number); - return true; + switch (prefix) { + case 'U': { + std::uint8_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; } + result = static_cast(number); + return true; + } - case 'i': - { - std::int8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - if (number < 0) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); - } - result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char - return true; + case 'i': { + std::int8_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; + } + if (number < 0) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(113, chars_read, + exception_message(input_format, + "count in an optimized container must be positive", "size"), + nullptr)); + } + result = static_cast( + number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char + return true; + } + + case 'I': { + std::int16_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; + } + if (number < 0) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(113, chars_read, + exception_message(input_format, + "count in an optimized container must be positive", "size"), + nullptr)); + } + result = static_cast(number); + return true; + } + + case 'l': { + std::int32_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; } + if (number < 0) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(113, chars_read, + exception_message(input_format, + "count in an optimized container must be positive", "size"), + nullptr)); + } + result = static_cast(number); + return true; + } - case 'I': - { - std::int16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - if (number < 0) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); - } - result = static_cast(number); - return true; + case 'L': { + std::int64_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; + } + if (number < 0) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(113, chars_read, + exception_message(input_format, + "count in an optimized container must be positive", "size"), + nullptr)); } + if (!value_in_range_of(number)) { + return sax->parse_error(chars_read, get_token_string(), + out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), + nullptr)); + } + result = static_cast(number); + return true; + } - case 'l': - { - std::int32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - if (number < 0) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); - } - result = static_cast(number); - return true; + case 'u': { + if (input_format != input_format_t::bjdata) { + break; + } + std::uint16_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; } + result = static_cast(number); + return true; + } - case 'L': - { - std::int64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - if (number < 0) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); - } - if (!value_in_range_of(number)) - { - return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "integer value overflow", "size"), nullptr)); - } - result = static_cast(number); - return true; + case 'm': { + if (input_format != input_format_t::bjdata) { + break; + } + std::uint32_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; } + result = conditional_static_cast(number); + return true; + } - case 'u': - { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - result = static_cast(number); - return true; + case 'M': { + if (input_format != input_format_t::bjdata) { + break; + } + std::uint64_t number {}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { + return false; } + if (!value_in_range_of(number)) { + return sax->parse_error(chars_read, get_token_string(), + out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), + nullptr)); + } + result = detail::conditional_static_cast(number); + return true; + } - case 'm': + case '[': { + if (input_format != input_format_t::bjdata) { + break; + } + if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not + // embed another array { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - result = conditional_static_cast(number); - return true; + 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)); } - - case 'M': + std::vector dim; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) { + return false; + } + if (dim.size() == 1 + || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) - { - return false; - } - if (!value_in_range_of(number)) - { - return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "integer value overflow", "size"), nullptr)); - } - result = detail::conditional_static_cast(number); + result = dim.at(dim.size() - 1); return true; } - - case '[': + if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format { - if (input_format != input_format_t::bjdata) + for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D + // empty container { - break; - } - 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)); + if (i == 0) { + result = 0; + return true; + } } - std::vector dim; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) - { + + string_t key = "_ArraySize_"; + if (JSON_HEDLEY_UNLIKELY( + !sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) { return false; } - if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector - { - result = dim.at(dim.size() - 1); - return true; - } - if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format - { - for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container + result = 1; + for (auto i : dim) { + result *= i; + if (result == 0 + || result == npos) // because dim elements shall not have zeros, result = 0 + // means overflow happened; it also can't be npos as it + // is used to initialize size in get_ubjson_size_type() { - if ( i == 0 ) - { - result = 0; - return true; - } + return sax->parse_error(chars_read, get_token_string(), + out_of_range::create(408, + exception_message( + input_format, "excessive ndarray size caused overflow", "size"), + nullptr)); } - - string_t key = "_ArraySize_"; - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) - { + if (JSON_HEDLEY_UNLIKELY( + !sax->number_unsigned(static_cast(i)))) { return false; } - result = 1; - for (auto i : dim) - { - result *= i; - if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type() - { - return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); - } - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast(i)))) - { - return false; - } - } - is_ndarray = true; - return sax->end_array(); } - result = 0; - return true; + is_ndarray = true; + return sax->end_array(); } + result = 0; + return true; + } - default: - break; + default: + break; } auto last_token = get_token_string(); std::string message; - if (input_format != input_format_t::bjdata) - { - message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; - } - else - { - message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; + if (input_format != input_format_t::bjdata) { + message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + + last_token; + } else { + message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last " + "byte: 0x" + + last_token; } - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create( + 113, chars_read, exception_message(input_format, message, "size"), nullptr)); } /*! @@ -2228,7 +2232,8 @@ class binary_reader @return whether pair creation completed */ - bool get_ubjson_size_type(std::pair& result, bool inside_ndarray = false) + bool + get_ubjson_size_type(std::pair& result, bool inside_ndarray = false) { result.first = npos; // size result.second = 0; // type @@ -2236,54 +2241,62 @@ class binary_reader get_ignore_noop(); - if (current == '$') - { - result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (current == '$') { + result.second = get(); // must not ignore 'N', because 'N' maybe the type if (input_format == input_format_t::bjdata - && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) - { + && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), + bjd_optimized_type_markers.end(), result.second))) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message(input_format, + concat("marker 0x", last_token, + " is not a permitted optimized array type"), + "type"), + nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) { return false; } get_ignore_noop(); - if (JSON_HEDLEY_UNLIKELY(current != '#')) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) - { + if (JSON_HEDLEY_UNLIKELY(current != '#')) { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) { return false; } auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + 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); - if (input_format == input_format_t::bjdata && is_ndarray) - { - if (inside_ndarray) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, - exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); + if (input_format == input_format_t::bjdata && is_ndarray) { + if (inside_ndarray) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(112, chars_read, + exception_message(input_format, "ndarray can not be recursive", "size"), + nullptr)); } - result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters + result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData + // markers should be ASCII letters } return is_error; } - if (current == '#') - { + if (current == '#') { const 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, - exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); + if (input_format == input_format_t::bjdata && is_ndarray) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(112, chars_read, + exception_message( + input_format, "ndarray requires both type and size", "size"), + nullptr)); } return is_error; } @@ -2295,236 +2308,222 @@ class binary_reader @param prefix the previously read or set type prefix @return whether value creation completed */ - bool get_ubjson_value(const char_int_type prefix) + bool + get_ubjson_value(const char_int_type prefix) { - switch (prefix) - { - case char_traits::eof(): // EOF - return unexpect_eof(input_format, "value"); + switch (prefix) { + case char_traits::eof(): // EOF + return unexpect_eof(input_format, "value"); - case 'T': // true - return sax->boolean(true); - case 'F': // false - return sax->boolean(false); + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); - case 'Z': // null - return sax->null(); + case 'Z': // null + return sax->null(); - case 'U': - { - std::uint8_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); - } + case 'U': { + std::uint8_t number {}; + return get_number(input_format, number) && sax->number_unsigned(number); + } - case 'i': - { - std::int8_t number{}; - return get_number(input_format, number) && sax->number_integer(number); - } + case 'i': { + std::int8_t number {}; + return get_number(input_format, number) && sax->number_integer(number); + } - case 'I': - { - std::int16_t number{}; - return get_number(input_format, number) && sax->number_integer(number); - } + case 'I': { + std::int16_t number {}; + return get_number(input_format, number) && sax->number_integer(number); + } - case 'l': - { - std::int32_t number{}; - return get_number(input_format, number) && sax->number_integer(number); - } + case 'l': { + std::int32_t number {}; + return get_number(input_format, number) && sax->number_integer(number); + } - case 'L': - { - std::int64_t number{}; - return get_number(input_format, number) && sax->number_integer(number); + case 'L': { + std::int64_t number {}; + return get_number(input_format, number) && sax->number_integer(number); + } + + case 'u': { + if (input_format != input_format_t::bjdata) { + break; } + std::uint16_t number {}; + return get_number(input_format, number) && sax->number_unsigned(number); + } - case 'u': - { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint16_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + case 'm': { + if (input_format != input_format_t::bjdata) { + break; } + std::uint32_t number {}; + return get_number(input_format, number) && sax->number_unsigned(number); + } - case 'm': - { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint32_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + case 'M': { + if (input_format != input_format_t::bjdata) { + break; } + std::uint64_t number {}; + return get_number(input_format, number) && sax->number_unsigned(number); + } - case 'M': - { - if (input_format != input_format_t::bjdata) - { - break; - } - std::uint64_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + case 'h': { + if (input_format != input_format_t::bjdata) { + break; + } + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) { + return false; } - case 'h': - { - if (input_format != input_format_t::bjdata) - { - break; - } - const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) - { - return false; - } - const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) - { - return false; + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte2 << 8u) + byte1); + const double val = [&half] { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp && exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); } + }(); + return sax->number_float((half & 0x8000u) != 0 ? static_cast(-val) + : static_cast(val), + ""); + } - const auto byte1 = static_cast(byte1_raw); - const auto byte2 = static_cast(byte2_raw); - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added - // to IEEE 754 in 2008, today's programming platforms often - // still only have limited support for them. It is very - // easy to include at least decoding support for them even - // without such support. An example of a small decoder for - // half-precision floating-point numbers in the C language - // is shown in Fig. 3. - const auto half = static_cast((byte2 << 8u) + byte1); - const double val = [&half] - { - const int exp = (half >> 10u) & 0x1Fu; - const unsigned int mant = half & 0x3FFu; - JSON_ASSERT(0 <= exp&& exp <= 32); - JSON_ASSERT(mant <= 1024); - switch (exp) - { - case 0: - return std::ldexp(mant, -24); - case 31: - return (mant == 0) - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - default: - return std::ldexp(mant + 1024, exp - 25); - } - }(); - return sax->number_float((half & 0x8000u) != 0 - ? static_cast(-val) - : static_cast(val), ""); - } - - case 'd': - { - float number{}; - return get_number(input_format, number) && sax->number_float(static_cast(number), ""); - } + case 'd': { + float number {}; + return get_number(input_format, number) + && sax->number_float(static_cast(number), ""); + } - case 'D': - { - double number{}; - return get_number(input_format, number) && sax->number_float(static_cast(number), ""); - } + case 'D': { + double number {}; + return get_number(input_format, number) + && sax->number_float(static_cast(number), ""); + } - case 'H': - { - return get_ubjson_high_precision_number(); - } + case 'H': { + return get_ubjson_high_precision_number(); + } - case 'C': // char - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(current > 127)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); - } - string_t s(1, static_cast(current)); - return sax->string(s); + case 'C': // char + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) { + return false; } + if (JSON_HEDLEY_UNLIKELY(current > 127)) { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(113, chars_read, + exception_message(input_format, + concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", + last_token), + "char"), + nullptr)); + } + string_t s(1, static_cast(current)); + return sax->string(s); + } - case 'S': // string - { - string_t s; - return get_ubjson_string(s) && sax->string(s); - } + case 'S': // string + { + string_t s; + return get_ubjson_string(s) && sax->string(s); + } - case '[': // array - return get_ubjson_array(); + case '[': // array + return get_ubjson_array(); - case '{': // object - return get_ubjson_object(); + case '{': // object + return get_ubjson_object(); - default: // anything else - break; + default: // anything else + break; } auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message(input_format, "invalid byte: 0x" + last_token, "value"), + nullptr)); } /*! @return whether array creation completed */ - bool get_ubjson_array() + bool + get_ubjson_array() { std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) { return false; } - // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): + // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData + // annotated array format (https://github.com/NeuroJSON/jdata): // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} - if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) - { - size_and_type.second &= ~(static_cast(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker - auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t) - { - return p.first < t; - }); + if (input_format == input_format_t::bjdata && size_and_type.first != npos + && (size_and_type.second & (1 << 8)) != 0) { + size_and_type.second &= ~( + static_cast(1) << 8); // use bit 8 to indicate ndarray, here we + // remove the bit to restore the type marker + auto it + = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, + [](const bjd_type& p, char_int_type t) { return p.first < t; }); string_t key = "_ArrayType_"; - if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) - { + if (JSON_HEDLEY_UNLIKELY( + it == bjd_types_map.end() || it->first != size_and_type.second)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message(input_format, "invalid byte: 0x" + last_token, "type"), + nullptr)); } string_t type = it->second; // sax->string() takes a reference - if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) { return false; } - if (size_and_type.second == 'C') - { + if (size_and_type.second == 'C') { size_and_type.second = 'U'; } key = "_ArrayData_"; - if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) - { + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first))) { return false; } - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) { return false; } } @@ -2532,48 +2531,33 @@ class binary_reader return (sax->end_array() && sax->end_object()); } - if (size_and_type.first != npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) - { + if (size_and_type.first != npos) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) { return false; } - if (size_and_type.second != 0) - { - if (size_and_type.second != 'N') - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { + if (size_and_type.second != 0) { + if (size_and_type.second != 'N') { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) { return false; } } } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { + } else { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) { return false; } } } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) - { + } else { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) { return false; } - while (current != ']') - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) - { + while (current != ']') { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) { return false; } get_ignore_noop(); @@ -2586,76 +2570,63 @@ class binary_reader /*! @return whether object creation completed */ - bool get_ubjson_object() + bool + get_ubjson_object() { std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) { return false; } // do not accept ND-array size in objects in BJData - if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) - { + if (input_format == input_format_t::bjdata && size_and_type.first != npos + && (size_and_type.second & (1 << 8)) != 0) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, + exception_message(input_format, + "BJData object does not support ND-array size in optimized format", + "object"), + nullptr)); } string_t key; - if (size_and_type.first != npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) - { + if (size_and_type.first != npos) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) { return false; } - if (size_and_type.second != 0) - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { + if (size_and_type.second != 0) { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) { return false; } key.clear(); } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { + } else { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) { return false; } key.clear(); } } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) - { + } else { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) { return false; } - while (current != '}') - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) - { + while (current != '}') { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) { return false; } get_ignore_noop(); @@ -2669,24 +2640,22 @@ class binary_reader // Note, no reader for UBJSON binary types is implemented because they do // not exist - bool get_ubjson_high_precision_number() + bool + get_ubjson_high_precision_number() { // get size of following number string - std::size_t size{}; + std::size_t size {}; bool no_ndarray = true; auto res = get_ubjson_size_value(size, no_ndarray); - if (JSON_HEDLEY_UNLIKELY(!res)) - { + if (JSON_HEDLEY_UNLIKELY(!res)) { return res; } // get number string std::vector number_vector; - for (std::size_t i = 0; i < size; ++i) - { + for (std::size_t i = 0; i < size; ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) { return false; } number_vector.push_back(static_cast(current)); @@ -2694,44 +2663,51 @@ class binary_reader // parse number string using ia_type = decltype(detail::input_adapter(number_vector)); - auto number_lexer = detail::lexer(detail::input_adapter(number_vector), false); + auto number_lexer + = detail::lexer(detail::input_adapter(number_vector), false); const auto result_number = number_lexer.scan(); const auto number_string = number_lexer.get_token_string(); const auto result_remainder = number_lexer.scan(); using token_type = typename detail::lexer_base::token_type; - if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) - { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); - } - - switch (result_number) - { - case token_type::value_integer: - return sax->number_integer(number_lexer.get_number_integer()); - case token_type::value_unsigned: - return sax->number_unsigned(number_lexer.get_number_unsigned()); - case token_type::value_float: - return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); - case token_type::uninitialized: - case token_type::literal_true: - case token_type::literal_false: - case token_type::literal_null: - case token_type::value_string: - case token_type::begin_array: - case token_type::begin_object: - case token_type::end_array: - case token_type::end_object: - case token_type::name_separator: - case token_type::value_separator: - case token_type::parse_error: - case token_type::end_of_input: - case token_type::literal_or_value: - default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); + if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { + return sax->parse_error(chars_read, number_string, + parse_error::create(115, chars_read, + exception_message(input_format, + concat("invalid number text: ", number_lexer.get_token_string()), + "high-precision number"), + nullptr)); + } + + switch (result_number) { + case token_type::value_integer: + return sax->number_integer(number_lexer.get_number_integer()); + case token_type::value_unsigned: + return sax->number_unsigned(number_lexer.get_number_unsigned()); + case token_type::value_float: + return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + case token_type::uninitialized: + case token_type::literal_true: + case token_type::literal_false: + case token_type::literal_null: + case token_type::value_string: + case token_type::begin_array: + case token_type::begin_object: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::parse_error: + case token_type::end_of_input: + case token_type::literal_or_value: + default: + return sax->parse_error(chars_read, number_string, + parse_error::create(115, chars_read, + exception_message(input_format, + concat("invalid number text: ", number_lexer.get_token_string()), + "high-precision number"), + nullptr)); } } @@ -2748,7 +2724,8 @@ class binary_reader @return character read from the input */ - char_int_type get() + char_int_type + get() { ++chars_read; return current = ia.get_character(); @@ -2757,13 +2734,12 @@ class binary_reader /*! @return character read from the input after ignoring all 'N' entries */ - char_int_type get_ignore_noop() + char_int_type + get_ignore_noop() { - do - { + do { get(); - } - while (current == 'N'); + } while (current == 'N'); return current; } @@ -2783,26 +2759,22 @@ class binary_reader On the other hand, BSON and BJData use little endian and should reorder on big endian systems. */ - template - bool get_number(const input_format_t format, NumberType& result) + template + bool + get_number(const input_format_t format, NumberType& result) { // step 1: read input into array with system's byte order - std::array vec{}; - for (std::size_t i = 0; i < sizeof(NumberType); ++i) - { + std::array vec {}; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) { return false; } // reverse byte order prior to conversion if necessary - if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) - { + if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) { vec[sizeof(NumberType) - i - 1] = static_cast(current); - } - else - { + } else { vec[i] = static_cast(current); // LCOV_EXCL_LINE } } @@ -2826,17 +2798,14 @@ class binary_reader may be too large. Usually, @ref unexpect_eof() detects the end of the input before we run out of string memory. */ - template - bool get_string(const input_format_t format, - const NumberType len, - string_t& result) + template + bool + get_string(const input_format_t format, const NumberType len, string_t& result) { bool success = true; - for (NumberType i = 0; i < len; i++) - { + for (NumberType i = 0; i < len; i++) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) { success = false; break; } @@ -2859,17 +2828,14 @@ class binary_reader may be too large. Usually, @ref unexpect_eof() detects the end of the input before we run out of memory. */ - template - bool get_binary(const input_format_t format, - const NumberType len, - binary_t& result) + template + bool + get_binary(const input_format_t format, const NumberType len, binary_t& result) { bool success = true; - for (NumberType i = 0; i < len; i++) - { + for (NumberType i = 0; i < len; i++) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) - { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) { success = false; break; } @@ -2884,12 +2850,13 @@ class binary_reader @return whether the last read character is not EOF */ JSON_HEDLEY_NON_NULL(3) - bool unexpect_eof(const input_format_t format, const char* context) const + bool + unexpect_eof(const input_format_t format, const char* context) const { - if (JSON_HEDLEY_UNLIKELY(current == char_traits::eof())) - { + if (JSON_HEDLEY_UNLIKELY(current == char_traits::eof())) { return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + parse_error::create(110, chars_read, + exception_message(format, "unexpected end of input", context), nullptr)); } return true; } @@ -2897,11 +2864,14 @@ class binary_reader /*! @return a string representation of the last read byte */ - std::string get_token_string() const + std::string + get_token_string() const { - std::array cr{{}}; - static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - return std::string{cr.data()}; + std::array cr { {} }; + static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", + static_cast( + current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return std::string { cr.data() }; } /*! @@ -2910,43 +2880,43 @@ class binary_reader @param[in] context further context information @return a message string to use in the parse_error exceptions */ - std::string exception_message(const input_format_t format, - const std::string& detail, - const std::string& context) const + std::string + exception_message( + const input_format_t format, const std::string& detail, const std::string& context) const { std::string error_msg = "syntax error while parsing "; - switch (format) - { - case input_format_t::cbor: - error_msg += "CBOR"; - break; + switch (format) { + case input_format_t::cbor: + error_msg += "CBOR"; + break; - case input_format_t::msgpack: - error_msg += "MessagePack"; - break; + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; - case input_format_t::ubjson: - error_msg += "UBJSON"; - break; + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; - case input_format_t::bson: - error_msg += "BSON"; - break; + case input_format_t::bson: + error_msg += "BSON"; + break; - case input_format_t::bjdata: - error_msg += "BJData"; - break; + case input_format_t::bjdata: + error_msg += "BJData"; + break; - case input_format_t::json: // LCOV_EXCL_LINE - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // LCOV_EXCL_LINE } return concat(error_msg, ' ', context, ": ", detail); } - private: +private: static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast(-1); /// input adapter @@ -2968,42 +2938,35 @@ class binary_reader json_sax_t* sax = nullptr; // excluded markers in bjdata optimized type -#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ +#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ make_array('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') -#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ - make_array( \ - bjd_type{'C', "char"}, \ - bjd_type{'D', "double"}, \ - bjd_type{'I', "int16"}, \ - bjd_type{'L', "int64"}, \ - bjd_type{'M', "uint64"}, \ - bjd_type{'U', "uint8"}, \ - bjd_type{'d', "single"}, \ - bjd_type{'i', "int8"}, \ - bjd_type{'l', "int32"}, \ - bjd_type{'m', "uint32"}, \ - bjd_type{'u', "uint16"}) - - JSON_PRIVATE_UNLESS_TESTED: - // lookup tables - // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) - const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = - JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; +#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ + make_array(bjd_type { 'C', "char" }, bjd_type { 'D', "double" }, \ + bjd_type { 'I', "int16" }, bjd_type { 'L', "int64" }, bjd_type { 'M', "uint64" }, \ + bjd_type { 'U', "uint8" }, bjd_type { 'd', "single" }, bjd_type { 'i', "int8" }, \ + bjd_type { 'l', "int32" }, bjd_type { 'm', "uint32" }, bjd_type { 'u', "uint16" }) + + JSON_PRIVATE_UNLESS_TESTED : + // lookup tables + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) + bjd_optimized_type_markers + = JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; using bjd_type = std::pair; // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) - const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = - JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; + const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map + = JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ }; #ifndef JSON_HAS_CPP_17 - template - constexpr std::size_t binary_reader::npos; +template +constexpr std::size_t binary_reader::npos; #endif -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/input/input_adapters.hpp b/modules/commons/src/include/nlohmann/detail/input/input_adapters.hpp index 33fca3e4b9..7628877f0f 100644 --- a/modules/commons/src/include/nlohmann/detail/input/input_adapters.hpp +++ b/modules/commons/src/include/nlohmann/detail/input/input_adapters.hpp @@ -19,20 +19,27 @@ #include // pair, declval #ifndef JSON_NO_IO - #include // FILE * - #include // istream -#endif // JSON_NO_IO +#include // FILE * +#include // istream +#endif // JSON_NO_IO #include #include #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; +enum class input_format_t +{ + json, + cbor, + msgpack, + ubjson, + bson, + bjdata +}; //////////////////// // input adapters // @@ -45,12 +52,11 @@ Input adapter for stdio file access. This adapter read only 1 byte and do not us */ class file_input_adapter { - public: +public: using char_type = char; JSON_HEDLEY_NON_NULL(2) - explicit file_input_adapter(std::FILE* f) noexcept - : m_file(f) + explicit file_input_adapter(std::FILE* f) noexcept : m_file(f) { JSON_ASSERT(m_file != nullptr); } @@ -58,16 +64,21 @@ class file_input_adapter // make class move-only file_input_adapter(const file_input_adapter&) = delete; file_input_adapter(file_input_adapter&&) noexcept = default; - file_input_adapter& operator=(const file_input_adapter&) = delete; - file_input_adapter& operator=(file_input_adapter&&) = delete; + file_input_adapter& + operator=(const file_input_adapter&) + = delete; + file_input_adapter& + operator=(file_input_adapter&&) + = delete; ~file_input_adapter() = default; - std::char_traits::int_type get_character() noexcept + std::char_traits::int_type + get_character() noexcept { return std::fgetc(m_file); } - private: +private: /// the file pointer to read from std::FILE* m_file; }; @@ -83,30 +94,30 @@ subsequent call for input from the std::istream. */ class input_stream_adapter { - public: +public: using char_type = char; ~input_stream_adapter() { // clear stream flags; we use underlying streambuf I/O, do not // maintain ifstream flags, except eof - if (is != nullptr) - { + if (is != nullptr) { is->clear(is->rdstate() & std::ios::eofbit); } } - explicit input_stream_adapter(std::istream& i) - : is(&i), sb(i.rdbuf()) - {} + explicit input_stream_adapter(std::istream& i) : is(&i), sb(i.rdbuf()) { } // delete because of pointer members input_stream_adapter(const input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&&) = delete; - - input_stream_adapter(input_stream_adapter&& rhs) noexcept - : is(rhs.is), sb(rhs.sb) + input_stream_adapter& + operator=(input_stream_adapter&) + = delete; + input_stream_adapter& + operator=(input_stream_adapter&&) + = delete; + + input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb) { rhs.is = nullptr; rhs.sb = nullptr; @@ -115,40 +126,40 @@ class input_stream_adapter // std::istream/std::streambuf use std::char_traits::to_int_type, to // ensure that std::char_traits::eof() and the character 0xFF do not // end up as the same value, e.g. 0xFFFFFFFF. - std::char_traits::int_type get_character() + std::char_traits::int_type + get_character() { auto res = sb->sbumpc(); // set eof manually, as we don't use the istream interface. - if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) - { + if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) { is->clear(is->rdstate() | std::ios::eofbit); } return res; } - private: +private: /// the associated input stream std::istream* is = nullptr; std::streambuf* sb = nullptr; }; -#endif // JSON_NO_IO +#endif // JSON_NO_IO // General-purpose iterator-based adapter. It might not be as fast as // theoretically possible for some containers, but it is extremely versatile. -template -class iterator_input_adapter +template class iterator_input_adapter { - public: +public: using char_type = typename std::iterator_traits::value_type; iterator_input_adapter(IteratorType first, IteratorType last) : current(std::move(first)), end(std::move(last)) - {} + { + } - typename char_traits::int_type get_character() + typename char_traits::int_type + get_character() { - if (JSON_HEDLEY_LIKELY(current != end)) - { + if (JSON_HEDLEY_LIKELY(current != end)) { auto result = char_traits::to_int_type(*current); std::advance(current, 1); return result; @@ -157,72 +168,67 @@ class iterator_input_adapter return char_traits::eof(); } - private: +private: IteratorType current; IteratorType end; - template - friend struct wide_string_input_helper; + template friend struct wide_string_input_helper; - bool empty() const + bool + empty() const { return current == end; } }; -template -struct wide_string_input_helper; +template struct wide_string_input_helper; -template -struct wide_string_input_helper +template struct wide_string_input_helper { // UTF-32 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) + static void + fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) { utf8_bytes_index = 0; - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { + if (JSON_HEDLEY_UNLIKELY(input.empty())) { utf8_bytes[0] = std::char_traits::eof(); utf8_bytes_filled = 1; - } - else - { + } else { // get the current character const auto wc = input.get_character(); // UTF-32 to UTF-8 encoding - if (wc < 0x80) - { + if (wc < 0x80) { utf8_bytes[0] = static_cast::int_type>(wc); utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + } else if (wc <= 0x7FF) { + utf8_bytes[0] = static_cast::int_type>( + 0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>( + 0x80u | (static_cast(wc) & 0x3Fu)); utf8_bytes_filled = 2; - } - else if (wc <= 0xFFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + } else if (wc <= 0xFFFF) { + utf8_bytes[0] = static_cast::int_type>( + 0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>( + 0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>( + 0x80u | (static_cast(wc) & 0x3Fu)); utf8_bytes_filled = 3; - } - else if (wc <= 0x10FFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + } else if (wc <= 0x10FFFF) { + utf8_bytes[0] = static_cast::int_type>( + 0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>( + 0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>( + 0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>( + 0x80u | (static_cast(wc) & 0x3Fu)); utf8_bytes_filled = 4; - } - else - { + } else { // unknown character utf8_bytes[0] = static_cast::int_type>(wc); utf8_bytes_filled = 1; @@ -231,60 +237,56 @@ struct wide_string_input_helper } }; -template -struct wide_string_input_helper +template struct wide_string_input_helper { // UTF-16 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) + static void + fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) { utf8_bytes_index = 0; - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { + if (JSON_HEDLEY_UNLIKELY(input.empty())) { utf8_bytes[0] = std::char_traits::eof(); utf8_bytes_filled = 1; - } - else - { + } else { // get the current character const auto wc = input.get_character(); // UTF-16 to UTF-8 encoding - if (wc < 0x80) - { + if (wc < 0x80) { utf8_bytes[0] = static_cast::int_type>(wc); utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + } else if (wc <= 0x7FF) { + utf8_bytes[0] = static_cast::int_type>( + 0xC0u | ((static_cast(wc) >> 6u))); + utf8_bytes[1] = static_cast::int_type>( + 0x80u | (static_cast(wc) & 0x3Fu)); utf8_bytes_filled = 2; - } - else if (0xD800 > wc || wc >= 0xE000) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + } else if (0xD800 > wc || wc >= 0xE000) { + utf8_bytes[0] = static_cast::int_type>( + 0xE0u | ((static_cast(wc) >> 12u))); + utf8_bytes[1] = static_cast::int_type>( + 0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>( + 0x80u | (static_cast(wc) & 0x3Fu)); utf8_bytes_filled = 3; - } - else - { - if (JSON_HEDLEY_UNLIKELY(!input.empty())) - { + } else { + if (JSON_HEDLEY_UNLIKELY(!input.empty())) { const auto wc2 = static_cast(input.get_character()); - const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); - utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + const auto charcode = 0x10000u + + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] + = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>( + 0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>( + 0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] + = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); utf8_bytes_filled = 4; - } - else - { + } else { utf8_bytes[0] = static_cast::int_type>(wc); utf8_bytes_filled = 1; } @@ -294,20 +296,18 @@ struct wide_string_input_helper }; // Wraps another input adapter to convert wide character types into individual bytes. -template -class wide_string_input_adapter +template class wide_string_input_adapter { - public: +public: using char_type = char; - wide_string_input_adapter(BaseInputAdapter base) - : base_adapter(base) {} + wide_string_input_adapter(BaseInputAdapter base) : base_adapter(base) { } - typename std::char_traits::int_type get_character() noexcept + typename std::char_traits::int_type + get_character() noexcept { // check if buffer needs to be filled - if (utf8_bytes_index == utf8_bytes_filled) - { + if (utf8_bytes_index == utf8_bytes_filled) { fill_buffer(); JSON_ASSERT(utf8_bytes_filled > 0); @@ -320,17 +320,19 @@ class wide_string_input_adapter return utf8_bytes[utf8_bytes_index++]; } - private: +private: BaseInputAdapter base_adapter; - template - void fill_buffer() + template + void + fill_buffer() { - wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + wide_string_input_helper::fill_buffer( + base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); } /// a buffer for UTF-8 bytes - std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + std::array::int_type, 4> utf8_bytes = { { 0, 0, 0, 0 } }; /// index to the utf8_codes array for the next valid byte std::size_t utf8_bytes_index = 0; @@ -338,21 +340,20 @@ class wide_string_input_adapter std::size_t utf8_bytes_filled = 0; }; -template -struct iterator_input_adapter_factory +template struct iterator_input_adapter_factory { using iterator_type = IteratorType; using char_type = typename std::iterator_traits::value_type; using adapter_type = iterator_input_adapter; - static adapter_type create(IteratorType first, IteratorType last) + static adapter_type + create(IteratorType first, IteratorType last) { return adapter_type(std::move(first), std::move(last)); } }; -template -struct is_iterator_of_multibyte +template struct is_iterator_of_multibyte { using value_type = typename std::iterator_traits::value_type; enum @@ -361,23 +362,26 @@ struct is_iterator_of_multibyte }; }; -template -struct iterator_input_adapter_factory::value>> +template +struct iterator_input_adapter_factory::value>> { using iterator_type = IteratorType; using char_type = typename std::iterator_traits::value_type; using base_adapter_type = iterator_input_adapter; using adapter_type = wide_string_input_adapter; - static adapter_type create(IteratorType first, IteratorType last) + static adapter_type + create(IteratorType first, IteratorType last) { return adapter_type(base_adapter_type(std::move(first), std::move(last))); } }; // General purpose iterator-based input -template -typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) +template +typename iterator_input_adapter_factory::adapter_type +input_adapter(IteratorType first, IteratorType last) { using factory_type = iterator_input_adapter_factory; return factory_type::create(first, last); @@ -387,72 +391,83 @@ typename iterator_input_adapter_factory::adapter_type input_adapte // Enables ADL on begin(container) and end(container) // Encloses the using declarations in namespace for not to leak them to outside scope -namespace container_input_adapter_factory_impl -{ +namespace container_input_adapter_factory_impl { -using std::begin; -using std::end; + using std::begin; + using std::end; -template -struct container_input_adapter_factory {}; + template struct container_input_adapter_factory + { }; -template -struct container_input_adapter_factory< ContainerType, - void_t()), end(std::declval()))>> - { - using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); + template + struct container_input_adapter_factory()), end(std::declval()))>> + { + using adapter_type = decltype(input_adapter( + begin(std::declval()), end(std::declval()))); - static adapter_type create(const ContainerType& container) -{ - return input_adapter(begin(container), end(container)); -} - }; + static adapter_type + create(const ContainerType& container) + { + return input_adapter(begin(container), end(container)); + } + }; -} // namespace container_input_adapter_factory_impl +} // namespace container_input_adapter_factory_impl -template -typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) +template +typename container_input_adapter_factory_impl::container_input_adapter_factory< + ContainerType>::adapter_type +input_adapter(const ContainerType& container) { - return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); + return container_input_adapter_factory_impl::container_input_adapter_factory< + ContainerType>::create(container); } #ifndef JSON_NO_IO // Special cases with fast paths -inline file_input_adapter input_adapter(std::FILE* file) +inline file_input_adapter +input_adapter(std::FILE* file) { return file_input_adapter(file); } -inline input_stream_adapter input_adapter(std::istream& stream) +inline input_stream_adapter +input_adapter(std::istream& stream) { return input_stream_adapter(stream); } -inline input_stream_adapter input_adapter(std::istream&& stream) +inline input_stream_adapter +input_adapter(std::istream&& stream) { return input_stream_adapter(stream); } -#endif // JSON_NO_IO +#endif // JSON_NO_IO -using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); +using contiguous_bytes_input_adapter + = decltype(input_adapter(std::declval(), std::declval())); // Null-delimited strings, and the like. -template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - !std::is_array::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > -contiguous_bytes_input_adapter input_adapter(CharT b) +template ::value && !std::is_array::value + && std::is_integral::type>::value + && sizeof(typename std::remove_pointer::type) == 1, + int>::type + = 0> +contiguous_bytes_input_adapter +input_adapter(CharT b) { auto length = std::strlen(reinterpret_cast(b)); const auto* ptr = reinterpret_cast(b); return input_adapter(ptr, ptr + length); } -template -auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +template +auto +input_adapter(T (&array)[N]) -> decltype(input_adapter(array, + array + + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { return input_adapter(array, array + N); } @@ -462,31 +477,37 @@ auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) / // to the correct adapter. class span_input_adapter { - public: - template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > +public: + template ::value + && std::is_integral::type>::value + && sizeof(typename std::remove_pointer::type) == 1, + int>::type + = 0> span_input_adapter(CharT b, std::size_t l) - : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} + : ia(reinterpret_cast(b), reinterpret_cast(b) + l) + { + } - template::iterator_category, std::random_access_iterator_tag>::value, - int>::type = 0> - span_input_adapter(IteratorType first, IteratorType last) - : ia(input_adapter(first, last)) {} + template ::iterator_category, + std::random_access_iterator_tag>::value, + int>::type + = 0> + span_input_adapter(IteratorType first, IteratorType last) : ia(input_adapter(first, last)) + { + } - contiguous_bytes_input_adapter&& get() + contiguous_bytes_input_adapter&& + get() { return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) } - private: +private: contiguous_bytes_input_adapter ia; }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/input/json_sax.hpp b/modules/commons/src/include/nlohmann/detail/input/json_sax.hpp index c772521cd8..1c17d9ddaa 100644 --- a/modules/commons/src/include/nlohmann/detail/input/json_sax.hpp +++ b/modules/commons/src/include/nlohmann/detail/input/json_sax.hpp @@ -27,8 +27,7 @@ Each function is called in different situations while the input is parsed. The boolean return value informs the parser whether to continue processing the input. */ -template -struct json_sax +template struct json_sax { using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; @@ -40,28 +39,36 @@ struct json_sax @brief a null value was read @return whether parsing should proceed */ - virtual bool null() = 0; + virtual bool + null() + = 0; /*! @brief a boolean value was read @param[in] val boolean value @return whether parsing should proceed */ - virtual bool boolean(bool val) = 0; + virtual bool + boolean(bool val) + = 0; /*! @brief an integer number was read @param[in] val integer value @return whether parsing should proceed */ - virtual bool number_integer(number_integer_t val) = 0; + virtual bool + number_integer(number_integer_t val) + = 0; /*! @brief an unsigned integer number was read @param[in] val unsigned integer value @return whether parsing should proceed */ - virtual bool number_unsigned(number_unsigned_t val) = 0; + virtual bool + number_unsigned(number_unsigned_t val) + = 0; /*! @brief a floating-point number was read @@ -69,7 +76,9 @@ struct json_sax @param[in] s raw token value @return whether parsing should proceed */ - virtual bool number_float(number_float_t val, const string_t& s) = 0; + virtual bool + number_float(number_float_t val, const string_t& s) + = 0; /*! @brief a string value was read @@ -77,7 +86,9 @@ struct json_sax @return whether parsing should proceed @note It is safe to move the passed string value. */ - virtual bool string(string_t& val) = 0; + virtual bool + string(string_t& val) + = 0; /*! @brief a binary value was read @@ -85,7 +96,9 @@ struct json_sax @return whether parsing should proceed @note It is safe to move the passed binary value. */ - virtual bool binary(binary_t& val) = 0; + virtual bool + binary(binary_t& val) + = 0; /*! @brief the beginning of an object was read @@ -93,7 +106,9 @@ struct json_sax @return whether parsing should proceed @note binary formats may report the number of elements */ - virtual bool start_object(std::size_t elements) = 0; + virtual bool + start_object(std::size_t elements) + = 0; /*! @brief an object key was read @@ -101,13 +116,17 @@ struct json_sax @return whether parsing should proceed @note It is safe to move the passed string. */ - virtual bool key(string_t& val) = 0; + virtual bool + key(string_t& val) + = 0; /*! @brief the end of an object was read @return whether parsing should proceed */ - virtual bool end_object() = 0; + virtual bool + end_object() + = 0; /*! @brief the beginning of an array was read @@ -115,13 +134,17 @@ struct json_sax @return whether parsing should proceed @note binary formats may report the number of elements */ - virtual bool start_array(std::size_t elements) = 0; + virtual bool + start_array(std::size_t elements) + = 0; /*! @brief the end of an array was read @return whether parsing should proceed */ - virtual bool end_array() = 0; + virtual bool + end_array() + = 0; /*! @brief a parse error occurred @@ -130,20 +153,23 @@ struct json_sax @param[in] ex an exception object describing the error @return whether parsing should proceed (must return false) */ - virtual bool parse_error(std::size_t position, - const std::string& last_token, - const detail::exception& ex) = 0; + virtual bool + parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex) + = 0; json_sax() = default; json_sax(const json_sax&) = default; json_sax(json_sax&&) noexcept = default; - json_sax& operator=(const json_sax&) = default; - json_sax& operator=(json_sax&&) noexcept = default; + json_sax& + operator=(const json_sax&) + = default; + json_sax& + operator=(json_sax&&) noexcept + = default; virtual ~json_sax() = default; }; -namespace detail -{ +namespace detail { /*! @brief SAX implementation to create a JSON value from SAX events @@ -157,10 +183,9 @@ constructor contains the parsed value. @tparam BasicJsonType the JSON type */ -template -class json_sax_dom_parser +template class json_sax_dom_parser { - public: +public: using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using number_float_t = typename BasicJsonType::number_float_t; @@ -174,70 +199,86 @@ class json_sax_dom_parser */ explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) : root(r), allow_exceptions(allow_exceptions_) - {} + { + } // make class move-only json_sax_dom_parser(const json_sax_dom_parser&) = delete; - json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; - json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_parser(json_sax_dom_parser&&) + = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_parser& + operator=(const json_sax_dom_parser&) + = delete; + json_sax_dom_parser& + operator=(json_sax_dom_parser&&) + = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) ~json_sax_dom_parser() = default; - bool null() + bool + null() { handle_value(nullptr); return true; } - bool boolean(bool val) + bool + boolean(bool val) { handle_value(val); return true; } - bool number_integer(number_integer_t val) + bool + number_integer(number_integer_t val) { handle_value(val); return true; } - bool number_unsigned(number_unsigned_t val) + bool + number_unsigned(number_unsigned_t val) { handle_value(val); return true; } - bool number_float(number_float_t val, const string_t& /*unused*/) + bool + number_float(number_float_t val, const string_t& /*unused*/) { handle_value(val); return true; } - bool string(string_t& val) + bool + string(string_t& val) { handle_value(val); return true; } - bool binary(binary_t& val) + bool + binary(binary_t& val) { handle_value(std::move(val)); return true; } - bool start_object(std::size_t len) + bool + start_object(std::size_t len) { ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); - if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); + if (JSON_HEDLEY_UNLIKELY( + len != static_cast(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create( + 408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); } return true; } - bool key(string_t& val) + bool + key(string_t& val) { JSON_ASSERT(!ref_stack.empty()); JSON_ASSERT(ref_stack.back()->is_object()); @@ -247,7 +288,8 @@ class json_sax_dom_parser return true; } - bool end_object() + bool + end_object() { JSON_ASSERT(!ref_stack.empty()); JSON_ASSERT(ref_stack.back()->is_object()); @@ -257,19 +299,22 @@ class json_sax_dom_parser return true; } - bool start_array(std::size_t len) + bool + start_array(std::size_t len) { ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); - if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + if (JSON_HEDLEY_UNLIKELY( + len != static_cast(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create( + 408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); } return true; } - bool end_array() + bool + end_array() { JSON_ASSERT(!ref_stack.empty()); JSON_ASSERT(ref_stack.back()->is_array()); @@ -279,45 +324,43 @@ class json_sax_dom_parser return true; } - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) + template + bool + parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex) { errored = true; static_cast(ex); - if (allow_exceptions) - { + if (allow_exceptions) { JSON_THROW(ex); } return false; } - constexpr bool is_errored() const + constexpr bool + is_errored() const { return errored; } - private: +private: /*! @invariant If the ref stack is empty, then the passed value will be the new root. @invariant If the ref stack contains a value, then it is an array or an object to which we can add elements */ - template - JSON_HEDLEY_RETURNS_NON_NULL - BasicJsonType* handle_value(Value&& v) + template + JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType* + handle_value(Value&& v) { - if (ref_stack.empty()) - { + if (ref_stack.empty()) { root = BasicJsonType(std::forward(v)); return &root; } JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - if (ref_stack.back()->is_array()) - { + 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()); } @@ -340,10 +383,9 @@ class json_sax_dom_parser const bool allow_exceptions = true; }; -template -class json_sax_dom_callback_parser +template class json_sax_dom_callback_parser { - public: +public: using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using number_float_t = typename BasicJsonType::number_float_t; @@ -352,9 +394,8 @@ class json_sax_dom_callback_parser using parser_callback_t = typename BasicJsonType::parser_callback_t; using parse_event_t = typename BasicJsonType::parse_event_t; - json_sax_dom_callback_parser(BasicJsonType& r, - const parser_callback_t cb, - const bool allow_exceptions_ = true) + json_sax_dom_callback_parser( + BasicJsonType& r, const parser_callback_t cb, const bool allow_exceptions_ = true) : root(r), callback(cb), allow_exceptions(allow_exceptions_) { keep_stack.push_back(true); @@ -362,72 +403,89 @@ class json_sax_dom_callback_parser // make class move-only json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) + = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_callback_parser& + operator=(const json_sax_dom_callback_parser&) + = delete; + json_sax_dom_callback_parser& + operator=(json_sax_dom_callback_parser&&) + = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) ~json_sax_dom_callback_parser() = default; - bool null() + bool + null() { handle_value(nullptr); return true; } - bool boolean(bool val) + bool + boolean(bool val) { handle_value(val); return true; } - bool number_integer(number_integer_t val) + bool + number_integer(number_integer_t val) { handle_value(val); return true; } - bool number_unsigned(number_unsigned_t val) + bool + number_unsigned(number_unsigned_t val) { handle_value(val); return true; } - bool number_float(number_float_t val, const string_t& /*unused*/) + bool + number_float(number_float_t val, const string_t& /*unused*/) { handle_value(val); return true; } - bool string(string_t& val) + bool + string(string_t& val) { handle_value(val); return true; } - bool binary(binary_t& val) + bool + binary(binary_t& val) { handle_value(std::move(val)); return true; } - bool start_object(std::size_t len) + bool + start_object(std::size_t len) { // check callback for object start - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + const bool keep + = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); keep_stack.push_back(keep); auto val = handle_value(BasicJsonType::value_t::object, true); ref_stack.push_back(val.second); // check object limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); + if (ref_stack.back() + && JSON_HEDLEY_UNLIKELY( + len != static_cast(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create( + 408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); } return true; } - bool key(string_t& val) + bool + key(string_t& val) { BasicJsonType k = BasicJsonType(val); @@ -436,25 +494,23 @@ class json_sax_dom_callback_parser key_keep_stack.push_back(keep); // add discarded value at given key and store the reference for later - if (keep && ref_stack.back()) - { - object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); + if (keep && ref_stack.back()) { + object_element + = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); } return true; } - bool end_object() + bool + end_object() { - if (ref_stack.back()) - { - if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) - { + if (ref_stack.back()) { + if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, + *ref_stack.back())) { // discard object *ref_stack.back() = discarded; - } - else - { + } else { ref_stack.back()->set_parents(); } } @@ -464,13 +520,10 @@ class json_sax_dom_callback_parser ref_stack.pop_back(); keep_stack.pop_back(); - if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) - { + if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) { // remove discarded value - for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) - { - if (it->is_discarded()) - { + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) { + if (it->is_discarded()) { ref_stack.back()->erase(it); break; } @@ -480,36 +533,38 @@ class json_sax_dom_callback_parser return true; } - bool start_array(std::size_t len) + bool + start_array(std::size_t len) { - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + const bool keep + = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); keep_stack.push_back(keep); auto val = handle_value(BasicJsonType::value_t::array, true); ref_stack.push_back(val.second); // check array limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + if (ref_stack.back() + && JSON_HEDLEY_UNLIKELY( + len != static_cast(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create( + 408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); } return true; } - bool end_array() + bool + end_array() { bool keep = true; - if (ref_stack.back()) - { - keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); - if (keep) - { + if (ref_stack.back()) { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, + *ref_stack.back()); + if (keep) { ref_stack.back()->set_parents(); - } - else - { + } else { // discard array *ref_stack.back() = discarded; } @@ -521,33 +576,32 @@ class json_sax_dom_callback_parser keep_stack.pop_back(); // remove discarded value - if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) - { + if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) { ref_stack.back()->m_data.m_value.array->pop_back(); } return true; } - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) + template + bool + parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex) { errored = true; static_cast(ex); - if (allow_exceptions) - { + if (allow_exceptions) { JSON_THROW(ex); } return false; } - constexpr bool is_errored() const + constexpr bool + is_errored() const { return errored; } - private: +private: /*! @param[in] v value to add to the JSON value we build during parsing @param[in] skip_callback whether we should skip calling the callback @@ -563,51 +617,48 @@ class json_sax_dom_callback_parser @return pair of boolean (whether value should be kept) and pointer (to the passed value in the ref_stack hierarchy; nullptr if not kept) */ - template - std::pair handle_value(Value&& v, const bool skip_callback = false) + template + std::pair + handle_value(Value&& v, const bool skip_callback = false) { JSON_ASSERT(!keep_stack.empty()); // do not handle this value if we know it would be added to a discarded // container - if (!keep_stack.back()) - { - return {false, nullptr}; + if (!keep_stack.back()) { + return { false, nullptr }; } // create value auto value = BasicJsonType(std::forward(v)); // check callback - const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); + const bool keep = skip_callback + || callback(static_cast(ref_stack.size()), parse_event_t::value, value); // do not handle this value if we just learnt it shall be discarded - if (!keep) - { - return {false, nullptr}; + if (!keep) { + return { false, nullptr }; } - if (ref_stack.empty()) - { + 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 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) - if (!ref_stack.back()) - { - return {false, nullptr}; + if (!ref_stack.back()) { + return { false, nullptr }; } // we now only expect arrays and objects JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); // array - if (ref_stack.back()->is_array()) - { + 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())}; + return { true, &(ref_stack.back()->m_data.m_value.array->back()) }; } // object @@ -617,14 +668,13 @@ class json_sax_dom_callback_parser const bool store_element = key_keep_stack.back(); key_keep_stack.pop_back(); - if (!store_element) - { - return {false, nullptr}; + if (!store_element) { + return { false, nullptr }; } JSON_ASSERT(object_element); *object_element = std::move(value); - return {true, object_element}; + return { true, object_element }; } /// the parsed JSON value @@ -647,81 +697,94 @@ class json_sax_dom_callback_parser BasicJsonType discarded = BasicJsonType::value_t::discarded; }; -template -class json_sax_acceptor +template class json_sax_acceptor { - public: +public: using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using number_float_t = typename BasicJsonType::number_float_t; using string_t = typename BasicJsonType::string_t; using binary_t = typename BasicJsonType::binary_t; - bool null() + bool + null() { return true; } - bool boolean(bool /*unused*/) + bool + boolean(bool /*unused*/) { return true; } - bool number_integer(number_integer_t /*unused*/) + bool + number_integer(number_integer_t /*unused*/) { return true; } - bool number_unsigned(number_unsigned_t /*unused*/) + bool + number_unsigned(number_unsigned_t /*unused*/) { return true; } - bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + bool + number_float(number_float_t /*unused*/, const string_t& /*unused*/) { return true; } - bool string(string_t& /*unused*/) + bool + string(string_t& /*unused*/) { return true; } - bool binary(binary_t& /*unused*/) + bool + binary(binary_t& /*unused*/) { return true; } - bool start_object(std::size_t /*unused*/ = static_cast(-1)) + bool + start_object(std::size_t /*unused*/ = static_cast(-1)) { return true; } - bool key(string_t& /*unused*/) + bool + key(string_t& /*unused*/) { return true; } - bool end_object() + bool + end_object() { return true; } - bool start_array(std::size_t /*unused*/ = static_cast(-1)) + bool + start_array(std::size_t /*unused*/ = static_cast(-1)) { return true; } - bool end_array() + bool + end_array() { return true; } - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + bool + parse_error( + std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) { return false; } }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/input/lexer.hpp b/modules/commons/src/include/nlohmann/detail/input/lexer.hpp index 4b3bf77d62..e738c3224c 100644 --- a/modules/commons/src/include/nlohmann/detail/input/lexer.hpp +++ b/modules/commons/src/include/nlohmann/detail/input/lexer.hpp @@ -24,82 +24,80 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /////////// // lexer // /////////// -template -class lexer_base +template class lexer_base { - public: +public: /// token types for the parser enum class token_type { - uninitialized, ///< indicating the scanner is uninitialized - literal_true, ///< the `true` literal - literal_false, ///< the `false` literal - literal_null, ///< the `null` literal - value_string, ///< a string -- use get_string() for actual value - value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value - value_integer, ///< a signed integer -- use get_number_integer() for actual value - value_float, ///< an floating point number -- use get_number_float() for actual value - begin_array, ///< the character for array begin `[` - begin_object, ///< the character for object begin `{` - end_array, ///< the character for array end `]` - end_object, ///< the character for object end `}` - name_separator, ///< the name separator `:` - value_separator, ///< the value separator `,` - parse_error, ///< indicating a parse error - end_of_input, ///< indicating the end of the input buffer - literal_or_value ///< a literal or the begin of a value (only for diagnostics) + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) }; /// return name of values of type token_type (only used for errors) JSON_HEDLEY_RETURNS_NON_NULL JSON_HEDLEY_CONST - static const char* token_type_name(const token_type t) noexcept + static const char* + token_type_name(const token_type t) noexcept { - switch (t) - { - case token_type::uninitialized: - return ""; - case token_type::literal_true: - return "true literal"; - case token_type::literal_false: - return "false literal"; - case token_type::literal_null: - return "null literal"; - case token_type::value_string: - return "string literal"; - case token_type::value_unsigned: - case token_type::value_integer: - case token_type::value_float: - return "number literal"; - case token_type::begin_array: - return "'['"; - case token_type::begin_object: - return "'{'"; - case token_type::end_array: - return "']'"; - case token_type::end_object: - return "'}'"; - case token_type::name_separator: - return "':'"; - case token_type::value_separator: - return "','"; - case token_type::parse_error: - return ""; - case token_type::end_of_input: - return "end of input"; - case token_type::literal_or_value: - return "'[', '{', or a literal"; - // LCOV_EXCL_START - default: // catch non-enum values - return "unknown token"; - // LCOV_EXCL_STOP + switch (t) { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case token_type::value_unsigned: + case token_type::value_integer: + case token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP } } }; @@ -108,7 +106,7 @@ class lexer_base This class organizes the lexical analysis during JSON deserialization. */ -template +template class lexer : public lexer_base { using number_integer_t = typename BasicJsonType::number_integer_t; @@ -118,30 +116,36 @@ class lexer : public lexer_base using char_type = typename InputAdapterType::char_type; using char_int_type = typename char_traits::int_type; - public: +public: using token_type = typename lexer_base::token_type; explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept : ia(std::move(adapter)) , ignore_comments(ignore_comments_) , decimal_point_char(static_cast(get_decimal_point())) - {} + { + } // delete because of pointer members lexer(const lexer&) = delete; lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - lexer& operator=(lexer&) = delete; - lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + lexer& + operator=(lexer&) + = delete; + lexer& + operator=(lexer&&) + = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) ~lexer() = default; - private: +private: ///////////////////// // locales ///////////////////// /// return the locale-dependent decimal point JSON_HEDLEY_PURE - static char get_decimal_point() noexcept + static char + get_decimal_point() noexcept { const auto* loc = localeconv(); JSON_ASSERT(loc != nullptr); @@ -167,31 +171,27 @@ class lexer : public lexer_base @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or non-hex character) */ - int get_codepoint() + int + get_codepoint() { // this function only makes sense after reading `\u` JSON_ASSERT(current == 'u'); int codepoint = 0; const auto factors = { 12u, 8u, 4u, 0u }; - for (const auto factor : factors) - { + for (const auto factor : factors) { get(); - if (current >= '0' && current <= '9') - { - codepoint += static_cast((static_cast(current) - 0x30u) << factor); - } - else if (current >= 'A' && current <= 'F') - { - codepoint += static_cast((static_cast(current) - 0x37u) << factor); - } - else if (current >= 'a' && current <= 'f') - { - codepoint += static_cast((static_cast(current) - 0x57u) << factor); - } - else - { + if (current >= '0' && current <= '9') { + codepoint + += static_cast((static_cast(current) - 0x30u) << factor); + } else if (current >= 'A' && current <= 'F') { + codepoint + += static_cast((static_cast(current) - 0x37u) << factor); + } else if (current >= 'a' && current <= 'f') { + codepoint + += static_cast((static_cast(current) - 0x57u) << factor); + } else { return -1; } } @@ -215,20 +215,19 @@ class lexer : public lexer_base @return true if and only if no range violation was detected */ - bool next_byte_in_range(std::initializer_list ranges) + bool + next_byte_in_range(std::initializer_list ranges) { JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); add(current); - for (auto range = ranges.begin(); range != ranges.end(); ++range) - { + 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))) // NOLINT(bugprone-inc-dec-in-conditions) { add(current); - } - else - { + } else { error_message = "invalid string: ill-formed UTF-8 byte"; return false; } @@ -252,7 +251,8 @@ class lexer : public lexer_base @note In case of errors, variable error_message contains a textual description. */ - token_type scan_string() + token_type + scan_string() { // reset token_buffer (ignore opening quote) reset(); @@ -260,580 +260,554 @@ class lexer : public lexer_base // we entered the function by reading an open quote JSON_ASSERT(current == '\"'); - while (true) - { + while (true) { // get next character - switch (get()) - { - // end of file while parsing string - case char_traits::eof(): - { - error_message = "invalid string: missing closing quote"; - return token_type::parse_error; - } + switch (get()) { + // end of file while parsing string + case char_traits::eof(): { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } - // closing quote - case '\"': - { - return token_type::value_string; - } + // closing quote + case '\"': { + return token_type::value_string; + } - // escapes + // escapes + case '\\': { + switch (get()) { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus case '\\': - { - switch (get()) - { - // quotation mark - case '\"': - add('\"'); - break; - // reverse solidus - case '\\': - add('\\'); - break; - // solidus - case '/': - add('/'); - break; - // backspace - case 'b': - add('\b'); - break; - // form feed - case 'f': - add('\f'); - break; - // line feed - case 'n': - add('\n'); - break; - // carriage return - case 'r': - add('\r'); - break; - // tab - case 't': - add('\t'); - break; - - // unicode escapes - case 'u': - { - const int codepoint1 = get_codepoint(); - int codepoint = codepoint1; // start with codepoint1 - - if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; - // check if code point is a high surrogate - if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) - { - // expect next \uxxxx entry - if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) - { - const int codepoint2 = get_codepoint(); - - if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if codepoint2 is a low surrogate - if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) - { - // overwrite codepoint - codepoint = static_cast( - // high surrogate occupies the most significant 22 bits - (static_cast(codepoint1) << 10u) - // low surrogate occupies the least significant 15 bits - + static_cast(codepoint2) - // there is still the 0xD800, 0xDC00 and 0x10000 noise - // in the result, so we have to subtract with: - // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - - 0x35FDC00u); - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) - { - error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; - return token_type::parse_error; - } - } + // unicode escapes + case 'u': { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 - // result of the above calculation yields a proper codepoint - JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } - // translate codepoint into bytes - if (codepoint < 0x80) - { - // 1-byte characters: 0xxxxxxx (ASCII) - add(static_cast(codepoint)); - } - else if (codepoint <= 0x7FF) - { - // 2-byte characters: 110xxxxx 10xxxxxx - add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else if (codepoint <= 0xFFFF) - { - // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else - { - // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + // check if code point is a high surrogate + if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) { + // expect next \uxxxx entry + if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) { + const int codepoint2 = get_codepoint(); + + if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) { + error_message + = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; } - break; + // check if codepoint2 is a low surrogate + if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) { + // overwrite codepoint + codepoint = static_cast( + // high surrogate occupies the most significant 22 bits + (static_cast(codepoint1) << 10u) + // low surrogate occupies the least significant 15 bits + + static_cast(codepoint2) + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result, so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00u); + } else { + error_message = "invalid string: surrogate U+D800..U+DBFF must be " + "followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } else { + error_message = "invalid string: surrogate U+D800..U+DBFF must be " + "followed by U+DC00..U+DFFF"; + return token_type::parse_error; } - - // other characters after escape - default: - error_message = "invalid string: forbidden character after backslash"; + } else { + if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow " + "U+D800..U+DBFF"; return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) { + // 1-byte characters: 0xxxxxxx (ASCII) + add(static_cast(codepoint)); + } else if (codepoint <= 0x7FF) { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast( + 0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast( + 0x80u | (static_cast(codepoint) & 0x3Fu))); + } else if (codepoint <= 0xFFFF) { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast( + 0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast( + 0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast( + 0x80u | (static_cast(codepoint) & 0x3Fu))); + } else { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast( + 0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast( + 0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast( + 0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast( + 0x80u | (static_cast(codepoint) & 0x3Fu))); } break; } - // invalid control characters - case 0x00: - { - error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; return token_type::parse_error; } - case 0x01: - { - error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; - return token_type::parse_error; - } + break; + } - case 0x02: - { - error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; - return token_type::parse_error; - } + // invalid control characters + case 0x00: { + error_message + = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } - case 0x03: - { - error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; - return token_type::parse_error; - } + case 0x01: { + error_message + = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } - case 0x04: - { - error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; - return token_type::parse_error; - } + case 0x02: { + error_message + = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } - case 0x05: - { - error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; - return token_type::parse_error; - } + case 0x03: { + error_message + = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } - case 0x06: - { - error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; - return token_type::parse_error; - } + case 0x04: { + error_message + = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } - case 0x07: - { - error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; - return token_type::parse_error; - } + case 0x05: { + error_message + = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } - case 0x08: - { - error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; - return token_type::parse_error; - } + case 0x06: { + error_message + = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } - case 0x09: - { - error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; - return token_type::parse_error; - } + case 0x07: { + error_message + = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } - case 0x0A: - { - error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; - return token_type::parse_error; - } + case 0x08: { + error_message = "invalid string: control character U+0008 (BS) must be escaped to " + "\\u0008 or \\b"; + return token_type::parse_error; + } - case 0x0B: - { - error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; - return token_type::parse_error; - } + case 0x09: { + error_message = "invalid string: control character U+0009 (HT) must be escaped to " + "\\u0009 or \\t"; + return token_type::parse_error; + } - case 0x0C: - { - error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; - return token_type::parse_error; - } + case 0x0A: { + error_message = "invalid string: control character U+000A (LF) must be escaped to " + "\\u000A or \\n"; + return token_type::parse_error; + } - case 0x0D: - { - error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; - return token_type::parse_error; - } + case 0x0B: { + error_message + = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } - case 0x0E: - { - error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; - return token_type::parse_error; - } + case 0x0C: { + error_message = "invalid string: control character U+000C (FF) must be escaped to " + "\\u000C or \\f"; + return token_type::parse_error; + } - case 0x0F: - { - error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; - return token_type::parse_error; - } + case 0x0D: { + error_message = "invalid string: control character U+000D (CR) must be escaped to " + "\\u000D or \\r"; + return token_type::parse_error; + } - case 0x10: - { - error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; - return token_type::parse_error; - } + case 0x0E: { + error_message + = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } - case 0x11: - { - error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; - return token_type::parse_error; - } + case 0x0F: { + error_message + = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } - case 0x12: - { - error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; - return token_type::parse_error; - } + case 0x10: { + error_message + = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } - case 0x13: - { - error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; - return token_type::parse_error; - } + case 0x11: { + error_message + = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } - case 0x14: - { - error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; - return token_type::parse_error; - } + case 0x12: { + error_message + = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } - case 0x15: - { - error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; - return token_type::parse_error; - } + case 0x13: { + error_message + = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } - case 0x16: - { - error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; - return token_type::parse_error; - } + case 0x14: { + error_message + = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } - case 0x17: - { - error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; - return token_type::parse_error; - } + case 0x15: { + error_message + = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } - case 0x18: - { - error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; - return token_type::parse_error; - } + case 0x16: { + error_message + = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } - case 0x19: - { - error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; - return token_type::parse_error; - } + case 0x17: { + error_message + = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } - case 0x1A: - { - error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; - return token_type::parse_error; - } + case 0x18: { + error_message + = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } - case 0x1B: - { - error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; - return token_type::parse_error; - } + case 0x19: { + error_message + = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } - case 0x1C: - { - error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; - return token_type::parse_error; - } + case 0x1A: { + error_message + = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } - case 0x1D: - { - error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; - return token_type::parse_error; - } + case 0x1B: { + error_message + = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } - case 0x1E: - { - error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; - return token_type::parse_error; - } + case 0x1C: { + error_message + = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } - case 0x1F: - { - error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; - return token_type::parse_error; - } + case 0x1D: { + error_message + = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } - // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) - case 0x20: - case 0x21: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - { - add(current); - break; - } + case 0x1E: { + error_message + = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } - // U+0080..U+07FF: bytes C2..DF 80..BF - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - { - if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) - { - return token_type::parse_error; - } - break; - } + case 0x1F: { + error_message + = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } - // U+0800..U+0FFF: bytes E0 A0..BF 80..BF - case 0xE0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: { + if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({ 0x80, 0xBF }))) { + return token_type::parse_error; } + break; + } - // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF - // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xEE: - case 0xEF: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0xA0, 0xBF, 0x80, 0xBF })))) { + return token_type::parse_error; } + break; + } - // U+D000..U+D7FF: bytes ED 80..9F 80..BF - case 0xED: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF })))) { + return token_type::parse_error; } + break; + } - // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF - case 0xF0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0x9F, 0x80, 0xBF })))) { + return token_type::parse_error; } + break; + } - // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF - case 0xF1: - case 0xF2: - case 0xF3: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: { + if (JSON_HEDLEY_UNLIKELY( + !(next_byte_in_range({ 0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF })))) { + return token_type::parse_error; } + break; + } - // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF - case 0xF4: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: { + if (JSON_HEDLEY_UNLIKELY( + !(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF })))) { + return token_type::parse_error; } + break; + } - // remaining bytes (80..C1 and F5..FF) are ill-formed - default: - { - error_message = "invalid string: ill-formed UTF-8 byte"; + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: { + if (JSON_HEDLEY_UNLIKELY( + !(next_byte_in_range({ 0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF })))) { return token_type::parse_error; } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } } } } @@ -842,87 +816,79 @@ class lexer : public lexer_base * @brief scan a comment * @return whether comment could be scanned successfully */ - bool scan_comment() + bool + scan_comment() { - switch (get()) - { - // single-line comments skip input until a newline or EOF is read - case '/': - { - while (true) - { - switch (get()) - { - case '\n': - case '\r': - case char_traits::eof(): - case '\0': - return true; - - default: - break; - } + switch (get()) { + // single-line comments skip input until a newline or EOF is read + case '/': { + while (true) { + switch (get()) { + case '\n': + case '\r': + case char_traits::eof(): + case '\0': + return true; + + default: + break; } } + } - // multi-line comments skip input until */ is read - case '*': - { - while (true) - { - switch (get()) - { - case char_traits::eof(): - case '\0': - { - error_message = "invalid comment; missing closing '*/'"; - return false; - } + // multi-line comments skip input until */ is read + case '*': { + while (true) { + switch (get()) { + case char_traits::eof(): + case '\0': { + error_message = "invalid comment; missing closing '*/'"; + return false; + } - case '*': - { - switch (get()) - { - case '/': - return true; - - default: - { - unget(); - continue; - } - } - } + case '*': { + switch (get()) { + case '/': + return true; - default: - continue; + default: { + unget(); + continue; + } } } - } - // unexpected character after reading '/' - default: - { - error_message = "invalid comment; expecting '/' or '*' after '/'"; - return false; + default: + continue; + } } } + + // unexpected character after reading '/' + default: { + error_message = "invalid comment; expecting '/' or '*' after '/'"; + return false; + } + } } JSON_HEDLEY_NON_NULL(2) - static void strtof(float& f, const char* str, char** endptr) noexcept + static void + strtof(float& f, const char* str, char** endptr) noexcept { f = std::strtof(str, endptr); } JSON_HEDLEY_NON_NULL(2) - static void strtof(double& f, const char* str, char** endptr) noexcept + static void + strtof(double& f, const char* str, char** endptr) noexcept { f = std::strtod(str, endptr); } JSON_HEDLEY_NON_NULL(2) - static void strtof(long double& f, const char* str, char** endptr) noexcept + static void + strtof(long double& f, const char* str, char** endptr) noexcept { f = std::strtold(str, endptr); } @@ -967,7 +933,8 @@ class lexer : public lexer_base locale's decimal point is used instead of `.` to work with the locale-dependent converters. */ - token_type scan_number() // lgtm [cpp/use-of-goto] + token_type + scan_number() // lgtm [cpp/use-of-goto] { // reset token_buffer to store the number's bytes reset(); @@ -977,270 +944,240 @@ class lexer : public lexer_base token_type number_type = token_type::value_unsigned; // state (init): we just found out we need to scan a number - switch (current) - { - case '-': - { - add(current); - goto scan_number_minus; - } + switch (current) { + case '-': { + add(current); + goto scan_number_minus; + } - case '0': - { - add(current); - goto scan_number_zero; - } + case '0': { + add(current); + goto scan_number_zero; + } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any1; + } - // all other characters are rejected outside scan_number() - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // LCOV_EXCL_LINE } -scan_number_minus: + scan_number_minus: // state: we just parsed a leading minus sign number_type = token_type::value_integer; - switch (get()) - { - case '0': - { - add(current); - goto scan_number_zero; - } + switch (get()) { + case '0': { + add(current); + goto scan_number_zero; + } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any1; + } - default: - { - error_message = "invalid number; expected digit after '-'"; - return token_type::parse_error; - } + default: { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } } -scan_number_zero: + scan_number_zero: // state: we just parse a zero (maybe with a leading minus sign) - switch (get()) - { - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } + switch (get()) { + case '.': { + add(decimal_point_char); + goto scan_number_decimal1; + } - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } + case 'e': + case 'E': { + add(current); + goto scan_number_exponent; + } - default: - goto scan_number_done; + default: + goto scan_number_done; } -scan_number_any1: + scan_number_any1: // state: we just parsed a number 0-9 (maybe with a leading minus sign) - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any1; + } - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } + case '.': { + add(decimal_point_char); + goto scan_number_decimal1; + } - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } + case 'e': + case 'E': { + add(current); + goto scan_number_exponent; + } - default: - goto scan_number_done; + default: + goto scan_number_done; } -scan_number_decimal1: + scan_number_decimal1: // state: we just parsed a decimal point number_type = token_type::value_float; - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_decimal2; + } - default: - { - error_message = "invalid number; expected digit after '.'"; - return token_type::parse_error; - } + default: { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } } -scan_number_decimal2: + scan_number_decimal2: // we just parsed at least one number after a decimal point - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_decimal2; + } - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } + case 'e': + case 'E': { + add(current); + goto scan_number_exponent; + } - default: - goto scan_number_done; + default: + goto scan_number_done; } -scan_number_exponent: + scan_number_exponent: // we just parsed an exponent number_type = token_type::value_float; - switch (get()) - { - case '+': - case '-': - { - add(current); - goto scan_number_sign; - } + switch (get()) { + case '+': + case '-': { + add(current); + goto scan_number_sign; + } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any2; + } - default: - { - error_message = - "invalid number; expected '+', '-', or digit after exponent"; - return token_type::parse_error; - } + default: { + error_message = "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } } -scan_number_sign: + scan_number_sign: // we just parsed an exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any2; + } - default: - { - error_message = "invalid number; expected digit after exponent sign"; - return token_type::parse_error; - } + default: { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } } -scan_number_any2: + scan_number_any2: // we just parsed a number after the exponent or exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any2; + } - default: - goto scan_number_done; + default: + goto scan_number_done; } -scan_number_done: + scan_number_done: // unget the character after the number (we only read it to know that // we are done scanning a number) unget(); @@ -1249,34 +1186,27 @@ class lexer : public lexer_base errno = 0; // try to parse integers first and fall back to floats - if (number_type == token_type::value_unsigned) - { + if (number_type == token_type::value_unsigned) { const auto x = std::strtoull(token_buffer.data(), &endptr, 10); // we checked the number format before JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - if (errno == 0) - { + if (errno == 0) { value_unsigned = static_cast(x); - if (value_unsigned == x) - { + if (value_unsigned == x) { return token_type::value_unsigned; } } - } - else if (number_type == token_type::value_integer) - { + } else if (number_type == token_type::value_integer) { const auto x = std::strtoll(token_buffer.data(), &endptr, 10); // we checked the number format before JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - if (errno == 0) - { + if (errno == 0) { value_integer = static_cast(x); - if (value_integer == x) - { + if (value_integer == x) { return token_type::value_integer; } } @@ -1298,14 +1228,13 @@ class lexer : public lexer_base @param[in] return_type the token type to return on success */ JSON_HEDLEY_NON_NULL(2) - token_type scan_literal(const char_type* literal_text, const std::size_t length, - token_type return_type) + token_type + scan_literal(const char_type* literal_text, const std::size_t length, token_type return_type) { JSON_ASSERT(char_traits::to_char_type(current) == literal_text[0]); - for (std::size_t i = 1; i < length; ++i) - { - if (JSON_HEDLEY_UNLIKELY(char_traits::to_char_type(get()) != literal_text[i])) - { + for (std::size_t i = 1; i < length; ++i) { + if (JSON_HEDLEY_UNLIKELY( + char_traits::to_char_type(get()) != literal_text[i])) { error_message = "invalid literal"; return token_type::parse_error; } @@ -1318,7 +1247,8 @@ class lexer : public lexer_base ///////////////////// /// reset token_buffer; current character is beginning of token - void reset() noexcept + void + reset() noexcept { token_buffer.clear(); token_string.clear(); @@ -1335,28 +1265,24 @@ class lexer : public lexer_base @return character read from the input */ - char_int_type get() + char_int_type + get() { ++position.chars_read_total; ++position.chars_read_current_line; - if (next_unget) - { + if (next_unget) { // just reset the next_unget variable and work with current next_unget = false; - } - else - { + } else { current = ia.get_character(); } - if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) - { + if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) { token_string.push_back(char_traits::to_char_type(current)); } - if (current == '\n') - { + if (current == '\n') { ++position.lines_read; position.chars_read_current_line = 0; } @@ -1372,63 +1298,64 @@ class lexer : public lexer_base chars_read_current_line, and token_string. The next call to get() will behave as if the unget character is read again. */ - void unget() + void + unget() { next_unget = true; --position.chars_read_total; // in case we "unget" a newline, we have to also decrement the lines_read - if (position.chars_read_current_line == 0) - { - if (position.lines_read > 0) - { + if (position.chars_read_current_line == 0) { + if (position.lines_read > 0) { --position.lines_read; } - } - else - { + } else { --position.chars_read_current_line; } - if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) - { + if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) { JSON_ASSERT(!token_string.empty()); token_string.pop_back(); } } /// add a character to token_buffer - void add(char_int_type c) + void + add(char_int_type c) { token_buffer.push_back(static_cast(c)); } - public: +public: ///////////////////// // value getters ///////////////////// /// return integer value - constexpr number_integer_t get_number_integer() const noexcept + constexpr number_integer_t + get_number_integer() const noexcept { return value_integer; } /// return unsigned integer value - constexpr number_unsigned_t get_number_unsigned() const noexcept + constexpr number_unsigned_t + get_number_unsigned() const noexcept { return value_unsigned; } /// return floating-point value - constexpr number_float_t get_number_float() const noexcept + constexpr number_float_t + get_number_float() const noexcept { return value_float; } /// return current string value (implicitly resets the token; useful only once) - string_t& get_string() + string_t& + get_string() { return token_buffer; } @@ -1438,7 +1365,8 @@ class lexer : public lexer_base ///////////////////// /// return position of last read token - constexpr position_t get_position() const noexcept + constexpr position_t + get_position() const noexcept { return position; } @@ -1446,21 +1374,20 @@ class lexer : public lexer_base /// return the last read token (for errors only). Will never contain EOF /// (an arbitrary value that is not a valid char value, often -1), because /// 255 may legitimately occur. May contain NUL, which should be escaped. - std::string get_token_string() const + std::string + get_token_string() const { // escape control characters std::string result; - for (const auto c : token_string) - { - if (static_cast(c) <= '\x1F') - { + for (const auto c : token_string) { + if (static_cast(c) <= '\x1F') { // escape control characters - std::array cs{{}}; - static_cast((std::snprintf)(cs.data(), cs.size(), "", static_cast(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + std::array cs { {} }; + static_cast((std::snprintf)(cs.data(), cs.size(), "", + static_cast( + c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) result += cs.data(); - } - else - { + } else { // add character as is result.push_back(static_cast(c)); } @@ -1471,7 +1398,8 @@ class lexer : public lexer_base /// return syntax error message JSON_HEDLEY_RETURNS_NON_NULL - constexpr const char* get_error_message() const noexcept + constexpr const char* + get_error_message() const noexcept { return error_message; } @@ -1484,10 +1412,10 @@ class lexer : public lexer_base @brief skip the UTF-8 byte order mark @return true iff there is no BOM or the correct BOM has been skipped */ - bool skip_bom() + bool + skip_bom() { - if (get() == 0xEF) - { + if (get() == 0xEF) { // check if we completely parse the BOM return get() == 0xBB && get() == 0xBF; } @@ -1498,20 +1426,19 @@ class lexer : public lexer_base return true; } - void skip_whitespace() + void + skip_whitespace() { - do - { + do { get(); - } - while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); + } while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); } - token_type scan() + token_type + scan() { // initially, skip the BOM - if (position.chars_read_total == 0 && !skip_bom()) - { + if (position.chars_read_total == 0 && !skip_bom()) { error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; return token_type::parse_error; } @@ -1520,10 +1447,8 @@ class lexer : public lexer_base skip_whitespace(); // ignore comments - while (ignore_comments && current == '/') - { - if (!scan_comment()) - { + while (ignore_comments && current == '/') { + if (!scan_comment()) { return token_type::parse_error; } @@ -1531,71 +1456,74 @@ class lexer : public lexer_base skip_whitespace(); } - switch (current) - { - // structural characters - case '[': - return token_type::begin_array; - case ']': - return token_type::end_array; - case '{': - return token_type::begin_object; - case '}': - return token_type::end_object; - case ':': - return token_type::name_separator; - case ',': - return token_type::value_separator; - - // literals - case 't': - { - std::array true_literal = {{static_cast('t'), static_cast('r'), static_cast('u'), static_cast('e')}}; - return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); - } - case 'f': - { - std::array false_literal = {{static_cast('f'), static_cast('a'), static_cast('l'), static_cast('s'), static_cast('e')}}; - return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); - } - case 'n': - { - std::array null_literal = {{static_cast('n'), static_cast('u'), static_cast('l'), static_cast('l')}}; - return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); - } + switch (current) { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': { + std::array true_literal + = { { static_cast('t'), static_cast('r'), + static_cast('u'), static_cast('e') } }; + return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); + } + case 'f': { + std::array false_literal = { { static_cast('f'), + static_cast('a'), static_cast('l'), + static_cast('s'), static_cast('e') } }; + return scan_literal( + false_literal.data(), false_literal.size(), token_type::literal_false); + } + case 'n': { + std::array null_literal + = { { static_cast('n'), static_cast('u'), + static_cast('l'), static_cast('l') } }; + return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); + } - // string - case '\"': - return scan_string(); - - // number - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return scan_number(); - - // end of input (the null byte is needed when parsing from - // string literals) - case '\0': - case char_traits::eof(): - return token_type::end_of_input; - - // error - default: - error_message = "invalid literal"; - return token_type::parse_error; + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case char_traits::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; } } - private: +private: /// input adapter InputAdapterType ia; @@ -1629,5 +1557,5 @@ class lexer : public lexer_base const char_int_type decimal_point_char = '.'; }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/input/parser.hpp b/modules/commons/src/include/nlohmann/detail/input/parser.hpp index bdf85ba292..236f286fbd 100644 --- a/modules/commons/src/include/nlohmann/detail/input/parser.hpp +++ b/modules/commons/src/include/nlohmann/detail/input/parser.hpp @@ -25,8 +25,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { //////////// // parser // //////////// @@ -47,17 +46,16 @@ enum class parse_event_t : std::uint8_t value }; -template -using parser_callback_t = - std::function; +template +using parser_callback_t + = std::function; /*! @brief syntax analysis This class implements a recursive descent parser. */ -template -class parser +template class parser { using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; @@ -66,12 +64,10 @@ class parser using lexer_t = lexer; using token_type = typename lexer_t::token_type; - public: +public: /// a parser reading from an input adapter - explicit parser(InputAdapterType&& adapter, - const parser_callback_t cb = nullptr, - const bool allow_exceptions_ = true, - const bool skip_comments = false) + explicit parser(InputAdapterType&& adapter, const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true, const bool skip_comments = false) : callback(cb) , m_lexer(std::move(adapter), skip_comments) , allow_exceptions(allow_exceptions_) @@ -90,52 +86,44 @@ class parser @throw parse_error.102 if to_unicode fails or surrogate error @throw parse_error.103 if to_unicode fails */ - void parse(const bool strict, BasicJsonType& result) + void + parse(const bool strict, BasicJsonType& result) { - if (callback) - { + if (callback) { json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); sax_parse_internal(&sdp); // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"), nullptr)); + if (strict && (get_token() != token_type::end_of_input)) { + sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value - if (sdp.is_errored()) - { + if (sdp.is_errored()) { result = value_t::discarded; return; } // set top-level value to null if it was discarded by the callback // function - if (result.is_discarded()) - { + if (result.is_discarded()) { result = nullptr; } - } - else - { + } else { json_sax_dom_parser sdp(result, allow_exceptions); sax_parse_internal(&sdp); // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + if (strict && (get_token() != token_type::end_of_input)) { + sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value - if (sdp.is_errored()) - { + if (sdp.is_errored()) { result = value_t::discarded; return; } @@ -150,13 +138,14 @@ class parser @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text */ - bool accept(const bool strict = true) + bool + accept(const bool strict = true) { json_sax_acceptor sax_acceptor; return sax_parse(&sax_acceptor, strict); } - template + template JSON_HEDLEY_NON_NULL(2) bool sax_parse(SAX* sax, const bool strict = true) { @@ -164,20 +153,17 @@ class parser const bool result = sax_parse_internal(sax); // strict mode: next byte must be EOF - if (result && strict && (get_token() != token_type::end_of_input)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + if (result && strict && (get_token() != token_type::end_of_input)) { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), nullptr)); } return result; } - private: - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse_internal(SAX* sax) +private: + template JSON_HEDLEY_NON_NULL(2) bool sax_parse_internal(SAX* sax) { // stack to remember the hierarchy of structured values we are parsing // true = array; false = object @@ -185,217 +171,185 @@ class parser // value to avoid a goto (see comment where set to true) bool skip_to_state_evaluation = false; - while (true) - { - if (!skip_to_state_evaluation) - { + while (true) { + if (!skip_to_state_evaluation) { // invariant: get_token() was called before each iteration - switch (last_token) - { - case token_type::begin_object: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) - { + switch (last_token) { + case token_type::begin_object: { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { return false; } + break; + } - // closing } -> we are done - if (get_token() == token_type::end_object) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - break; - } + // parse key + if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"), + nullptr)); + } + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { + return false; + } - // parse key - if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); - } - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"), + nullptr)); + } - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); - } + // remember we are now inside an object + states.push_back(false); - // remember we are now inside an object - states.push_back(false); + // parse values + get_token(); + continue; + } - // parse values - get_token(); - continue; + case token_type::begin_array: { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) { + return false; } - case token_type::begin_array: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) - { + // closing ] -> we are done + if (get_token() == token_type::end_array) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { return false; } - - // closing ] -> we are done - if (get_token() == token_type::end_array) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - break; - } - - // remember we are now inside an array - states.push_back(true); - - // parse values (no need to call get_token) - continue; + break; } - case token_type::value_float: - { - const auto res = m_lexer.get_number_float(); + // remember we are now inside an array + states.push_back(true); - if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); - } + // parse values (no need to call get_token) + continue; + } - if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) - { - return false; - } + case token_type::value_float: { + const auto res = m_lexer.get_number_float(); - break; + if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + out_of_range::create(406, + concat( + "number overflow parsing '", m_lexer.get_token_string(), '\''), + nullptr)); } - case token_type::literal_false: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) - { - return false; - } - break; + if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) { + return false; } - case token_type::literal_null: - { - if (JSON_HEDLEY_UNLIKELY(!sax->null())) - { - return false; - } - break; - } + break; + } - case token_type::literal_true: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) - { - return false; - } - break; + case token_type::literal_false: { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) { + return false; } + break; + } - case token_type::value_integer: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) - { - return false; - } - break; + case token_type::literal_null: { + if (JSON_HEDLEY_UNLIKELY(!sax->null())) { + return false; } + break; + } - case token_type::value_string: - { - if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) - { - return false; - } - break; + case token_type::literal_true: { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) { + return false; } + break; + } - case token_type::value_unsigned: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) - { - return false; - } - break; + case token_type::value_integer: { + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) { + return false; } + break; + } - case token_type::parse_error: - { - // using "uninitialized" to avoid "expected" message - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); + case token_type::value_string: { + if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) { + return false; } - 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)); - } + break; + } - 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::value_unsigned: { + if (JSON_HEDLEY_UNLIKELY( + !sax->number_unsigned(m_lexer.get_number_unsigned()))) { + return false; } - case token_type::uninitialized: - case token_type::end_array: - case token_type::end_object: - case token_type::name_separator: - case token_type::value_separator: - case token_type::literal_or_value: - default: // the last token was unexpected - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); + break; + } + + case token_type::parse_error: { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::uninitialized, "value"), nullptr)); + } + case token_type::end_of_input: { + if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + "attempting to parse an empty input; check that your input string " + "or stream contains the expected JSON", + nullptr)); } + + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::literal_or_value, "value"), nullptr)); } - } - else - { + case token_type::uninitialized: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::literal_or_value: + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::literal_or_value, "value"), nullptr)); + } + } + } else { skip_to_state_evaluation = false; } // we reached this line after we successfully parsed a value - if (states.empty()) - { + if (states.empty()) { // empty stack: we reached the end of the hierarchy: done return true; } - if (states.back()) // array + if (states.back()) // array { // comma -> next value - if (get_token() == token_type::value_separator) - { + if (get_token() == token_type::value_separator) { // parse a new value get_token(); continue; } // closing ] - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { return false; } @@ -409,35 +363,32 @@ class parser continue; } - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_array, "array"), nullptr)); } // states.back() is false -> object // comma -> next value - if (get_token() == token_type::value_separator) - { + if (get_token() == token_type::value_separator) { // parse key - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { return false; } // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"), + nullptr)); } // parse values @@ -446,10 +397,8 @@ class parser } // closing } - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { return false; } @@ -463,48 +412,45 @@ class parser continue; } - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); + return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_object, "object"), nullptr)); } } /// get next token from lexer - token_type get_token() + token_type + get_token() { return last_token = m_lexer.scan(); } - std::string exception_message(const token_type expected, const std::string& context) + std::string + exception_message(const token_type expected, const std::string& context) { std::string error_msg = "syntax error "; - if (!context.empty()) - { + if (!context.empty()) { error_msg += concat("while parsing ", context, ' '); } error_msg += "- "; - if (last_token == token_type::parse_error) - { - error_msg += concat(m_lexer.get_error_message(), "; last read: '", - m_lexer.get_token_string(), '\''); - } - else - { + if (last_token == token_type::parse_error) { + error_msg += concat( + m_lexer.get_error_message(), "; last read: '", m_lexer.get_token_string(), '\''); + } else { error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); } - if (expected != token_type::uninitialized) - { + if (expected != token_type::uninitialized) { error_msg += concat("; expected ", lexer_t::token_type_name(expected)); } return error_msg; } - private: +private: /// callback function const parser_callback_t callback = nullptr; /// the type of the last read token @@ -515,5 +461,5 @@ class parser const bool allow_exceptions = true; }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/input/position_t.hpp b/modules/commons/src/include/nlohmann/detail/input/position_t.hpp index 8ac7c78cfd..81903047b9 100644 --- a/modules/commons/src/include/nlohmann/detail/input/position_t.hpp +++ b/modules/commons/src/include/nlohmann/detail/input/position_t.hpp @@ -13,8 +13,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /// struct to capture the start position of the current token struct position_t @@ -27,11 +26,8 @@ struct position_t std::size_t lines_read = 0; /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } + constexpr operator size_t() const { return chars_read_total; } }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/iterators/internal_iterator.hpp b/modules/commons/src/include/nlohmann/detail/iterators/internal_iterator.hpp index 2991ee6930..8a4d12c570 100644 --- a/modules/commons/src/include/nlohmann/detail/iterators/internal_iterator.hpp +++ b/modules/commons/src/include/nlohmann/detail/iterators/internal_iterator.hpp @@ -12,8 +12,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /*! @brief an iterator value @@ -21,7 +20,7 @@ namespace detail @note This structure could easily be a union, but MSVC currently does not allow unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. */ -template struct internal_iterator +template struct internal_iterator { /// iterator for JSON objects typename BasicJsonType::object_t::iterator object_iterator {}; @@ -31,5 +30,5 @@ template struct internal_iterator primitive_iterator_t primitive_iterator {}; }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/iterators/iter_impl.hpp b/modules/commons/src/include/nlohmann/detail/iterators/iter_impl.hpp index 4447091347..64a801a54f 100644 --- a/modules/commons/src/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/modules/commons/src/include/nlohmann/detail/iterators/iter_impl.hpp @@ -20,12 +20,11 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { // forward declare, to be able to friend it later on -template class iteration_proxy; -template class iteration_proxy_value; +template class iteration_proxy; +template class iteration_proxy_value; /*! @brief a template for a bidirectional iterator for the @ref basic_json class @@ -43,11 +42,12 @@ This class implements a both iterators (iterator and const_iterator) for the @since version 1.0.0, simplified in version 2.0.9, change to bidirectional iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) */ -template +template class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) { /// the iterator with BasicJsonType of different const-ness - using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + using other_iter_impl = iter_impl::value, + typename std::remove_const::type, const BasicJsonType>::type>; /// allow basic_json to access private members friend other_iter_impl; friend BasicJsonType; @@ -58,16 +58,20 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci using array_t = typename BasicJsonType::array_t; // make sure BasicJsonType is basic_json or const basic_json static_assert(is_basic_json::type>::value, - "iter_impl only accepts (const) basic_json"); + "iter_impl only accepts (const) basic_json"); // superficial check for the LegacyBidirectionalIterator named requirement - static_assert(std::is_base_of::value - && std::is_base_of::iterator_category>::value, - "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); - - public: - /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. - /// The C++ Standard has never required user-defined iterators to derive from std::iterator. - /// A user-defined iterator should provide publicly accessible typedefs named + static_assert( + std::is_base_of::value + && std::is_base_of::iterator_category>:: + value, + "basic_json iterator assumes array and object type iterators satisfy the " + "LegacyBidirectionalIterator named requirement."); + +public: + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in + /// C++17. The C++ Standard has never required user-defined iterators to derive from + /// std::iterator. A user-defined iterator should provide publicly accessible typedefs named /// iterator_category, value_type, difference_type, pointer, and reference. /// Note that value_type is required to be non-const, even for constant iterators. using iterator_category = std::bidirectional_iterator_tag; @@ -78,18 +82,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci using difference_type = typename BasicJsonType::difference_type; /// defines a pointer to the type iterated over (value_type) using pointer = typename std::conditional::value, - typename BasicJsonType::const_pointer, - typename BasicJsonType::pointer>::type; + typename BasicJsonType::const_pointer, typename BasicJsonType::pointer>::type; /// defines a reference to the type iterated over (value_type) - using reference = - typename std::conditional::value, - typename BasicJsonType::const_reference, - typename BasicJsonType::reference>::type; + using reference = typename std::conditional::value, + typename BasicJsonType::const_reference, typename BasicJsonType::reference>::type; iter_impl() = default; ~iter_impl() = default; iter_impl(iter_impl&&) noexcept = default; - iter_impl& operator=(iter_impl&&) noexcept = default; + iter_impl& + operator=(iter_impl&&) noexcept + = default; /*! @brief constructor for a given JSON instance @@ -101,33 +104,29 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - { - m_it.object_iterator = typename object_t::iterator(); - break; - } + switch (m_object->m_data.m_type) { + case value_t::object: { + m_it.object_iterator = typename object_t::iterator(); + break; + } - case value_t::array: - { - m_it.array_iterator = typename array_t::iterator(); - break; - } + case value_t::array: { + m_it.array_iterator = typename array_t::iterator(); + break; + } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } } } @@ -149,7 +148,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci */ iter_impl(const iter_impl& other) noexcept : m_object(other.m_object), m_it(other.m_it) - {} + { + } /*! @brief converting assignment @@ -157,10 +157,10 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @return const/non-const iterator @note It is not checked whether @a other is initialized. */ - iter_impl& operator=(const iter_impl& other) noexcept + iter_impl& + operator=(const iter_impl& other) noexcept { - if (&other != this) - { + if (&other != this) { m_object = other.m_object; m_it = other.m_it; } @@ -174,7 +174,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci */ iter_impl(const iter_impl::type>& other) noexcept : m_object(other.m_object), m_it(other.m_it) - {} + { + } /*! @brief converting assignment @@ -182,55 +183,53 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @return const/non-const iterator @note It is not checked whether @a other is initialized. */ - iter_impl& operator=(const iter_impl::type>& other) noexcept // NOLINT(cert-oop54-cpp) + iter_impl& + operator=(const iter_impl::type>& + other) noexcept // NOLINT(cert-oop54-cpp) { m_object = other.m_object; m_it = other.m_it; return *this; } - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief set the iterator to the first value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_begin() noexcept + JSON_PRIVATE_UNLESS_TESTED : + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void + set_begin() noexcept { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_data.m_value.object->begin(); - break; - } + switch (m_object->m_data.m_type) { + case value_t::object: { + m_it.object_iterator = m_object->m_data.m_value.object->begin(); + break; + } - case value_t::array: - { - m_it.array_iterator = m_object->m_data.m_value.array->begin(); - break; - } + case value_t::array: { + m_it.array_iterator = m_object->m_data.m_value.array->begin(); + break; + } - case value_t::null: - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } + case value_t::null: { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator.set_begin(); - break; - } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + m_it.primitive_iterator.set_begin(); + break; + } } } @@ -238,82 +237,75 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief set the iterator past the last value @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - void set_end() noexcept + void + set_end() noexcept { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_data.m_value.object->end(); - break; - } + switch (m_object->m_data.m_type) { + case value_t::object: { + m_it.object_iterator = m_object->m_data.m_value.object->end(); + break; + } - case value_t::array: - { - m_it.array_iterator = m_object->m_data.m_value.array->end(); - break; - } + case value_t::array: { + m_it.array_iterator = m_object->m_data.m_value.array->end(); + break; + } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator.set_end(); - break; - } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + m_it.primitive_iterator.set_end(); + break; + } } } - public: +public: /*! @brief return a reference to the value pointed to by the iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - reference operator*() const + reference + operator*() const { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); - return m_it.object_iterator->second; - } + switch (m_object->m_data.m_type) { + case value_t::object: { + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + return m_it.object_iterator->second; + } - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); - return *m_it.array_iterator; - } + case value_t::array: { + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); + return *m_it.array_iterator; + } - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); - - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) { + return *m_object; } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + } } } @@ -321,41 +313,37 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief dereference the iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - pointer operator->() const + pointer + operator->() const { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); - return &(m_it.object_iterator->second); - } + switch (m_object->m_data.m_type) { + case value_t::object: { + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + return &(m_it.object_iterator->second); + } - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); - return &*m_it.array_iterator; - } + case value_t::array: { + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); + return &*m_it.array_iterator; + } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) { + return m_object; } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + } } } @@ -363,7 +351,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief post-increment (it++) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) + iter_impl + operator++(int) & // NOLINT(cert-dcl21-cpp) { auto result = *this; ++(*this); @@ -374,37 +363,34 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief pre-increment (++it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator++() + iter_impl& + operator++() { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, 1); - break; - } + switch (m_object->m_data.m_type) { + case value_t::object: { + std::advance(m_it.object_iterator, 1); + break; + } - case value_t::array: - { - std::advance(m_it.array_iterator, 1); - break; - } + case value_t::array: { + std::advance(m_it.array_iterator, 1); + break; + } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - ++m_it.primitive_iterator; - break; - } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + ++m_it.primitive_iterator; + break; + } } return *this; @@ -414,7 +400,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief post-decrement (it--) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) + iter_impl + operator--(int) & // NOLINT(cert-dcl21-cpp) { auto result = *this; --(*this); @@ -425,37 +412,34 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief pre-decrement (--it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator--() + iter_impl& + operator--() { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, -1); - break; - } + switch (m_object->m_data.m_type) { + case value_t::object: { + std::advance(m_it.object_iterator, -1); + break; + } - case value_t::array: - { - std::advance(m_it.array_iterator, -1); - break; - } + case value_t::array: { + std::advance(m_it.array_iterator, -1); + break; + } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - --m_it.primitive_iterator; - break; - } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + --m_it.primitive_iterator; + break; + } } return *this; @@ -465,35 +449,39 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief comparison: equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > - bool operator==(const IterImpl& other) const + template ::value + || std::is_same::value), + std::nullptr_t> + = nullptr> + bool + operator==(const IterImpl& other) const { // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { + JSON_THROW(invalid_iterator::create( + 212, "cannot compare iterators of different containers", m_object)); } JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - return (m_it.object_iterator == other.m_it.object_iterator); - - case value_t::array: - return (m_it.array_iterator == other.m_it.array_iterator); - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return (m_it.primitive_iterator == other.m_it.primitive_iterator); + switch (m_object->m_data.m_type) { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); } } @@ -501,8 +489,13 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief comparison: not equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > - bool operator!=(const IterImpl& other) const + template ::value + || std::is_same::value), + std::nullptr_t> + = nullptr> + bool + operator!=(const IterImpl& other) const { return !operator==(other); } @@ -511,34 +504,35 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief comparison: smaller @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<(const iter_impl& other) const + bool + operator<(const iter_impl& other) const { // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { + JSON_THROW(invalid_iterator::create( + 212, "cannot compare iterators of different containers", m_object)); } JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); - - case value_t::array: - return (m_it.array_iterator < other.m_it.array_iterator); - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return (m_it.primitive_iterator < other.m_it.primitive_iterator); + switch (m_object->m_data.m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create( + 213, "cannot compare order of object iterators", m_object)); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); } } @@ -546,16 +540,18 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief comparison: less than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<=(const iter_impl& other) const + bool + operator<=(const iter_impl& other) const { - return !other.operator < (*this); + return !other.operator<(*this); } /*! @brief comparison: greater than @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>(const iter_impl& other) const + bool + operator>(const iter_impl& other) const { return !operator<=(other); } @@ -564,7 +560,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief comparison: greater than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>=(const iter_impl& other) const + bool + operator>=(const iter_impl& other) const { return !operator<(other); } @@ -573,34 +570,33 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator+=(difference_type i) + iter_impl& + operator+=(difference_type i) { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); + switch (m_object->m_data.m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create( + 209, "cannot use offsets with object iterators", m_object)); - case value_t::array: - { - std::advance(m_it.array_iterator, i); - break; - } + case value_t::array: { + std::advance(m_it.array_iterator, i); + break; + } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - m_it.primitive_iterator += i; - break; - } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + m_it.primitive_iterator += i; + break; + } } return *this; @@ -610,7 +606,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator-=(difference_type i) + iter_impl& + operator-=(difference_type i) { return operator+=(-i); } @@ -619,7 +616,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl operator+(difference_type i) const + iter_impl + operator+(difference_type i) const { auto result = *this; result += i; @@ -630,7 +628,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief addition of distance and iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - friend iter_impl operator+(difference_type i, const iter_impl& it) + friend iter_impl + operator+(difference_type i, const iter_impl& it) { auto result = it; result += i; @@ -641,7 +640,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl operator-(difference_type i) const + iter_impl + operator-(difference_type i) const { auto result = *this; result -= i; @@ -652,28 +652,29 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief return difference @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - difference_type operator-(const iter_impl& other) const + difference_type + operator-(const iter_impl& other) const { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); - - case value_t::array: - return m_it.array_iterator - other.m_it.array_iterator; - - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return m_it.primitive_iterator - other.m_it.primitive_iterator; + switch (m_object->m_data.m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create( + 209, "cannot use offsets with object iterators", m_object)); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; } } @@ -681,37 +682,36 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief access to successor @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - reference operator[](difference_type n) const + reference + operator[](difference_type n) const { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); - - case value_t::array: - return *std::next(m_it.array_iterator, n); - - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); - - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + switch (m_object->m_data.m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create( + 208, "cannot use operator[] for object iterators", m_object)); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) { + return *m_object; } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + } } } @@ -719,33 +719,36 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief return the key of an object iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const typename object_t::key_type& key() const + const typename object_t::key_type& + key() const { JSON_ASSERT(m_object != nullptr); - if (JSON_HEDLEY_LIKELY(m_object->is_object())) - { + if (JSON_HEDLEY_LIKELY(m_object->is_object())) { return m_it.object_iterator->first; } - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); + JSON_THROW( + invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); } /*! @brief return the value of an iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - reference value() const + reference + value() const { return operator*(); } - JSON_PRIVATE_UNLESS_TESTED: - /// associated JSON instance - pointer m_object = nullptr; + JSON_PRIVATE_UNLESS_TESTED : + /// associated JSON instance + pointer m_object + = nullptr; /// the actual iterator of the associated instance internal_iterator::type> m_it {}; }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/iterators/iteration_proxy.hpp b/modules/commons/src/include/nlohmann/detail/iterators/iteration_proxy.hpp index 76293de227..4ce446c6b1 100644 --- a/modules/commons/src/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/modules/commons/src/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -15,7 +15,7 @@ #include // move #if JSON_HAS_RANGES - #include // enable_borrowed_range +#include // enable_borrowed_range #endif #include @@ -23,29 +23,30 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { -template -void int_to_string( string_type& target, std::size_t value ) +template +void +int_to_string(string_type& target, std::size_t value) { // For ADL using std::to_string; target = to_string(value); } -template class iteration_proxy_value +template class iteration_proxy_value { - public: +public: using difference_type = std::ptrdiff_t; using value_type = iteration_proxy_value; - using pointer = value_type *; - using reference = value_type &; + using pointer = value_type*; + using reference = value_type&; using iterator_category = std::input_iterator_tag; - using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; + using string_type = typename std::remove_cv< + typename std::remove_reference().key())>::type>::type; - private: +private: /// the iterator - IteratorType anchor{}; + IteratorType anchor {}; /// an index for arrays (used to create key names) std::size_t array_index = 0; /// last stringified array index @@ -53,36 +54,43 @@ template class iteration_proxy_value /// a string representation of the array index mutable string_type array_index_str = "0"; /// an empty string (to return a reference for primitive values) - string_type empty_str{}; + string_type empty_str {}; - public: +public: explicit iteration_proxy_value() = default; - explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) - noexcept(std::is_nothrow_move_constructible::value - && std::is_nothrow_default_constructible::value) - : anchor(std::move(it)) - , array_index(array_index_) - {} + explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) noexcept( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_default_constructible::value) + : anchor(std::move(it)), array_index(array_index_) + { + } iteration_proxy_value(iteration_proxy_value const&) = default; - iteration_proxy_value& operator=(iteration_proxy_value const&) = default; + iteration_proxy_value& + operator=(iteration_proxy_value const&) + = default; // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions - iteration_proxy_value(iteration_proxy_value&&) - noexcept(std::is_nothrow_move_constructible::value - && std::is_nothrow_move_constructible::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) - iteration_proxy_value& operator=(iteration_proxy_value&&) - noexcept(std::is_nothrow_move_assignable::value - && std::is_nothrow_move_assignable::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) + 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) + 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) ~iteration_proxy_value() = default; /// dereference operator (needed for range-based for) - const iteration_proxy_value& operator*() const + const iteration_proxy_value& + operator*() const { return *this; } /// increment operator (needed for range-based for) - iteration_proxy_value& operator++() + iteration_proxy_value& + operator++() { ++anchor; ++array_index; @@ -90,7 +98,8 @@ template class iteration_proxy_value return *this; } - iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) + iteration_proxy_value + operator++(int) & // NOLINT(cert-dcl21-cpp) { auto tmp = iteration_proxy_value(anchor, array_index); ++anchor; @@ -99,88 +108,94 @@ template class iteration_proxy_value } /// equality operator (needed for InputIterator) - bool operator==(const iteration_proxy_value& o) const + bool + operator==(const iteration_proxy_value& o) const { return anchor == o.anchor; } /// inequality operator (needed for range-based for) - bool operator!=(const iteration_proxy_value& o) const + bool + operator!=(const iteration_proxy_value& o) const { return anchor != o.anchor; } /// return key of the iterator - const string_type& key() const + const string_type& + key() const { JSON_ASSERT(anchor.m_object != nullptr); - switch (anchor.m_object->type()) - { - // use integer array index as key - case value_t::array: - { - if (array_index != array_index_last) - { - int_to_string( array_index_str, array_index ); - array_index_last = array_index; - } - return array_index_str; + switch (anchor.m_object->type()) { + // use integer array index as key + case value_t::array: { + if (array_index != array_index_last) { + int_to_string(array_index_str, array_index); + array_index_last = array_index; } + return array_index_str; + } - // use key from the object - case value_t::object: - return anchor.key(); - - // use an empty key for all primitive types - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: - default: - return empty_str; + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return empty_str; } } /// return value of the iterator - typename IteratorType::reference value() const + typename IteratorType::reference + value() const { return anchor.value(); } }; /// proxy class for the items() function -template class iteration_proxy +template class iteration_proxy { - private: +private: /// the container to iterate typename IteratorType::pointer container = nullptr; - public: +public: explicit iteration_proxy() = default; /// construct iteration proxy from a container - explicit iteration_proxy(typename IteratorType::reference cont) noexcept - : container(&cont) {} + explicit iteration_proxy(typename IteratorType::reference cont) noexcept : container(&cont) { } iteration_proxy(iteration_proxy const&) = default; - iteration_proxy& operator=(iteration_proxy const&) = default; + iteration_proxy& + operator=(iteration_proxy const&) + = default; iteration_proxy(iteration_proxy&&) noexcept = default; - iteration_proxy& operator=(iteration_proxy&&) noexcept = default; + iteration_proxy& + operator=(iteration_proxy&&) noexcept + = default; ~iteration_proxy() = default; /// return iterator begin (needed for range-based for) - iteration_proxy_value begin() const noexcept + iteration_proxy_value + begin() const noexcept { return iteration_proxy_value(container->begin()); } /// return iterator end (needed for range-based for) - iteration_proxy_value end() const noexcept + iteration_proxy_value + end() const noexcept { return iteration_proxy_value(container->end()); } @@ -189,54 +204,58 @@ template class iteration_proxy // Structured Bindings Support // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) +template = 0> +auto +get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) { return i.key(); } // Structured Bindings Support // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) +template = 0> +auto +get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) { return i.value(); } -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END // The Addition to the STD Namespace is required to add // Structured Bindings Support to the iteration_proxy_value class // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 -namespace std -{ +namespace std { #if defined(__clang__) - // Fix: https://github.com/nlohmann/json/issues/1401 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wmismatched-tags" +// Fix: https://github.com/nlohmann/json/issues/1401 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmismatched-tags" #endif -template +template class tuple_size<::nlohmann::detail::iteration_proxy_value> // NOLINT(cert-dcl58-cpp) - : public std::integral_constant {}; + : public std::integral_constant +{ }; -template -class tuple_element> // NOLINT(cert-dcl58-cpp) +template +class tuple_element> // NOLINT(cert-dcl58-cpp) { - public: - using type = decltype( - get(std::declval < - ::nlohmann::detail::iteration_proxy_value> ())); +public: + using type + = decltype(get(std::declval<::nlohmann::detail::iteration_proxy_value>())); }; #if defined(__clang__) - #pragma clang diagnostic pop +#pragma clang diagnostic pop #endif -} // namespace std +} // namespace std #if JSON_HAS_RANGES - template - inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy> = true; +template +inline constexpr bool ::std::ranges::enable_borrowed_range< + ::nlohmann::detail::iteration_proxy> + = true; #endif diff --git a/modules/commons/src/include/nlohmann/detail/iterators/iterator_traits.hpp b/modules/commons/src/include/nlohmann/detail/iterators/iterator_traits.hpp index 84cc27a85e..d4dfb5aa9b 100644 --- a/modules/commons/src/include/nlohmann/detail/iterators/iterator_traits.hpp +++ b/modules/commons/src/include/nlohmann/detail/iterators/iterator_traits.hpp @@ -15,17 +15,15 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { -template -struct iterator_types {}; +template struct iterator_types +{ }; -template -struct iterator_types < - It, +template +struct iterator_types> + typename It::reference, typename It::iterator_category>> { using difference_type = typename It::difference_type; using value_type = typename It::value_type; @@ -36,19 +34,14 @@ struct iterator_types < // This is required as some compilers implement std::iterator_traits in a way that // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; +template struct iterator_traits +{ }; -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; +template +struct iterator_traits::value>> : iterator_types +{ }; -template -struct iterator_traits::value>> +template struct iterator_traits::value>> { using iterator_category = std::random_access_iterator_tag; using value_type = T; @@ -57,5 +50,5 @@ struct iterator_traits::value>> using reference = T&; }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/iterators/json_reverse_iterator.hpp b/modules/commons/src/include/nlohmann/detail/iterators/json_reverse_iterator.hpp index 006d5499ad..9e571f64a8 100644 --- a/modules/commons/src/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +++ b/modules/commons/src/include/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -15,8 +15,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { ////////////////////// // reverse_iterator // @@ -40,10 +39,9 @@ create @ref const_reverse_iterator). @since version 1.0.0 */ -template -class json_reverse_iterator : public std::reverse_iterator +template class json_reverse_iterator : public std::reverse_iterator { - public: +public: using difference_type = std::ptrdiff_t; /// shortcut to the reverse iterator adapter using base_iterator = std::reverse_iterator; @@ -52,79 +50,92 @@ class json_reverse_iterator : public std::reverse_iterator /// create reverse iterator from iterator explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept - : base_iterator(it) {} + : base_iterator(it) + { + } /// create reverse iterator from base class - explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) { } /// post-increment (it++) - json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) + json_reverse_iterator + operator++(int) & // NOLINT(cert-dcl21-cpp) { return static_cast(base_iterator::operator++(1)); } /// pre-increment (++it) - json_reverse_iterator& operator++() + json_reverse_iterator& + operator++() { return static_cast(base_iterator::operator++()); } /// post-decrement (it--) - json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) + json_reverse_iterator + operator--(int) & // NOLINT(cert-dcl21-cpp) { return static_cast(base_iterator::operator--(1)); } /// pre-decrement (--it) - json_reverse_iterator& operator--() + json_reverse_iterator& + operator--() { return static_cast(base_iterator::operator--()); } /// add to iterator - json_reverse_iterator& operator+=(difference_type i) + json_reverse_iterator& + operator+=(difference_type i) { return static_cast(base_iterator::operator+=(i)); } /// add to iterator - json_reverse_iterator operator+(difference_type i) const + json_reverse_iterator + operator+(difference_type i) const { return static_cast(base_iterator::operator+(i)); } /// subtract from iterator - json_reverse_iterator operator-(difference_type i) const + json_reverse_iterator + operator-(difference_type i) const { return static_cast(base_iterator::operator-(i)); } /// return difference - difference_type operator-(const json_reverse_iterator& other) const + difference_type + operator-(const json_reverse_iterator& other) const { return base_iterator(*this) - base_iterator(other); } /// access to successor - reference operator[](difference_type n) const + reference + operator[](difference_type n) const { return *(this->operator+(n)); } /// return the key of an object iterator - auto key() const -> decltype(std::declval().key()) + auto + key() const -> decltype(std::declval().key()) { auto it = --this->base(); return it.key(); } /// return the value of an iterator - reference value() const + reference + value() const { auto it = --this->base(); - return it.operator * (); + return it.operator*(); } }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/iterators/primitive_iterator.hpp b/modules/commons/src/include/nlohmann/detail/iterators/primitive_iterator.hpp index 0b6e8499e6..4612f449c7 100644 --- a/modules/commons/src/include/nlohmann/detail/iterators/primitive_iterator.hpp +++ b/modules/commons/src/include/nlohmann/detail/iterators/primitive_iterator.hpp @@ -9,13 +9,12 @@ #pragma once #include // ptrdiff_t -#include // numeric_limits +#include // numeric_limits #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /* @brief an iterator for primitive JSON types @@ -28,105 +27,121 @@ end_value (`1`) models past the end. */ class primitive_iterator_t { - private: +private: using difference_type = std::ptrdiff_t; static constexpr difference_type begin_value = 0; static constexpr difference_type end_value = begin_value + 1; - JSON_PRIVATE_UNLESS_TESTED: - /// iterator as signed integer type - difference_type m_it = (std::numeric_limits::min)(); + JSON_PRIVATE_UNLESS_TESTED : + /// iterator as signed integer type + difference_type m_it + = (std::numeric_limits::min)(); - public: - constexpr difference_type get_value() const noexcept +public: + constexpr difference_type + get_value() const noexcept { return m_it; } /// set iterator to a defined beginning - void set_begin() noexcept + void + set_begin() noexcept { m_it = begin_value; } /// set iterator to a defined past the end - void set_end() noexcept + void + set_end() noexcept { m_it = end_value; } /// return whether the iterator can be dereferenced - constexpr bool is_begin() const noexcept + constexpr bool + is_begin() const noexcept { return m_it == begin_value; } /// return whether the iterator is at end - constexpr bool is_end() const noexcept + constexpr bool + is_end() const noexcept { return m_it == end_value; } - friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + friend constexpr bool + operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it == rhs.m_it; } - friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + friend constexpr bool + operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it < rhs.m_it; } - primitive_iterator_t operator+(difference_type n) noexcept + primitive_iterator_t + operator+(difference_type n) noexcept { auto result = *this; result += n; return result; } - friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + friend constexpr difference_type + operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it - rhs.m_it; } - primitive_iterator_t& operator++() noexcept + primitive_iterator_t& + operator++() noexcept { ++m_it; return *this; } - primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) + primitive_iterator_t + operator++(int) & noexcept // NOLINT(cert-dcl21-cpp) { auto result = *this; ++m_it; return result; } - primitive_iterator_t& operator--() noexcept + primitive_iterator_t& + operator--() noexcept { --m_it; return *this; } - primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) + primitive_iterator_t + operator--(int) & noexcept // NOLINT(cert-dcl21-cpp) { auto result = *this; --m_it; return result; } - primitive_iterator_t& operator+=(difference_type n) noexcept + primitive_iterator_t& + operator+=(difference_type n) noexcept { m_it += n; return *this; } - primitive_iterator_t& operator-=(difference_type n) noexcept + primitive_iterator_t& + operator-=(difference_type n) noexcept { m_it -= n; return *this; } }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/json_custom_base_class.hpp b/modules/commons/src/include/nlohmann/detail/json_custom_base_class.hpp index d1e29162a3..2edf9ad473 100644 --- a/modules/commons/src/include/nlohmann/detail/json_custom_base_class.hpp +++ b/modules/commons/src/include/nlohmann/detail/json_custom_base_class.hpp @@ -13,8 +13,7 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { /*! @brief Default base class of the @ref basic_json class. @@ -26,14 +25,12 @@ of @ref basic_json do not require complex case distinctions 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 {}; +struct json_default_base +{ }; -template -using json_base_class = typename std::conditional < - std::is_same::value, - json_default_base, - T - >::type; +template +using json_base_class = + typename std::conditional::value, json_default_base, T>::type; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/json_pointer.hpp b/modules/commons/src/include/nlohmann/detail/json_pointer.hpp index 4fdcd9ad28..110df55733 100644 --- a/modules/commons/src/include/nlohmann/detail/json_pointer.hpp +++ b/modules/commons/src/include/nlohmann/detail/json_pointer.hpp @@ -13,8 +13,8 @@ #include // errno, ERANGE #include // strtoull #ifndef JSON_NO_IO - #include // ostream -#endif // JSON_NO_IO +#include // ostream +#endif // JSON_NO_IO #include // max #include // accumulate #include // string @@ -29,20 +29,18 @@ NLOHMANN_JSON_NAMESPACE_BEGIN -/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document +/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON +/// document /// @sa https://json.nlohmann.me/api/json_pointer/ -template -class json_pointer +template class json_pointer { // allow basic_json to access private members NLOHMANN_BASIC_JSON_TPL_DECLARATION friend class basic_json; - template - friend class json_pointer; + template friend class json_pointer; - template - struct string_t_helper + template struct string_t_helper { using type = T; }; @@ -53,40 +51,35 @@ class json_pointer using type = StringType; }; - public: +public: // for backwards compatibility accept BasicJsonType using string_t = typename string_t_helper::type; /// @brief create JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ - explicit json_pointer(const string_t& s = "") - : reference_tokens(split(s)) - {} + explicit json_pointer(const string_t& s = "") : reference_tokens(split(s)) { } /// @brief return a string representation of the JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ - string_t to_string() const + string_t + to_string() const { - return std::accumulate(reference_tokens.begin(), reference_tokens.end(), - string_t{}, - [](const string_t& a, const string_t& b) - { - return detail::concat(a, '/', detail::escape(b)); - }); + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), string_t {}, + [](const string_t& a, const string_t& b) { + return detail::concat(a, '/', detail::escape(b)); + }); } /// @brief return a string representation of the JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) - operator string_t() const - { - return to_string(); - } + operator string_t() const { return to_string(); } #ifndef JSON_NO_IO /// @brief write string representation of the JSON pointer to stream /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ - friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) + friend std::ostream& + operator<<(std::ostream& o, const json_pointer& ptr) { o << ptr.to_string(); return o; @@ -95,17 +88,18 @@ class json_pointer /// @brief append another JSON pointer at the end of this JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ - json_pointer& operator/=(const json_pointer& ptr) + json_pointer& + operator/=(const json_pointer& ptr) { - reference_tokens.insert(reference_tokens.end(), - ptr.reference_tokens.begin(), - ptr.reference_tokens.end()); + reference_tokens.insert( + reference_tokens.end(), ptr.reference_tokens.begin(), ptr.reference_tokens.end()); return *this; } /// @brief append an unescaped reference token at the end of this JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ - json_pointer& operator/=(string_t token) + json_pointer& + operator/=(string_t token) { push_back(std::move(token)); return *this; @@ -113,39 +107,46 @@ class json_pointer /// @brief append an array index at the end of this JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ - json_pointer& operator/=(std::size_t array_idx) + json_pointer& + operator/=(std::size_t array_idx) { return *this /= std::to_string(array_idx); } - /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer + /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left + /// JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ - friend json_pointer operator/(const json_pointer& lhs, - const json_pointer& rhs) + friend json_pointer + operator/(const json_pointer& lhs, const json_pointer& rhs) { return json_pointer(lhs) /= rhs; } - /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer + /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON + /// pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ - friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) + friend json_pointer + operator/( + const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) { return json_pointer(lhs) /= std::move(token); } - /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer + /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON + /// pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ - friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) + friend json_pointer + operator/(const json_pointer& lhs, std::size_t array_idx) { return json_pointer(lhs) /= array_idx; } /// @brief returns the parent of this JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ - json_pointer parent_pointer() const + json_pointer + parent_pointer() const { - if (empty()) - { + if (empty()) { return *this; } @@ -156,10 +157,10 @@ class json_pointer /// @brief remove last reference token /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ - void pop_back() + void + pop_back() { - if (JSON_HEDLEY_UNLIKELY(empty())) - { + if (JSON_HEDLEY_UNLIKELY(empty())) { JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); } @@ -168,10 +169,10 @@ class json_pointer /// @brief return last reference token /// @sa https://json.nlohmann.me/api/json_pointer/back/ - const string_t& back() const + const string_t& + back() const { - if (JSON_HEDLEY_UNLIKELY(empty())) - { + if (JSON_HEDLEY_UNLIKELY(empty())) { JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); } @@ -180,26 +181,29 @@ class json_pointer /// @brief append an unescaped token at the end of the reference pointer /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ - void push_back(const string_t& token) + void + push_back(const string_t& token) { reference_tokens.push_back(token); } /// @brief append an unescaped token at the end of the reference pointer /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ - void push_back(string_t&& token) + void + push_back(string_t&& token) { reference_tokens.push_back(std::move(token)); } /// @brief return whether pointer points to the root document /// @sa https://json.nlohmann.me/api/json_pointer/empty/ - bool empty() const noexcept + bool + empty() const noexcept { return reference_tokens.empty(); } - private: +private: /*! @param[in] s reference token to be converted into an array index @@ -210,21 +214,22 @@ class json_pointer @throw out_of_range.404 if string @a s could not be converted to an integer @throw out_of_range.410 if an array index exceeds size_type */ - template - static typename BasicJsonType::size_type array_index(const string_t& s) + template + static typename BasicJsonType::size_type + array_index(const string_t& s) { using size_type = typename BasicJsonType::size_type; // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) - { - JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) { + JSON_THROW(detail::parse_error::create( + 106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); } // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) - { - JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) { + JSON_THROW(detail::parse_error::create( + 109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); } const char* p = s.c_str(); @@ -232,36 +237,40 @@ class json_pointer errno = 0; // strtoull doesn't reset errno const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) if (p == p_end // invalid input or empty string - || errno == ERANGE // out of range - || JSON_HEDLEY_UNLIKELY(static_cast(p_end - p) != s.size())) // incomplete read + || errno == ERANGE // out of range + || JSON_HEDLEY_UNLIKELY( + static_cast(p_end - p) != s.size())) // incomplete read { - JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); + JSON_THROW(detail::out_of_range::create( + 404, detail::concat("unresolved reference token '", s, "'"), nullptr)); } // only triggered on special platforms (like 32bit), see also // https://github.com/nlohmann/json/pull/2203 - if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) + if (res >= static_cast( + (std::numeric_limits::max)())) // NOLINT(runtime/int) { - JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE + JSON_THROW(detail::out_of_range::create(410, + detail::concat("array index ", s, " exceeds size_type"), + nullptr)); // LCOV_EXCL_LINE } return static_cast(res); } - JSON_PRIVATE_UNLESS_TESTED: - json_pointer top() const + JSON_PRIVATE_UNLESS_TESTED : json_pointer + top() const { - if (JSON_HEDLEY_UNLIKELY(empty())) - { + if (JSON_HEDLEY_UNLIKELY(empty())) { JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); } json_pointer result = *this; - result.reference_tokens = {reference_tokens[0]}; + result.reference_tokens = { reference_tokens[0] }; return result; } - private: +private: /*! @brief create and return a reference to the pointed to value @@ -270,61 +279,54 @@ class json_pointer @throw parse_error.109 if array index is not a number @throw type_error.313 if value cannot be unflattened */ - template - BasicJsonType& get_and_create(BasicJsonType& j) const + template + BasicJsonType& + get_and_create(BasicJsonType& j) const { auto* result = &j; // in case no reference tokens exist, return a reference to the JSON value // j which will be overwritten by a primitive value - for (const auto& reference_token : reference_tokens) - { - switch (result->type()) - { - case detail::value_t::null: - { - if (reference_token == "0") - { - // start a new array if reference token is 0 - result = &result->operator[](0); - } - else - { - // start a new object otherwise - result = &result->operator[](reference_token); - } - break; - } - - case detail::value_t::object: - { - // create an entry in the object + for (const auto& reference_token : reference_tokens) { + switch (result->type()) { + case detail::value_t::null: { + if (reference_token == "0") { + // start a new array if reference token is 0 + result = &result->operator[](0); + } else { + // start a new object otherwise result = &result->operator[](reference_token); - break; } + break; + } - case detail::value_t::array: - { - // create an entry in the array - result = &result->operator[](array_index(reference_token)); - break; - } + case detail::value_t::object: { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: { + // create an entry in the array + result = &result->operator[](array_index(reference_token)); + break; + } - /* - The following code is only reached if there exists a reference - token _and_ the current value is primitive. In this case, we have - an error situation, because primitive values may only occur as - single value; that is, with an empty list of reference tokens. - */ - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); } } @@ -350,62 +352,51 @@ class json_pointer @throw parse_error.109 if an array index was not a number @throw out_of_range.404 if the JSON pointer can not be resolved */ - template - BasicJsonType& get_unchecked(BasicJsonType* ptr) const + template + BasicJsonType& + get_unchecked(BasicJsonType* ptr) const { - for (const auto& reference_token : reference_tokens) - { + for (const auto& reference_token : reference_tokens) { // convert null values to arrays or objects before continuing - if (ptr->is_null()) - { + if (ptr->is_null()) { // check if reference token is a number - const bool nums = - std::all_of(reference_token.begin(), reference_token.end(), - [](const unsigned char x) - { - return std::isdigit(x); - }); + const bool nums = std::all_of(reference_token.begin(), reference_token.end(), + [](const unsigned char x) { return std::isdigit(x); }); // change value to array for numbers or "-" or to object otherwise - *ptr = (nums || reference_token == "-") - ? detail::value_t::array - : detail::value_t::object; + *ptr = (nums || reference_token == "-") ? detail::value_t::array + : detail::value_t::object; } - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } + switch (ptr->type()) { + case detail::value_t::object: { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } - case detail::value_t::array: - { - if (reference_token == "-") - { - // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); - } - else - { - // convert array index to number; unchecked access - ptr = &ptr->operator[](array_index(reference_token)); - } - break; + case detail::value_t::array: { + if (reference_token == "-") { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); + } else { + // convert array index to number; unchecked access + ptr = &ptr->operator[](array_index(reference_token)); } + break; + } - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, + detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -418,45 +409,43 @@ class json_pointer @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ - template - BasicJsonType& get_checked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), - ") is out of range"), ptr)); - } + template + BasicJsonType& + get_checked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + detail::concat("array index '-' (", + std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), + ptr)); } - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, + detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -476,43 +465,43 @@ class json_pointer @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ - template - const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); - } + template + const BasicJsonType& + get_unchecked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } - // use unchecked array access - ptr = &ptr->operator[](array_index(reference_token)); - break; + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, + detail::concat("array index '-' (", + std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), + ptr)); } - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + // use unchecked array access + ptr = &ptr->operator[](array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, + detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -525,45 +514,43 @@ class json_pointer @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ - template - const BasicJsonType& get_checked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), - ") is out of range"), ptr)); - } + template + const BasicJsonType& + get_checked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + detail::concat("array index '-' (", + std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), + ptr)); } - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, + detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -574,79 +561,70 @@ class json_pointer @throw parse_error.106 if an array index begins with '0' @throw parse_error.109 if an array index was not a number */ - template - bool contains(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - if (!ptr->contains(reference_token)) - { - // we did not find the key in the object - return false; - } - - ptr = &ptr->operator[](reference_token); - break; + template + bool + contains(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + if (!ptr->contains(reference_token)) { + // we did not find the key in the object + return false; } - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) - { - // invalid char + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" always fails the range check + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 + && !("0" <= reference_token && reference_token <= "9"))) { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) { + if (JSON_HEDLEY_UNLIKELY( + !('1' <= reference_token[0] && reference_token[0] <= '9'))) { + // first char should be between '1' and '9' return false; } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) - { - if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) - { - // first char should be between '1' and '9' + for (std::size_t i = 1; i < reference_token.size(); i++) { + if (JSON_HEDLEY_UNLIKELY( + !('0' <= reference_token[i] && reference_token[i] <= '9'))) { + // other char should be between '0' and '9' return false; } - for (std::size_t i = 1; i < reference_token.size(); i++) - { - if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) - { - // other char should be between '0' and '9' - return false; - } - } - } - - const auto idx = array_index(reference_token); - if (idx >= ptr->size()) - { - // index out of range - return false; } - - ptr = &ptr->operator[](idx); - break; } - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - { - // we do not expect primitive values if there is still a - // reference token to process + const auto idx = array_index(reference_token); + if (idx >= ptr->size()) { + // index out of range return false; } + + ptr = &ptr->operator[](idx); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: { + // we do not expect primitive values if there is still a + // reference token to process + return false; + } } } @@ -663,20 +641,22 @@ class json_pointer @throw parse_error.107 if the pointer is not empty or begins with '/' @throw parse_error.108 if character '~' is not followed by '0' or '1' */ - static std::vector split(const string_t& reference_string) + static std::vector + split(const string_t& reference_string) { std::vector result; // special case: empty reference string -> no reference tokens - if (reference_string.empty()) - { + if (reference_string.empty()) { return result; } // check if nonempty reference string begins with slash - if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) - { - JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); + if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) { + JSON_THROW(detail::parse_error::create(107, 1, + detail::concat( + "JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), + nullptr)); } // extract the reference tokens: @@ -685,33 +665,29 @@ class json_pointer for ( // search for the first slash after the first character std::size_t slash = reference_string.find_first_of('/', 1), - // set the beginning of the first reference token + // set the beginning of the first reference token start = 1; // we can stop if start == 0 (if slash == string_t::npos) start != 0; // set the beginning of the next reference token // (will eventually be 0 if slash == string_t::npos) start = (slash == string_t::npos) ? 0 : slash + 1, - // find next slash - slash = reference_string.find_first_of('/', start)) - { + // find next slash + slash = reference_string.find_first_of('/', start)) { // use the text between the beginning of the reference token // (start) and the last slash (slash). auto reference_token = reference_string.substr(start, slash - start); // check reference tokens are properly escaped - for (std::size_t pos = reference_token.find_first_of('~'); - pos != string_t::npos; - pos = reference_token.find_first_of('~', pos + 1)) - { + for (std::size_t pos = reference_token.find_first_of('~'); pos != string_t::npos; + pos = reference_token.find_first_of('~', pos + 1)) { JSON_ASSERT(reference_token[pos] == '~'); // ~ must be followed by 0 or 1 - if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || - (reference_token[pos + 1] != '0' && - reference_token[pos + 1] != '1'))) - { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); + if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 + || (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1'))) { + JSON_THROW(detail::parse_error::create( + 108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); } } @@ -723,7 +699,7 @@ class json_pointer return result; } - private: +private: /*! @param[in] reference_string the reference string to the current value @param[in] value the value to consider @@ -731,64 +707,52 @@ class json_pointer @note Empty objects or arrays are flattened to `null`. */ - template - static void flatten(const string_t& reference_string, - const BasicJsonType& value, - BasicJsonType& result) - { - switch (value.type()) - { - case detail::value_t::array: - { - if (value.m_data.m_value.array->empty()) - { - // flatten empty array as null - result[reference_string] = nullptr; - } - else - { - // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) - { - flatten(detail::concat(reference_string, '/', std::to_string(i)), - value.m_data.m_value.array->operator[](i), result); - } + template + static void + flatten(const string_t& reference_string, const BasicJsonType& value, BasicJsonType& result) + { + switch (value.type()) { + case detail::value_t::array: { + if (value.m_data.m_value.array->empty()) { + // flatten empty array as null + result[reference_string] = nullptr; + } else { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) { + flatten(detail::concat(reference_string, '/', std::to_string(i)), + value.m_data.m_value.array->operator[](i), result); } - break; } + break; + } - case detail::value_t::object: - { - if (value.m_data.m_value.object->empty()) - { - // flatten empty object as null - result[reference_string] = nullptr; + case detail::value_t::object: { + if (value.m_data.m_value.object->empty()) { + // flatten empty object as null + result[reference_string] = nullptr; + } else { + // iterate object and use keys as reference string + for (const auto& element : *value.m_data.m_value.object) { + flatten(detail::concat(reference_string, '/', detail::escape(element.first)), + element.second, result); } - else - { - // iterate object and use keys as reference string - for (const auto& element : *value.m_data.m_value.object) - { - flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); - } - } - break; } + break; + } - case detail::value_t::null: - case detail::value_t::string: - case detail::value_t::boolean: - case detail::value_t::number_integer: - case detail::value_t::number_unsigned: - case detail::value_t::number_float: - case detail::value_t::binary: - case detail::value_t::discarded: - default: - { - // add primitive value with its reference string - result[reference_string] = value; - break; - } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: { + // add primitive value with its reference string + result[reference_string] = value; + break; + } } } @@ -802,23 +766,21 @@ class json_pointer @throw type_error.315 if object values are not primitive @throw type_error.313 if value cannot be unflattened */ - template + template static BasicJsonType unflatten(const BasicJsonType& value) { - if (JSON_HEDLEY_UNLIKELY(!value.is_object())) - { + if (JSON_HEDLEY_UNLIKELY(!value.is_object())) { JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); } BasicJsonType result; // iterate the JSON object values - for (const auto& element : *value.m_data.m_value.object) - { - if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) - { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); + for (const auto& element : *value.m_data.m_value.object) { + if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { + JSON_THROW(detail::type_error::create( + 315, "values in object must be primitive", &element.second)); } // assign value to reference pointed to by JSON pointer; Note that if @@ -832,154 +794,170 @@ class json_pointer } // can't use conversion operator because of ambiguity - json_pointer convert() const& + json_pointer + convert() const& { json_pointer result; result.reference_tokens = reference_tokens; return result; } - json_pointer convert()&& + json_pointer + convert() && { json_pointer result; result.reference_tokens = std::move(reference_tokens); return result; } - public: +public: #if JSON_HAS_THREE_WAY_COMPARISON /// @brief compares two JSON pointers for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template - bool operator==(const json_pointer& rhs) const noexcept + template + bool + operator==(const json_pointer& rhs) const noexcept { return reference_tokens == rhs.reference_tokens; } /// @brief compares JSON pointer and string for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) - bool operator==(const string_t& rhs) const + JSON_HEDLEY_DEPRECATED_FOR(3.11.2, + operator==(json_pointer)) + bool + operator==(const string_t& rhs) const { return *this == json_pointer(rhs); } /// @brief 3-way compares two JSON pointers - template - std::strong_ordering operator<=>(const json_pointer& rhs) const noexcept // *NOPAD* + template + std::strong_ordering + operator<=>(const json_pointer& rhs) const noexcept // *NOPAD* { - return reference_tokens <=> rhs.reference_tokens; // *NOPAD* + return reference_tokens <=> rhs.reference_tokens; // *NOPAD* } #else /// @brief compares two JSON pointers for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template + template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(const json_pointer& lhs, - const json_pointer& rhs) noexcept; + friend bool + operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept; /// @brief compares JSON pointer and string for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template + template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(const json_pointer& lhs, - const StringType& rhs); + friend bool + operator==(const json_pointer& lhs, const StringType& rhs); /// @brief compares string and JSON pointer for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template + template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(const StringType& lhs, - const json_pointer& rhs); + friend bool + operator==(const StringType& lhs, const json_pointer& rhs); /// @brief compares two JSON pointers for inequality /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ - template + template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(const json_pointer& lhs, - const json_pointer& rhs) noexcept; + friend bool + operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept; /// @brief compares JSON pointer and string for inequality /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ - template + template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(const json_pointer& lhs, - const StringType& rhs); + friend bool + operator!=(const json_pointer& lhs, const StringType& rhs); /// @brief compares string and JSON pointer for inequality /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ - template + template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(const StringType& lhs, - const json_pointer& rhs); + friend bool + operator!=(const StringType& lhs, const json_pointer& rhs); /// @brief compares two JSON pointer for less-than - template + template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator<(const json_pointer& lhs, - const json_pointer& rhs) noexcept; + friend bool + operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept; #endif - private: +private: /// the reference tokens std::vector reference_tokens; }; #if !JSON_HAS_THREE_WAY_COMPARISON // functions cannot be defined inside class due to ODR violations -template -inline bool operator==(const json_pointer& lhs, - const json_pointer& rhs) noexcept +template +inline bool +operator==( + const json_pointer& lhs, const json_pointer& rhs) noexcept { return lhs.reference_tokens == rhs.reference_tokens; } -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) -inline bool operator==(const json_pointer& lhs, - const StringType& rhs) +template ::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, + operator==(json_pointer, json_pointer)) +inline bool +operator==(const json_pointer& lhs, const StringType& rhs) { return lhs == json_pointer(rhs); } -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) -inline bool operator==(const StringType& lhs, - const json_pointer& rhs) +template ::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, + operator==(json_pointer, json_pointer)) +inline bool +operator==(const StringType& lhs, const json_pointer& rhs) { return json_pointer(lhs) == rhs; } -template -inline bool operator!=(const json_pointer& lhs, - const json_pointer& rhs) noexcept +template +inline bool +operator!=( + const json_pointer& lhs, const json_pointer& rhs) noexcept { return !(lhs == rhs); } -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) -inline bool operator!=(const json_pointer& lhs, - const StringType& rhs) +template ::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, + operator!=(json_pointer, json_pointer)) +inline bool +operator!=(const json_pointer& lhs, const StringType& rhs) { return !(lhs == rhs); } -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) -inline bool operator!=(const StringType& lhs, - const json_pointer& rhs) +template ::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, + operator!=(json_pointer, json_pointer)) +inline bool +operator!=(const StringType& lhs, const json_pointer& rhs) { return !(lhs == rhs); } -template -inline bool operator<(const json_pointer& lhs, - const json_pointer& rhs) noexcept +template +inline bool +operator<( + const json_pointer& lhs, const json_pointer& rhs) noexcept { return lhs.reference_tokens < rhs.reference_tokens; } diff --git a/modules/commons/src/include/nlohmann/detail/json_ref.hpp b/modules/commons/src/include/nlohmann/detail/json_ref.hpp index b8bb6a76b0..d380718173 100644 --- a/modules/commons/src/include/nlohmann/detail/json_ref.hpp +++ b/modules/commons/src/include/nlohmann/detail/json_ref.hpp @@ -15,64 +15,61 @@ #include NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ +namespace detail { -template -class json_ref +template class json_ref { - public: +public: using value_type = BasicJsonType; - json_ref(value_type&& value) - : owned_value(std::move(value)) - {} + json_ref(value_type&& value) : owned_value(std::move(value)) { } - json_ref(const value_type& value) - : value_ref(&value) - {} + json_ref(const value_type& value) : value_ref(&value) { } - json_ref(std::initializer_list init) - : owned_value(init) - {} + json_ref(std::initializer_list init) : owned_value(init) { } - template < - class... Args, - enable_if_t::value, int> = 0 > - json_ref(Args && ... args) - : owned_value(std::forward(args)...) - {} + template ::value, int> = 0> + json_ref(Args&&... args) : owned_value(std::forward(args)...) + { + } // class should be movable only json_ref(json_ref&&) noexcept = default; json_ref(const json_ref&) = delete; - json_ref& operator=(const json_ref&) = delete; - json_ref& operator=(json_ref&&) = delete; + json_ref& + operator=(const json_ref&) + = delete; + json_ref& + operator=(json_ref&&) + = delete; ~json_ref() = default; - value_type moved_or_copied() const + value_type + moved_or_copied() const { - if (value_ref == nullptr) - { + if (value_ref == nullptr) { return std::move(owned_value); } return *value_ref; } - value_type const& operator*() const + value_type const& + operator*() const { return value_ref ? *value_ref : owned_value; } - value_type const* operator->() const + value_type const* + operator->() const { - return &** this; + return &**this; } - private: +private: mutable value_type owned_value = nullptr; value_type const* value_ref = nullptr; }; -} // namespace detail +} // namespace detail NLOHMANN_JSON_NAMESPACE_END diff --git a/modules/commons/src/include/nlohmann/detail/macro_scope.hpp b/modules/commons/src/include/nlohmann/detail/macro_scope.hpp index 97127a6462..715b3ac05c 100644 --- a/modules/commons/src/include/nlohmann/detail/macro_scope.hpp +++ b/modules/commons/src/include/nlohmann/detail/macro_scope.hpp @@ -19,192 +19,196 @@ // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif +#if defined(__clang__) +#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 +#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" +#endif +#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 +#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" +#endif +#endif #endif // C++ language standard detection // if the user manually specified the used c++ version this is skipped -#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) - #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 - #endif - // the cpp 11 flag is always specified because it is the minimal required version - #define JSON_HAS_CPP_11 +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) \ + && !defined(JSON_HAS_CPP_11) +#if (defined(__cplusplus) && __cplusplus >= 202002L) \ + || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +#define JSON_HAS_CPP_20 +#define JSON_HAS_CPP_17 +#define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201703L) \ + || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 +#define JSON_HAS_CPP_17 +#define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) +#define JSON_HAS_CPP_14 +#endif +// the cpp 11 flag is always specified because it is the minimal required version +#define JSON_HAS_CPP_11 #endif #ifdef __has_include - #if __has_include() - #include - #endif +#if __has_include() +#include +#endif #endif #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) - #ifdef JSON_HAS_CPP_17 - #if defined(__cpp_lib_filesystem) - #define JSON_HAS_FILESYSTEM 1 - #elif defined(__cpp_lib_experimental_filesystem) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif !defined(__has_include) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #endif - - // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ - #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__clang_major__) && __clang_major__ < 7 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support - #if defined(_MSC_VER) && _MSC_VER < 1914 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before iOS 13 - #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before macOS Catalina - #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - #endif +#ifdef JSON_HAS_CPP_17 +#if defined(__cpp_lib_filesystem) +#define JSON_HAS_FILESYSTEM 1 +#elif defined(__cpp_lib_experimental_filesystem) +#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 +#elif !defined(__has_include) +#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 +#elif __has_include() +#define JSON_HAS_FILESYSTEM 1 +#elif __has_include() +#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 +#endif + +// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ +#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#endif + +// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#endif + +// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support +#if defined(__clang_major__) && __clang_major__ < 7 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#endif + +// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support +#if defined(_MSC_VER) && _MSC_VER < 1914 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#endif + +// no filesystem support before iOS 13 +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#endif + +// no filesystem support before macOS Catalina +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#endif +#endif #endif #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 #endif #ifndef JSON_HAS_FILESYSTEM - #define JSON_HAS_FILESYSTEM 0 +#define JSON_HAS_FILESYSTEM 0 #endif #ifndef JSON_HAS_THREE_WAY_COMPARISON - #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ - && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L - #define JSON_HAS_THREE_WAY_COMPARISON 1 - #else - #define JSON_HAS_THREE_WAY_COMPARISON 0 - #endif +#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L +#define JSON_HAS_THREE_WAY_COMPARISON 1 +#else +#define JSON_HAS_THREE_WAY_COMPARISON 0 +#endif #endif #ifndef JSON_HAS_RANGES - // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error - #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 - #define JSON_HAS_RANGES 0 - #elif defined(__cpp_lib_ranges) - #define JSON_HAS_RANGES 1 - #else - #define JSON_HAS_RANGES 0 - #endif +// ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error +#if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 +#define JSON_HAS_RANGES 0 +#elif defined(__cpp_lib_ranges) +#define JSON_HAS_RANGES 1 +#else +#define JSON_HAS_RANGES 0 +#endif #endif #ifndef JSON_HAS_STATIC_RTTI - #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 - #define JSON_HAS_STATIC_RTTI 1 - #else - #define JSON_HAS_STATIC_RTTI 0 - #endif +#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 +#define JSON_INLINE_VARIABLE inline #else - #define JSON_INLINE_VARIABLE +#define JSON_INLINE_VARIABLE #endif #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) - #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] #else - #define JSON_NO_UNIQUE_ADDRESS +#define JSON_NO_UNIQUE_ADDRESS #endif // disable documentation warnings on clang #if defined(__clang__) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdocumentation" - #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" +#pragma clang diagnostic ignored "-Wdocumentation-unknown-command" #endif // allow disabling exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) \ + && !defined(JSON_NOEXCEPTION) +#define JSON_THROW(exception) throw exception +#define JSON_TRY try +#define JSON_CATCH(exception) catch (exception) +#define JSON_INTERNAL_CATCH(exception) catch (exception) #else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) +#include +#define JSON_THROW(exception) std::abort() +#define JSON_TRY if (true) +#define JSON_CATCH(exception) if (false) +#define JSON_INTERNAL_CATCH(exception) if (false) #endif // override exception macros #if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER +#undef JSON_THROW +#define JSON_THROW JSON_THROW_USER #endif #if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER +#undef JSON_TRY +#define JSON_TRY JSON_TRY_USER #endif #if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#undef JSON_CATCH +#define JSON_CATCH JSON_CATCH_USER +#undef JSON_INTERNAL_CATCH +#define JSON_INTERNAL_CATCH JSON_CATCH_USER #endif #if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#undef JSON_INTERNAL_CATCH +#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER #endif // allow overriding assert #if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) +#include // assert +#define JSON_ASSERT(x) assert(x) #endif // allow to access some private functions (needed by the test suite) #if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public +#define JSON_PRIVATE_UNLESS_TESTED public #else - #define JSON_PRIVATE_UNLESS_TESTED private +#define JSON_PRIVATE_UNLESS_TESTED private #endif /*! @@ -212,218 +216,499 @@ @def NLOHMANN_JSON_SERIALIZE_ENUM @since version 3.4.0 */ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They // may be removed in the future once the class is split. -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType, \ - class CustomBaseClass> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template