From 34049559cf47c240664b80057aead1b45ef2145e Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 02:01:45 +0530 Subject: [PATCH 01/38] fix: throw type_error.302 on unknown enum JSON value (fixes #3992) Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 9 +++++++- tests/src/unit-serialize_enum_strict.cpp | 29 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/src/unit-serialize_enum_strict.cpp diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 833b7ddf04..76a22d276f 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -250,7 +250,14 @@ { \ return ej_pair.second == j; \ }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + if (it == std::end(m)) \ + { \ + throw ::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ + nullptr); \ + } \ + e = it->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp new file mode 100644 index 0000000000..819c75b0d7 --- /dev/null +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -0,0 +1,29 @@ +#include +#include "../doctest/doctest.h" +using json = nlohmann::json; + +namespace ns { +enum class Color { red, green, blue, unknown }; + +NLOHMANN_JSON_SERIALIZE_ENUM(Color, { + { Color::unknown, "unknown" }, + { Color::red, "red" }, + { Color::green, "green" }, + { Color::blue, "blue" } +}) +} // namespace ns + +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM throws on unknown input string") +{ + json j = "purple"; // not mapped + ns::Color c; + + CHECK_THROWS_AS((j.get_to(c)), nlohmann::detail::type_error); +} + +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM still deserializes valid values") +{ + json j = "green"; + auto c = j.get(); + CHECK(c == ns::Color::green); +} \ No newline at end of file From e87fbc33115f9f7880760a648075fd6811f5157f Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 02:13:49 +0530 Subject: [PATCH 02/38] chore: regenerate single-header after enum deserialization fix Signed-off-by: Ash-Jose --- single_include/nlohmann/json.hpp | 135 ++++++++++++++++--------------- 1 file changed, 71 insertions(+), 64 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ceb7a9f11d..11140f3bec 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2614,7 +2614,14 @@ JSON_HEDLEY_DIAGNOSTIC_POP { \ return ej_pair.second == j; \ }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + if (it == std::end(m)) \ + { \ + throw ::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ + nullptr); \ + } \ + e = it->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They @@ -3499,71 +3506,71 @@ NLOHMANN_JSON_NAMESPACE_END // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ +#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #include // int64_t, uint64_t - #include // map - #include // allocator - #include // string - #include // vector +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector - // #include +// #include - /*! - @brief namespace for Niels Lohmann - @see https://github.com/nlohmann - @since version 1.0.0 - */ - NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +NLOHMANN_JSON_NAMESPACE_BEGIN - /*! - @brief default JSONSerializer template argument +/*! +@brief default JSONSerializer template argument - This serializer ignores the template arguments and uses ADL - ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) - for serialization. - */ - template - struct adl_serializer; - - /// a class to store JSON values - /// @sa https://json.nlohmann.me/api/basic_json/ - template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> - class basic_json; - - /// @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; +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +/// a class to store JSON values +/// @sa https://json.nlohmann.me/api/basic_json/ +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> +class basic_json; - /*! - @brief default specialization - @sa https://json.nlohmann.me/api/json/ - */ - using json = basic_json<>; +/// @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; - /// @brief a minimal map-like container that preserves insertion order - /// @sa https://json.nlohmann.me/api/ordered_map/ - template - struct ordered_map; +/*! +@brief default specialization +@sa https://json.nlohmann.me/api/json/ +*/ +using json = basic_json<>; - /// @brief specialization that maintains the insertion order of object keys - /// @sa https://json.nlohmann.me/api/ordered_json/ - using ordered_json = basic_json; +/// @brief a minimal map-like container that preserves insertion order +/// @sa https://json.nlohmann.me/api/ordered_map/ +template +struct ordered_map; - NLOHMANN_JSON_NAMESPACE_END +/// @brief specialization that maintains the insertion order of object keys +/// @sa https://json.nlohmann.me/api/ordered_json/ +using ordered_json = basic_json; + +NLOHMANN_JSON_NAMESPACE_END #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ @@ -5427,7 +5434,7 @@ NLOHMANN_JSON_NAMESPACE_END // #include -// JSON_HAS_CPP_17 + // JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17 #include // optional #endif @@ -20255,10 +20262,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true, const bool ignore_comments = false, const bool ignore_trailing_commas = false - ) + ) { return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); + std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); } private: @@ -20956,8 +20963,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::enable_if_t < !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) - JSONSerializer::to_json(std::declval(), - std::forward(val)))) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); set_parents(); @@ -21751,7 +21758,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) + JSONSerializer::from_json(std::declval(), std::declval()))) { auto ret = ValueType(); JSONSerializer::from_json(*this, ret); @@ -21793,7 +21800,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_non_default_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { return JSONSerializer::from_json(*this); } @@ -21943,7 +21950,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) + JSONSerializer::from_json(std::declval(), v))) { JSONSerializer::from_json(*this, v); return v; From 382367d3f11b0c5e18a917406497e3fd1081e89b Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 04:03:31 +0530 Subject: [PATCH 03/38] add NLOHMANN_JSON_SERIALIZE_ENUM_STRICT macro that throws on unknown JSON value (Fixes #3992) Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 35 ++++++++++++++++++++++++ single_include/nlohmann/json.hpp | 35 ++++++++++++++++++++++++ tests/src/unit-serialize_enum_strict.cpp | 6 ++-- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 76a22d276f..9d77917474 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -224,6 +224,41 @@ @since version 3.4.0 */ #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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; \ + } + +/*! +@brief macro to briefly define a mapping between an enum and JSON (strict version) +@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT +@since version 3.12.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ { \ diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 11140f3bec..33702790af 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2588,6 +2588,41 @@ JSON_HEDLEY_DIAGNOSTIC_POP @since version 3.4.0 */ #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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; \ + } + +/*! +@brief macro to briefly define a mapping between an enum and JSON (strict version) +@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT +@since version 3.12.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ { \ diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 819c75b0d7..94c24e572f 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -5,7 +5,7 @@ using json = nlohmann::json; namespace ns { enum class Color { red, green, blue, unknown }; -NLOHMANN_JSON_SERIALIZE_ENUM(Color, { +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, { { Color::unknown, "unknown" }, { Color::red, "red" }, { Color::green, "green" }, @@ -13,7 +13,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(Color, { }) } // namespace ns -TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM throws on unknown input string") +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT throws on unknown input string") { json j = "purple"; // not mapped ns::Color c; @@ -21,7 +21,7 @@ TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM throws on unknown input string") CHECK_THROWS_AS((j.get_to(c)), nlohmann::detail::type_error); } -TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM still deserializes valid values") +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT still deserializes valid values") { json j = "green"; auto c = j.get(); From 3d0e74cb4a06aa9cc027a5aac82350695692fcf7 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 14:52:21 +0530 Subject: [PATCH 04/38] style: apply concat() suggestion and rerun make amalgamate - Replaced std::string concatenation with concat() per maintainer feedback - Added missing newline in unit-serialize_enum_strict.cpp - Regenerated single-header files using make amalgamate for proper indentation Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 4 ++-- single_include/nlohmann/json.hpp | 4 ++-- tests/src/unit-serialize_enum_strict.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 9d77917474..6cb87b78c6 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -289,8 +289,8 @@ { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - nullptr); \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 33702790af..553db936d4 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2653,8 +2653,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - nullptr); \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 94c24e572f..3aab9963c0 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -26,4 +26,4 @@ TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT still deserializes valid values") json j = "green"; auto c = j.get(); CHECK(c == ns::Color::green); -} \ No newline at end of file +} From cb710cc54d5c496ef8e496b558fa01c8ad2c36ec Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 15:22:21 +0530 Subject: [PATCH 05/38] style: apply concat() suggestion and rerun make amalgamate Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 6 +- single_include/nlohmann/json.hpp | 132 +++++++++++------------ tests/src/unit-serialize_enum_strict.cpp | 6 +- 3 files changed, 73 insertions(+), 71 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 6cb87b78c6..1e2beeb4e4 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -288,9 +288,9 @@ if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 553db936d4..d59713dc09 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2652,9 +2652,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } @@ -3541,71 +3541,71 @@ NLOHMANN_JSON_NAMESPACE_END // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector - -// #include + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + // #include -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -NLOHMANN_JSON_NAMESPACE_BEGIN -/*! -@brief default JSONSerializer template argument + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; - -/// a class to store JSON values -/// @sa https://json.nlohmann.me/api/basic_json/ -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> -class basic_json; + /*! + @brief default JSONSerializer template argument -/// @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; + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @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; -/*! -@brief default specialization -@sa https://json.nlohmann.me/api/json/ -*/ -using json = basic_json<>; + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; -/// @brief a minimal map-like container that preserves insertion order -/// @sa https://json.nlohmann.me/api/ordered_map/ -template -struct ordered_map; + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; -/// @brief specialization that maintains the insertion order of object keys -/// @sa https://json.nlohmann.me/api/ordered_json/ -using ordered_json = basic_json; + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; -NLOHMANN_JSON_NAMESPACE_END + NLOHMANN_JSON_NAMESPACE_END #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ @@ -5469,7 +5469,7 @@ NLOHMANN_JSON_NAMESPACE_END // #include - // JSON_HAS_CPP_17 +// JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17 #include // optional #endif @@ -20297,10 +20297,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true, const bool ignore_comments = false, const bool ignore_trailing_commas = false - ) + ) { return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); + std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); } private: @@ -20998,8 +20998,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::enable_if_t < !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) - JSONSerializer::to_json(std::declval(), - std::forward(val)))) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); set_parents(); @@ -21793,7 +21793,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) + JSONSerializer::from_json(std::declval(), std::declval()))) { auto ret = ValueType(); JSONSerializer::from_json(*this, ret); @@ -21835,7 +21835,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_non_default_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { return JSONSerializer::from_json(*this); } @@ -21985,7 +21985,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) + JSONSerializer::from_json(std::declval(), v))) { JSONSerializer::from_json(*this, v); return v; diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 3aab9963c0..939f79fe2b 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -2,10 +2,12 @@ #include "../doctest/doctest.h" using json = nlohmann::json; -namespace ns { +namespace ns +{ enum class Color { red, green, blue, unknown }; -NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, { +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, +{ { Color::unknown, "unknown" }, { Color::red, "red" }, { Color::green, "green" }, From 216a636597d3066e72eb4de5b6ccd8ae73d227de Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 16:47:06 +0530 Subject: [PATCH 06/38] fix: include string_concat.hpp and correct concat() usage in NLOHMANN_JSON_SERIALIZE_ENUM_STRICT - Added missing include for - Replaced string concatenation with concat() call as suggested by maintainer - Re-ran `make amalgamate` to update single-header files Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 1 + single_include/nlohmann/json.hpp | 768 ++++++++++++------------ 2 files changed, 386 insertions(+), 383 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 1e2beeb4e4..1dde8f14f2 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -11,6 +11,7 @@ #include // declval, pair #include #include +#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index d59713dc09..9ac9871805 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2374,6 +2374,328 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // strlen +#include // string +#include // forward + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +inline std::size_t concat_length() +{ + return 0; +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest); + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest); + +template +inline std::size_t concat_length(const char /*c*/, const Args& ... rest) +{ + return 1 + concat_length(rest...); +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest) +{ + // cppcheck-suppress ignoredReturnValue + return ::strlen(cstr) + concat_length(rest...); +} + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest) +{ + return str.size() + concat_length(rest...); +} + +template +inline void concat_into(OutStringType& /*out*/) +{} + +template +using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); + +template +using detect_string_can_append = is_detected; + +template +using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); + +template +using detect_string_can_append_op = is_detected; + +template +using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); + +template +using detect_string_can_append_iter = is_detected; + +template +using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); + +template +using detect_string_can_append_data = is_detected; + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > = 0 > +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template::value, int> = 0> +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) +{ + out.append(std::forward(arg)); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > > +inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) +{ + out += std::forward(arg); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.begin(), arg.end()); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.data(), arg.size()); + concat_into(out, std::forward(rest)...); +} + +template +inline OutStringType concat(Args && ... args) +{ + OutStringType str; + str.reserve(concat_length(args...)); + concat_into(str, std::forward(args)...); + return str; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -3146,260 +3468,88 @@ inline void replace_substring(StringType& s, const StringType& f, { JSON_ASSERT(!f.empty()); for (auto pos = s.find(f); // find the first occurrence of f - pos != StringType::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find the next occurrence of f - {} -} - -/*! - * @brief string escaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to escape - * @return escaped string - * - * Note the order of escaping "~" to "~0" and "/" to "~1" is important. - */ -template -inline StringType escape(StringType s) -{ - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} - -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -inline void unescape(StringType& s) -{ - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // size_t - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find the next occurrence of f + {} +} -template -struct Gen +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) { - using type = integer_sequence; -}; + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} -} // namespace utility_internal +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +inline void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} -// Compile-time sequences of integers +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END -// make_integer_sequence +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; -//// END OF CODE FROM GOOGLE ABSEIL +#include // size_t -#endif +// #include -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; -// taken from ranges-v3 -template -struct static_const +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail { - static JSON_INLINE_VARIABLE constexpr T value{}; -}; -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -constexpr std::array make_array(Args&& ... args) +/// struct to capture the start position of the current token +struct position_t { - return std::array {{static_cast(std::forward(args))...}}; -} + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; } // namespace detail NLOHMANN_JSON_NAMESPACE_END +// #include + +// #include + // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ @@ -4422,154 +4572,6 @@ struct is_transparent : bool_constant()> {}; NLOHMANN_JSON_NAMESPACE_END // #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // strlen -#include // string -#include // forward - -// #include - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -inline std::size_t concat_length() -{ - return 0; -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest); - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest); - -template -inline std::size_t concat_length(const char /*c*/, const Args& ... rest) -{ - return 1 + concat_length(rest...); -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest) -{ - // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(rest...); -} - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest) -{ - return str.size() + concat_length(rest...); -} - -template -inline void concat_into(OutStringType& /*out*/) -{} - -template -using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); - -template -using detect_string_can_append = is_detected; - -template -using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); - -template -using detect_string_can_append_op = is_detected; - -template -using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); - -template -using detect_string_can_append_iter = is_detected; - -template -using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); - -template -using detect_string_can_append_data = is_detected; - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > = 0 > -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template::value, int> = 0> -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) -{ - out.append(std::forward(arg)); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > > -inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) -{ - out += std::forward(arg); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.begin(), arg.end()); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.data(), arg.size()); - concat_into(out, std::forward(rest)...); -} - -template -inline OutStringType concat(Args && ... args) -{ - OutStringType str; - str.reserve(concat_length(args...)); - concat_into(str, std::forward(args)...); - return str; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END // With -Wweak-vtables, Clang will complain about the exception classes as they From 7863aa39ec57836655c479da9ba62bdd550752e5 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 16:48:22 +0530 Subject: [PATCH 07/38] made few formatting changes in macro_scope.hpp Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 1dde8f14f2..b318100d6c 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -289,9 +289,9 @@ if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } From 3155e6a1d3a200daa7c63e7193bfc771a75dd1a5 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 17:50:30 +0530 Subject: [PATCH 08/38] ran make amalgamate again Signed-off-by: Ash-Jose --- single_include/nlohmann/json.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9ac9871805..ebb3359b76 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2974,9 +2974,9 @@ NLOHMANN_JSON_NAMESPACE_END if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } From a0fc73b758f5049e29d3034c7998f5dcadea7ebc Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 19:52:51 +0530 Subject: [PATCH 09/38] revert to std::string() concat in enum strict macro Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 3 +- single_include/nlohmann/json.hpp | 740 ++++++++++++------------ 2 files changed, 370 insertions(+), 373 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index b318100d6c..99cf5dc8ba 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -11,7 +11,6 @@ #include // declval, pair #include #include -#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -290,7 +289,7 @@ { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ j); \ } \ e = it->first; \ diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ebb3359b76..0dd155ff14 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2374,328 +2374,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // strlen -#include // string -#include // forward - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; - -template -struct Gen -{ - using type = integer_sequence; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; - -//// END OF CODE FROM GOOGLE ABSEIL - -#endif - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static JSON_INLINE_VARIABLE constexpr T value{}; -}; - -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -constexpr std::array make_array(Args&& ... args) -{ - return std::array {{static_cast(std::forward(args))...}}; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -inline std::size_t concat_length() -{ - return 0; -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest); - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest); - -template -inline std::size_t concat_length(const char /*c*/, const Args& ... rest) -{ - return 1 + concat_length(rest...); -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest) -{ - // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(rest...); -} - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest) -{ - return str.size() + concat_length(rest...); -} - -template -inline void concat_into(OutStringType& /*out*/) -{} - -template -using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); - -template -using detect_string_can_append = is_detected; - -template -using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); - -template -using detect_string_can_append_op = is_detected; - -template -using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); - -template -using detect_string_can_append_iter = is_detected; - -template -using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); - -template -using detect_string_can_append_data = is_detected; - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > = 0 > -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template::value, int> = 0> -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) -{ - out.append(std::forward(arg)); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > > -inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) -{ - out += std::forward(arg); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.begin(), arg.end()); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.data(), arg.size()); - concat_into(out, std::forward(rest)...); -} - -template -inline OutStringType concat(Args && ... args) -{ - OutStringType str; - str.reserve(concat_length(args...)); - concat_into(str, std::forward(args)...); - return str; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -2975,7 +2653,7 @@ NLOHMANN_JSON_NAMESPACE_END { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ j); \ } \ e = it->first; \ @@ -3484,72 +3162,244 @@ inline void replace_substring(StringType& s, const StringType& f, template inline StringType escape(StringType s) { - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +inline void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -inline void unescape(StringType& s) +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen { - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END +template +struct Gen +{ + using type = integer_sequence; +}; -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence // -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; -#include // size_t +//// END OF CODE FROM GOOGLE ABSEIL -// #include +#endif +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail +// taken from ranges-v3 +template +struct static_const { + static JSON_INLINE_VARIABLE constexpr T value{}; +}; -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; +template +constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} } // namespace detail NLOHMANN_JSON_NAMESPACE_END -// #include - -// #include - // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ @@ -4572,6 +4422,154 @@ struct is_transparent : bool_constant()> {}; NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // strlen +#include // string +#include // forward + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +inline std::size_t concat_length() +{ + return 0; +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest); + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest); + +template +inline std::size_t concat_length(const char /*c*/, const Args& ... rest) +{ + return 1 + concat_length(rest...); +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest) +{ + // cppcheck-suppress ignoredReturnValue + return ::strlen(cstr) + concat_length(rest...); +} + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest) +{ + return str.size() + concat_length(rest...); +} + +template +inline void concat_into(OutStringType& /*out*/) +{} + +template +using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); + +template +using detect_string_can_append = is_detected; + +template +using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); + +template +using detect_string_can_append_op = is_detected; + +template +using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); + +template +using detect_string_can_append_iter = is_detected; + +template +using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); + +template +using detect_string_can_append_data = is_detected; + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > = 0 > +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template::value, int> = 0> +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) +{ + out.append(std::forward(arg)); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > > +inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) +{ + out += std::forward(arg); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.begin(), arg.end()); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.data(), arg.size()); + concat_into(out, std::forward(rest)...); +} + +template +inline OutStringType concat(Args && ... args) +{ + OutStringType str; + str.reserve(concat_length(args...)); + concat_into(str, std::forward(args)...); + return str; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // With -Wweak-vtables, Clang will complain about the exception classes as they From 88e36cbf2a89d58943f3d20ea88fa6610636a76c Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 21:46:04 +0530 Subject: [PATCH 10/38] fix: include exceptions.hpp for type_error in enum strict macro Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 1 + single_include/nlohmann/json.hpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 99cf5dc8ba..97663ad4ef 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -16,6 +16,7 @@ // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them #include +#include // for type_error // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0dd155ff14..ddfa92ac4f 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2380,6 +2380,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP // #include +// #include +// for type_error // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) From e07de0e773eddbd1f43ce395385596692acb71a5 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 22:56:08 +0530 Subject: [PATCH 11/38] fix: add forward declaration for type_error to avoid circular include Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 10 +++++++++- single_include/nlohmann/json.hpp | 11 +++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 97663ad4ef..21df32b3b0 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -16,7 +16,15 @@ // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them #include -#include // for type_error + +// forward declaration to avoid circular include with exceptions.hpp +namespace nlohmann +{ +namespace detail +{ +class type_error; +} // namespace detail +} // namespace nlohmann // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ddfa92ac4f..49c2602c5e 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2380,8 +2380,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP // #include -// #include -// for type_error + +// forward declaration to avoid circular include with exceptions.hpp +namespace nlohmann +{ +namespace detail +{ +class type_error; +} // namespace detail +} // namespace nlohmann // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) From 31c67e3e3221a9216718f6b08be2e5f098f8e8fa Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 00:15:43 +0530 Subject: [PATCH 12/38] fix: make NLOHMANN_JSON_SERIALIZE_ENUM_STRICT throw type_error on unknown values Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 13 ++----------- single_include/nlohmann/json.hpp | 13 ++----------- test.json | 7 +++++++ 3 files changed, 11 insertions(+), 22 deletions(-) create mode 100644 test.json diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 21df32b3b0..3f247a93ce 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -17,15 +17,6 @@ #include -// forward declaration to avoid circular include with exceptions.hpp -namespace nlohmann -{ -namespace detail -{ -class type_error; -} // namespace detail -} // namespace nlohmann - // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) #if defined(__clang__) @@ -296,10 +287,10 @@ class type_error; }); \ if (it == std::end(m)) \ { \ - throw ::nlohmann::detail::type_error::create( \ + throw nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - j); \ + &j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 49c2602c5e..8626747e7f 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2381,15 +2381,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP // #include -// forward declaration to avoid circular include with exceptions.hpp -namespace nlohmann -{ -namespace detail -{ -class type_error; -} // namespace detail -} // namespace nlohmann - // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) #if defined(__clang__) @@ -2660,10 +2651,10 @@ class type_error; }); \ if (it == std::end(m)) \ { \ - throw ::nlohmann::detail::type_error::create( \ + throw nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - j); \ + &j); \ } \ e = it->first; \ } diff --git a/test.json b/test.json new file mode 100644 index 0000000000..bc7289bc1b --- /dev/null +++ b/test.json @@ -0,0 +1,7 @@ +{ +"one" : 1, +"two" : 2 +} +{ +"three" : 3 +} \ No newline at end of file From 8c13504c45a38e108934a402740804436a8aeff8 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 00:26:03 +0530 Subject: [PATCH 13/38] minor formatting changes Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 4 ++-- single_include/nlohmann/json.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 3f247a93ce..f274f56fc2 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -287,10 +287,10 @@ }); \ if (it == std::end(m)) \ { \ - throw nlohmann::detail::type_error::create( \ + throw ::nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ + &j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 8626747e7f..6644c10086 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2651,10 +2651,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP }); \ if (it == std::end(m)) \ { \ - throw nlohmann::detail::type_error::create( \ + throw ::nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ + &j); \ } \ e = it->first; \ } From 9882be480726a84fe3e36e3ab50539bce3efe926 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 02:12:17 +0530 Subject: [PATCH 14/38] removed test,json which was left there by accident included string header Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 1 + test.json | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 test.json diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index f274f56fc2..651e4c3514 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -11,6 +11,7 @@ #include // declval, pair #include #include +#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them diff --git a/test.json b/test.json deleted file mode 100644 index bc7289bc1b..0000000000 --- a/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ -"one" : 1, -"two" : 2 -} -{ -"three" : 3 -} \ No newline at end of file From 780df1a4a51a2e49755fa604f7982ceae6304432 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 02:23:48 +0530 Subject: [PATCH 15/38] changed formatting of unit-serialize_enum_strict.cpp and amalgamated Signed-off-by: Ash-Jose --- single_include/nlohmann/json.hpp | 1 + tests/src/unit-serialize_enum_strict.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 6644c10086..3712f76642 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2374,6 +2374,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ +#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 939f79fe2b..50362ea17b 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -1,5 +1,14 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + #include #include "../doctest/doctest.h" + using json = nlohmann::json; namespace ns From a6a57cd21d23971d74a55f8ddd91bb90d5f2de78 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 02:01:45 +0530 Subject: [PATCH 16/38] fix: throw type_error.302 on unknown enum JSON value (fixes #3992) Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 9 +++++++- tests/src/unit-serialize_enum_strict.cpp | 29 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/src/unit-serialize_enum_strict.cpp diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 833b7ddf04..76a22d276f 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -250,7 +250,14 @@ { \ return ej_pair.second == j; \ }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + if (it == std::end(m)) \ + { \ + throw ::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ + nullptr); \ + } \ + e = it->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp new file mode 100644 index 0000000000..819c75b0d7 --- /dev/null +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -0,0 +1,29 @@ +#include +#include "../doctest/doctest.h" +using json = nlohmann::json; + +namespace ns { +enum class Color { red, green, blue, unknown }; + +NLOHMANN_JSON_SERIALIZE_ENUM(Color, { + { Color::unknown, "unknown" }, + { Color::red, "red" }, + { Color::green, "green" }, + { Color::blue, "blue" } +}) +} // namespace ns + +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM throws on unknown input string") +{ + json j = "purple"; // not mapped + ns::Color c; + + CHECK_THROWS_AS((j.get_to(c)), nlohmann::detail::type_error); +} + +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM still deserializes valid values") +{ + json j = "green"; + auto c = j.get(); + CHECK(c == ns::Color::green); +} \ No newline at end of file From fc2effbd0008a9317eb66e0de7f6fec259945380 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 02:13:49 +0530 Subject: [PATCH 17/38] chore: regenerate single-header after enum deserialization fix Signed-off-by: Ash-Jose --- single_include/nlohmann/json.hpp | 135 ++++++++++++++++--------------- 1 file changed, 71 insertions(+), 64 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ceb7a9f11d..11140f3bec 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2614,7 +2614,14 @@ JSON_HEDLEY_DIAGNOSTIC_POP { \ return ej_pair.second == j; \ }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + if (it == std::end(m)) \ + { \ + throw ::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ + nullptr); \ + } \ + e = it->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They @@ -3499,71 +3506,71 @@ NLOHMANN_JSON_NAMESPACE_END // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ +#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #include // int64_t, uint64_t - #include // map - #include // allocator - #include // string - #include // vector +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector - // #include +// #include - /*! - @brief namespace for Niels Lohmann - @see https://github.com/nlohmann - @since version 1.0.0 - */ - NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +NLOHMANN_JSON_NAMESPACE_BEGIN - /*! - @brief default JSONSerializer template argument +/*! +@brief default JSONSerializer template argument - This serializer ignores the template arguments and uses ADL - ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) - for serialization. - */ - template - struct adl_serializer; - - /// a class to store JSON values - /// @sa https://json.nlohmann.me/api/basic_json/ - template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> - class basic_json; - - /// @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; +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +/// a class to store JSON values +/// @sa https://json.nlohmann.me/api/basic_json/ +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> +class basic_json; - /*! - @brief default specialization - @sa https://json.nlohmann.me/api/json/ - */ - using json = basic_json<>; +/// @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; - /// @brief a minimal map-like container that preserves insertion order - /// @sa https://json.nlohmann.me/api/ordered_map/ - template - struct ordered_map; +/*! +@brief default specialization +@sa https://json.nlohmann.me/api/json/ +*/ +using json = basic_json<>; - /// @brief specialization that maintains the insertion order of object keys - /// @sa https://json.nlohmann.me/api/ordered_json/ - using ordered_json = basic_json; +/// @brief a minimal map-like container that preserves insertion order +/// @sa https://json.nlohmann.me/api/ordered_map/ +template +struct ordered_map; - NLOHMANN_JSON_NAMESPACE_END +/// @brief specialization that maintains the insertion order of object keys +/// @sa https://json.nlohmann.me/api/ordered_json/ +using ordered_json = basic_json; + +NLOHMANN_JSON_NAMESPACE_END #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ @@ -5427,7 +5434,7 @@ NLOHMANN_JSON_NAMESPACE_END // #include -// JSON_HAS_CPP_17 + // JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17 #include // optional #endif @@ -20255,10 +20262,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true, const bool ignore_comments = false, const bool ignore_trailing_commas = false - ) + ) { return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); + std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); } private: @@ -20956,8 +20963,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::enable_if_t < !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) - JSONSerializer::to_json(std::declval(), - std::forward(val)))) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); set_parents(); @@ -21751,7 +21758,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) + JSONSerializer::from_json(std::declval(), std::declval()))) { auto ret = ValueType(); JSONSerializer::from_json(*this, ret); @@ -21793,7 +21800,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_non_default_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { return JSONSerializer::from_json(*this); } @@ -21943,7 +21950,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) + JSONSerializer::from_json(std::declval(), v))) { JSONSerializer::from_json(*this, v); return v; From 07b7f675453e48e33ee52b74a5df38a213bf4e90 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 04:03:31 +0530 Subject: [PATCH 18/38] add NLOHMANN_JSON_SERIALIZE_ENUM_STRICT macro that throws on unknown JSON value (Fixes #3992) Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 35 ++++++++++++++++++++++++ single_include/nlohmann/json.hpp | 35 ++++++++++++++++++++++++ tests/src/unit-serialize_enum_strict.cpp | 6 ++-- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 76a22d276f..9d77917474 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -224,6 +224,41 @@ @since version 3.4.0 */ #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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; \ + } + +/*! +@brief macro to briefly define a mapping between an enum and JSON (strict version) +@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT +@since version 3.12.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ { \ diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 11140f3bec..33702790af 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2588,6 +2588,41 @@ JSON_HEDLEY_DIAGNOSTIC_POP @since version 3.4.0 */ #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + 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; \ + } + +/*! +@brief macro to briefly define a mapping between an enum and JSON (strict version) +@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT +@since version 3.12.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ { \ diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 819c75b0d7..94c24e572f 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -5,7 +5,7 @@ using json = nlohmann::json; namespace ns { enum class Color { red, green, blue, unknown }; -NLOHMANN_JSON_SERIALIZE_ENUM(Color, { +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, { { Color::unknown, "unknown" }, { Color::red, "red" }, { Color::green, "green" }, @@ -13,7 +13,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(Color, { }) } // namespace ns -TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM throws on unknown input string") +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT throws on unknown input string") { json j = "purple"; // not mapped ns::Color c; @@ -21,7 +21,7 @@ TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM throws on unknown input string") CHECK_THROWS_AS((j.get_to(c)), nlohmann::detail::type_error); } -TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM still deserializes valid values") +TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT still deserializes valid values") { json j = "green"; auto c = j.get(); From ac5e684069e0e61948e00de1aee4c33c0eb3936d Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 14:52:21 +0530 Subject: [PATCH 19/38] style: apply concat() suggestion and rerun make amalgamate - Replaced std::string concatenation with concat() per maintainer feedback - Added missing newline in unit-serialize_enum_strict.cpp - Regenerated single-header files using make amalgamate for proper indentation Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 4 ++-- single_include/nlohmann/json.hpp | 4 ++-- tests/src/unit-serialize_enum_strict.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 9d77917474..6cb87b78c6 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -289,8 +289,8 @@ { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - nullptr); \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 33702790af..553db936d4 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2653,8 +2653,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - nullptr); \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 94c24e572f..3aab9963c0 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -26,4 +26,4 @@ TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT still deserializes valid values") json j = "green"; auto c = j.get(); CHECK(c == ns::Color::green); -} \ No newline at end of file +} From 576975fe282f02d876d28096dbc7dc795d865221 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 15:22:21 +0530 Subject: [PATCH 20/38] style: apply concat() suggestion and rerun make amalgamate Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 6 +- single_include/nlohmann/json.hpp | 132 +++++++++++------------ tests/src/unit-serialize_enum_strict.cpp | 6 +- 3 files changed, 73 insertions(+), 71 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 6cb87b78c6..1e2beeb4e4 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -288,9 +288,9 @@ if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 553db936d4..d59713dc09 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2652,9 +2652,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } @@ -3541,71 +3541,71 @@ NLOHMANN_JSON_NAMESPACE_END // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector - -// #include + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + // #include -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -NLOHMANN_JSON_NAMESPACE_BEGIN -/*! -@brief default JSONSerializer template argument + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; - -/// a class to store JSON values -/// @sa https://json.nlohmann.me/api/basic_json/ -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> -class basic_json; + /*! + @brief default JSONSerializer template argument -/// @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; + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @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; -/*! -@brief default specialization -@sa https://json.nlohmann.me/api/json/ -*/ -using json = basic_json<>; + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; -/// @brief a minimal map-like container that preserves insertion order -/// @sa https://json.nlohmann.me/api/ordered_map/ -template -struct ordered_map; + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; -/// @brief specialization that maintains the insertion order of object keys -/// @sa https://json.nlohmann.me/api/ordered_json/ -using ordered_json = basic_json; + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; -NLOHMANN_JSON_NAMESPACE_END + NLOHMANN_JSON_NAMESPACE_END #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ @@ -5469,7 +5469,7 @@ NLOHMANN_JSON_NAMESPACE_END // #include - // JSON_HAS_CPP_17 +// JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17 #include // optional #endif @@ -20297,10 +20297,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true, const bool ignore_comments = false, const bool ignore_trailing_commas = false - ) + ) { return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); + std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas); } private: @@ -20998,8 +20998,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::enable_if_t < !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) - JSONSerializer::to_json(std::declval(), - std::forward(val)))) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); set_parents(); @@ -21793,7 +21793,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) + JSONSerializer::from_json(std::declval(), std::declval()))) { auto ret = ValueType(); JSONSerializer::from_json(*this, ret); @@ -21835,7 +21835,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_non_default_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { return JSONSerializer::from_json(*this); } @@ -21985,7 +21985,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) + JSONSerializer::from_json(std::declval(), v))) { JSONSerializer::from_json(*this, v); return v; diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 3aab9963c0..939f79fe2b 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -2,10 +2,12 @@ #include "../doctest/doctest.h" using json = nlohmann::json; -namespace ns { +namespace ns +{ enum class Color { red, green, blue, unknown }; -NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, { +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, +{ { Color::unknown, "unknown" }, { Color::red, "red" }, { Color::green, "green" }, From 893b4e84617e9751c943dde6f347f5ef7526a338 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 16:47:06 +0530 Subject: [PATCH 21/38] fix: include string_concat.hpp and correct concat() usage in NLOHMANN_JSON_SERIALIZE_ENUM_STRICT - Added missing include for - Replaced string concatenation with concat() call as suggested by maintainer - Re-ran `make amalgamate` to update single-header files Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 1 + single_include/nlohmann/json.hpp | 768 ++++++++++++------------ 2 files changed, 386 insertions(+), 383 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 1e2beeb4e4..1dde8f14f2 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -11,6 +11,7 @@ #include // declval, pair #include #include +#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index d59713dc09..9ac9871805 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2374,6 +2374,328 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // strlen +#include // string +#include // forward + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +inline std::size_t concat_length() +{ + return 0; +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest); + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest); + +template +inline std::size_t concat_length(const char /*c*/, const Args& ... rest) +{ + return 1 + concat_length(rest...); +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest) +{ + // cppcheck-suppress ignoredReturnValue + return ::strlen(cstr) + concat_length(rest...); +} + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest) +{ + return str.size() + concat_length(rest...); +} + +template +inline void concat_into(OutStringType& /*out*/) +{} + +template +using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); + +template +using detect_string_can_append = is_detected; + +template +using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); + +template +using detect_string_can_append_op = is_detected; + +template +using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); + +template +using detect_string_can_append_iter = is_detected; + +template +using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); + +template +using detect_string_can_append_data = is_detected; + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > = 0 > +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template::value, int> = 0> +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) +{ + out.append(std::forward(arg)); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > > +inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) +{ + out += std::forward(arg); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.begin(), arg.end()); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.data(), arg.size()); + concat_into(out, std::forward(rest)...); +} + +template +inline OutStringType concat(Args && ... args) +{ + OutStringType str; + str.reserve(concat_length(args...)); + concat_into(str, std::forward(args)...); + return str; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -3146,260 +3468,88 @@ inline void replace_substring(StringType& s, const StringType& f, { JSON_ASSERT(!f.empty()); for (auto pos = s.find(f); // find the first occurrence of f - pos != StringType::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find the next occurrence of f - {} -} - -/*! - * @brief string escaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to escape - * @return escaped string - * - * Note the order of escaping "~" to "~0" and "/" to "~1" is important. - */ -template -inline StringType escape(StringType s) -{ - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} - -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -inline void unescape(StringType& s) -{ - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // size_t - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find the next occurrence of f + {} +} -template -struct Gen +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) { - using type = integer_sequence; -}; + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} -} // namespace utility_internal +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +inline void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} -// Compile-time sequences of integers +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END -// make_integer_sequence +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; -//// END OF CODE FROM GOOGLE ABSEIL +#include // size_t -#endif +// #include -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; -// taken from ranges-v3 -template -struct static_const +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail { - static JSON_INLINE_VARIABLE constexpr T value{}; -}; -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -constexpr std::array make_array(Args&& ... args) +/// struct to capture the start position of the current token +struct position_t { - return std::array {{static_cast(std::forward(args))...}}; -} + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; } // namespace detail NLOHMANN_JSON_NAMESPACE_END +// #include + +// #include + // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ @@ -4422,154 +4572,6 @@ struct is_transparent : bool_constant()> {}; NLOHMANN_JSON_NAMESPACE_END // #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // strlen -#include // string -#include // forward - -// #include - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -inline std::size_t concat_length() -{ - return 0; -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest); - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest); - -template -inline std::size_t concat_length(const char /*c*/, const Args& ... rest) -{ - return 1 + concat_length(rest...); -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest) -{ - // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(rest...); -} - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest) -{ - return str.size() + concat_length(rest...); -} - -template -inline void concat_into(OutStringType& /*out*/) -{} - -template -using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); - -template -using detect_string_can_append = is_detected; - -template -using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); - -template -using detect_string_can_append_op = is_detected; - -template -using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); - -template -using detect_string_can_append_iter = is_detected; - -template -using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); - -template -using detect_string_can_append_data = is_detected; - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > = 0 > -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template::value, int> = 0> -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) -{ - out.append(std::forward(arg)); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > > -inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) -{ - out += std::forward(arg); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.begin(), arg.end()); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.data(), arg.size()); - concat_into(out, std::forward(rest)...); -} - -template -inline OutStringType concat(Args && ... args) -{ - OutStringType str; - str.reserve(concat_length(args...)); - concat_into(str, std::forward(args)...); - return str; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END // With -Wweak-vtables, Clang will complain about the exception classes as they From 512f4b415150effb991317856dfe9395f5a759b7 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 16:48:22 +0530 Subject: [PATCH 22/38] made few formatting changes in macro_scope.hpp Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 1dde8f14f2..b318100d6c 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -289,9 +289,9 @@ if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } From f6bc704f2987b2d6823add4c7b694b34b8df05b9 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 17:50:30 +0530 Subject: [PATCH 23/38] ran make amalgamate again Signed-off-by: Ash-Jose --- single_include/nlohmann/json.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9ac9871805..ebb3359b76 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2974,9 +2974,9 @@ NLOHMANN_JSON_NAMESPACE_END if (it == std::end(m)) \ { \ throw ::nlohmann::detail::type_error::create( \ - 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ - j); \ + 302, \ + concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + j); \ } \ e = it->first; \ } From d4f82893b0b13065d08b5ac7a7ac937701300c46 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 19:52:51 +0530 Subject: [PATCH 24/38] revert to std::string() concat in enum strict macro Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 3 +- single_include/nlohmann/json.hpp | 740 ++++++++++++------------ 2 files changed, 370 insertions(+), 373 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index b318100d6c..99cf5dc8ba 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -11,7 +11,6 @@ #include // declval, pair #include #include -#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -290,7 +289,7 @@ { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ j); \ } \ e = it->first; \ diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ebb3359b76..0dd155ff14 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2374,328 +2374,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // strlen -#include // string -#include // forward - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; - -template -struct Gen -{ - using type = integer_sequence; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; - -//// END OF CODE FROM GOOGLE ABSEIL - -#endif - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static JSON_INLINE_VARIABLE constexpr T value{}; -}; - -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -constexpr std::array make_array(Args&& ... args) -{ - return std::array {{static_cast(std::forward(args))...}}; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -inline std::size_t concat_length() -{ - return 0; -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest); - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest); - -template -inline std::size_t concat_length(const char /*c*/, const Args& ... rest) -{ - return 1 + concat_length(rest...); -} - -template -inline std::size_t concat_length(const char* cstr, const Args& ... rest) -{ - // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(rest...); -} - -template -inline std::size_t concat_length(const StringType& str, const Args& ... rest) -{ - return str.size() + concat_length(rest...); -} - -template -inline void concat_into(OutStringType& /*out*/) -{} - -template -using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); - -template -using detect_string_can_append = is_detected; - -template -using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); - -template -using detect_string_can_append_op = is_detected; - -template -using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); - -template -using detect_string_can_append_iter = is_detected; - -template -using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); - -template -using detect_string_can_append_data = is_detected; - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > = 0 > -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > = 0 > -inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); - -template::value, int> = 0> -inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) -{ - out.append(std::forward(arg)); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && detect_string_can_append_op::value, int > > -inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) -{ - out += std::forward(arg); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && detect_string_can_append_iter::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.begin(), arg.end()); - concat_into(out, std::forward(rest)...); -} - -template < typename OutStringType, typename Arg, typename... Args, - enable_if_t < !detect_string_can_append::value - && !detect_string_can_append_op::value - && !detect_string_can_append_iter::value - && detect_string_can_append_data::value, int > > -inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) -{ - out.append(arg.data(), arg.size()); - concat_into(out, std::forward(rest)...); -} - -template -inline OutStringType concat(Args && ... args) -{ - OutStringType str; - str.reserve(concat_length(args...)); - concat_into(str, std::forward(args)...); - return str; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -2975,7 +2653,7 @@ NLOHMANN_JSON_NAMESPACE_END { \ throw ::nlohmann::detail::type_error::create( \ 302, \ - concat("invalid value for ", #ENUM_TYPE, ": ", j.dump()), \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ j); \ } \ e = it->first; \ @@ -3484,72 +3162,244 @@ inline void replace_substring(StringType& s, const StringType& f, template inline StringType escape(StringType s) { - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +inline void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -inline void unescape(StringType& s) +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen { - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END +template +struct Gen +{ + using type = integer_sequence; +}; -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence // -// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann -// SPDX-License-Identifier: MIT +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; -#include // size_t +//// END OF CODE FROM GOOGLE ABSEIL -// #include +#endif +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail +// taken from ranges-v3 +template +struct static_const { + static JSON_INLINE_VARIABLE constexpr T value{}; +}; -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; +template +constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} } // namespace detail NLOHMANN_JSON_NAMESPACE_END -// #include - -// #include - // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ @@ -4572,6 +4422,154 @@ struct is_transparent : bool_constant()> {}; NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // strlen +#include // string +#include // forward + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +inline std::size_t concat_length() +{ + return 0; +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest); + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest); + +template +inline std::size_t concat_length(const char /*c*/, const Args& ... rest) +{ + return 1 + concat_length(rest...); +} + +template +inline std::size_t concat_length(const char* cstr, const Args& ... rest) +{ + // cppcheck-suppress ignoredReturnValue + return ::strlen(cstr) + concat_length(rest...); +} + +template +inline std::size_t concat_length(const StringType& str, const Args& ... rest) +{ + return str.size() + concat_length(rest...); +} + +template +inline void concat_into(OutStringType& /*out*/) +{} + +template +using string_can_append = decltype(std::declval().append(std::declval < Arg && > ())); + +template +using detect_string_can_append = is_detected; + +template +using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ()); + +template +using detect_string_can_append_op = is_detected; + +template +using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end())); + +template +using detect_string_can_append_iter = is_detected; + +template +using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size())); + +template +using detect_string_can_append_data = is_detected; + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > = 0 > +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > = 0 > +inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); + +template::value, int> = 0> +inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) +{ + out.append(std::forward(arg)); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && detect_string_can_append_op::value, int > > +inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) +{ + out += std::forward(arg); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && detect_string_can_append_iter::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.begin(), arg.end()); + concat_into(out, std::forward(rest)...); +} + +template < typename OutStringType, typename Arg, typename... Args, + enable_if_t < !detect_string_can_append::value + && !detect_string_can_append_op::value + && !detect_string_can_append_iter::value + && detect_string_can_append_data::value, int > > +inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) +{ + out.append(arg.data(), arg.size()); + concat_into(out, std::forward(rest)...); +} + +template +inline OutStringType concat(Args && ... args) +{ + OutStringType str; + str.reserve(concat_length(args...)); + concat_into(str, std::forward(args)...); + return str; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // With -Wweak-vtables, Clang will complain about the exception classes as they From 08f857044e00a21bf8dfa752ee18bffc3def1c2b Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 21:46:04 +0530 Subject: [PATCH 25/38] fix: include exceptions.hpp for type_error in enum strict macro Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 1 + single_include/nlohmann/json.hpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 99cf5dc8ba..97663ad4ef 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -16,6 +16,7 @@ // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them #include +#include // for type_error // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0dd155ff14..ddfa92ac4f 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2380,6 +2380,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP // #include +// #include +// for type_error // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) From 089e0bfd5d84257aec337467b01a507510731634 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 5 Nov 2025 22:56:08 +0530 Subject: [PATCH 26/38] fix: add forward declaration for type_error to avoid circular include Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 10 +++++++++- single_include/nlohmann/json.hpp | 11 +++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 97663ad4ef..21df32b3b0 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -16,7 +16,15 @@ // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them #include -#include // for type_error + +// forward declaration to avoid circular include with exceptions.hpp +namespace nlohmann +{ +namespace detail +{ +class type_error; +} // namespace detail +} // namespace nlohmann // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ddfa92ac4f..49c2602c5e 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2380,8 +2380,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP // #include -// #include -// for type_error + +// forward declaration to avoid circular include with exceptions.hpp +namespace nlohmann +{ +namespace detail +{ +class type_error; +} // namespace detail +} // namespace nlohmann // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) From 4f4ac7ffbd2753f956a35e4fd6b88854b311286b Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 00:15:43 +0530 Subject: [PATCH 27/38] fix: make NLOHMANN_JSON_SERIALIZE_ENUM_STRICT throw type_error on unknown values Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 13 ++----------- single_include/nlohmann/json.hpp | 13 ++----------- test.json | 7 +++++++ 3 files changed, 11 insertions(+), 22 deletions(-) create mode 100644 test.json diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 21df32b3b0..3f247a93ce 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -17,15 +17,6 @@ #include -// forward declaration to avoid circular include with exceptions.hpp -namespace nlohmann -{ -namespace detail -{ -class type_error; -} // namespace detail -} // namespace nlohmann - // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) #if defined(__clang__) @@ -296,10 +287,10 @@ class type_error; }); \ if (it == std::end(m)) \ { \ - throw ::nlohmann::detail::type_error::create( \ + throw nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - j); \ + &j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 49c2602c5e..8626747e7f 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2381,15 +2381,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP // #include -// forward declaration to avoid circular include with exceptions.hpp -namespace nlohmann -{ -namespace detail -{ -class type_error; -} // namespace detail -} // namespace nlohmann - // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) #if defined(__clang__) @@ -2660,10 +2651,10 @@ class type_error; }); \ if (it == std::end(m)) \ { \ - throw ::nlohmann::detail::type_error::create( \ + throw nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - j); \ + &j); \ } \ e = it->first; \ } diff --git a/test.json b/test.json new file mode 100644 index 0000000000..bc7289bc1b --- /dev/null +++ b/test.json @@ -0,0 +1,7 @@ +{ +"one" : 1, +"two" : 2 +} +{ +"three" : 3 +} \ No newline at end of file From c69f8d3343286dc2fc41861a66f707ae2375e8c2 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 00:26:03 +0530 Subject: [PATCH 28/38] minor formatting changes Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 4 ++-- single_include/nlohmann/json.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 3f247a93ce..f274f56fc2 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -287,10 +287,10 @@ }); \ if (it == std::end(m)) \ { \ - throw nlohmann::detail::type_error::create( \ + throw ::nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ + &j); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 8626747e7f..6644c10086 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2651,10 +2651,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP }); \ if (it == std::end(m)) \ { \ - throw nlohmann::detail::type_error::create( \ + throw ::nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ + &j); \ } \ e = it->first; \ } From c9b5137919f29f31c84bc66a6543db999cb69d5d Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 02:12:17 +0530 Subject: [PATCH 29/38] removed test,json which was left there by accident included string header Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 1 + test.json | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 test.json diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index f274f56fc2..651e4c3514 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -11,6 +11,7 @@ #include // declval, pair #include #include +#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them diff --git a/test.json b/test.json deleted file mode 100644 index bc7289bc1b..0000000000 --- a/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ -"one" : 1, -"two" : 2 -} -{ -"three" : 3 -} \ No newline at end of file From 97ef95f7117365332d25ce76e32a880751248837 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Thu, 6 Nov 2025 02:23:48 +0530 Subject: [PATCH 30/38] changed formatting of unit-serialize_enum_strict.cpp and amalgamated Signed-off-by: Ash-Jose --- single_include/nlohmann/json.hpp | 1 + tests/src/unit-serialize_enum_strict.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 6644c10086..3712f76642 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2374,6 +2374,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ +#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 939f79fe2b..50362ea17b 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -1,5 +1,14 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann +// SPDX-License-Identifier: MIT + #include #include "../doctest/doctest.h" + using json = nlohmann::json; namespace ns From 638ec5f52cdc6103c36256aa251c47d7c45875be Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 12 Nov 2025 17:48:40 +0530 Subject: [PATCH 31/38] aesthetic changes and included doctest_compatibility.h Signed-off-by: Ash Jose --- include/nlohmann/detail/macro_scope.hpp | 10 +++++----- single_include/nlohmann/json.hpp | 10 +++++----- tests/src/unit-serialize_enum_strict.cpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 651e4c3514..78e04c802f 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -9,9 +9,9 @@ #pragma once #include // declval, pair +#include #include #include -#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -288,10 +288,10 @@ }); \ if (it == std::end(m)) \ { \ - throw ::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ + JSON_THROW(::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ + &j)); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 3712f76642..211569b0aa 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -228,6 +228,7 @@ #include // declval, pair +#include // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ @@ -2374,7 +2375,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ -#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -2652,10 +2652,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP }); \ if (it == std::end(m)) \ { \ - throw ::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ + JSON_THROW(::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ + &j)); \ } \ e = it->first; \ } diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 50362ea17b..58fa32e2a7 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -6,8 +6,8 @@ // SPDX-FileCopyrightText: 2013-2025 Niels Lohmann // SPDX-License-Identifier: MIT +#include "doctest_compatibility.h" #include -#include "../doctest/doctest.h" using json = nlohmann::json; From 895d38e256bc3513e17f1b0274bfe10f5901486b Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 12 Nov 2025 18:04:06 +0530 Subject: [PATCH 32/38] changed position of string include in macro_scope.hpp Signed-off-by: Ash Jose --- include/nlohmann/detail/macro_scope.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 78e04c802f..401ed36498 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -8,8 +8,8 @@ #pragma once +#include #include // declval, pair -#include #include #include From ff46319602282d54048dc9a21a5c2a75eab68439 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Wed, 12 Nov 2025 18:07:21 +0530 Subject: [PATCH 33/38] amalgamated Signed-off-by: Ash Jose --- include/nlohmann/detail/macro_scope.hpp | 2 +- single_include/nlohmann/json.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 401ed36498..f783c47e16 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -8,7 +8,7 @@ #pragma once -#include +#include #include // declval, pair #include #include diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 211569b0aa..3b9254d452 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -227,8 +227,8 @@ -#include // declval, pair #include +#include // declval, pair // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ From 94ef0ce09acfc847473352446c7302a76b3e975e Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Fri, 14 Nov 2025 03:09:17 +0530 Subject: [PATCH 34/38] resolving merge conflict Signed-off-by: Ash-Jose --- tests/src/unit-serialize_enum_strict.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/src/unit-serialize_enum_strict.cpp b/tests/src/unit-serialize_enum_strict.cpp index 3eca58a33b..58fa32e2a7 100644 --- a/tests/src/unit-serialize_enum_strict.cpp +++ b/tests/src/unit-serialize_enum_strict.cpp @@ -6,13 +6,8 @@ // SPDX-FileCopyrightText: 2013-2025 Niels Lohmann // SPDX-License-Identifier: MIT -<<<<<<< HEAD #include "doctest_compatibility.h" #include -======= -#include -#include "../doctest/doctest.h" ->>>>>>> 988fdefee1963a7ab203012eb0fc425e861e08f5 using json = nlohmann::json; From d79240080255916fb009f28125208ae2075e55b6 Mon Sep 17 00:00:00 2001 From: Ashlin Jose <141202853+Ash-Jose@users.noreply.github.com> Date: Fri, 14 Nov 2025 03:26:01 +0530 Subject: [PATCH 35/38] removed merge conflicts again Signed-off-by: Ashlin Jose <141202853+Ash-Jose@users.noreply.github.com> --- include/nlohmann/detail/macro_scope.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index a9f1700fd3..5e3dd2b138 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -289,17 +289,14 @@ }); \ if (it == std::end(m)) \ { \ -<<<<<<< HEAD JSON_THROW(::nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ &j)); \ -======= throw ::nlohmann::detail::type_error::create( \ 302, \ std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ &j); \ ->>>>>>> 988fdefee1963a7ab203012eb0fc425e861e08f5 } \ e = it->first; \ } From 5944257de57d7a1c454f524c9b89b7d2a2cf922b Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Fri, 14 Nov 2025 03:34:30 +0530 Subject: [PATCH 36/38] added helper function Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 18 +++++++++--------- single_include/nlohmann/json.hpp | 21 +++++++++------------ 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 5e3dd2b138..9552a4230b 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -12,7 +12,6 @@ #include // declval, pair #include #include -#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -275,7 +274,15 @@ }); \ j = ((it != std::end(m)) ? it : std::begin(m))->second; \ } \ + /* helper for strict enum error reporting */ \ template \ + inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) \ + { \ + JSON_THROW(::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + enum_type + ": " + j.dump(), \ + &j)); \ + } \ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ { \ /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ @@ -289,14 +296,7 @@ }); \ if (it == std::end(m)) \ { \ - JSON_THROW(::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j)); \ - throw ::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ + throw_enum_error(j, #ENUM_TYPE); \ } \ e = it->first; \ } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 75f137a157..c258e244e3 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2375,7 +2375,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ -#include // This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them @@ -2639,7 +2638,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP }); \ j = ((it != std::end(m)) ? it : std::begin(m))->second; \ } \ + /* helper for strict enum error reporting */ \ template \ + inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) \ + { \ + JSON_THROW(::nlohmann::detail::type_error::create( \ + 302, \ + std::string("invalid value for ") + enum_type + ": " + j.dump(), \ + &j)); \ + } \ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ { \ /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ @@ -2653,17 +2660,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP }); \ if (it == std::end(m)) \ { \ -<<<<<<< HEAD - JSON_THROW(::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j)); \ -======= - throw ::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + #ENUM_TYPE + ": " + j.dump(), \ - &j); \ ->>>>>>> 988fdefee1963a7ab203012eb0fc425e861e08f5 + throw_enum_error(j, #ENUM_TYPE); \ } \ e = it->first; \ } From 677f5d9cb197b7404f888523a36f1b1c1bd744b6 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Fri, 14 Nov 2025 03:51:35 +0530 Subject: [PATCH 37/38] formatting and correcting the helper Signed-off-by: Ash-Jose --- include/nlohmann/detail/macro_scope.hpp | 26 ++++++++++++++----------- single_include/nlohmann/json.hpp | 26 ++++++++++++++----------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 9552a4230b..b71445e7c9 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -259,6 +259,17 @@ @def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT @since version 3.12.0 */ + +/* helper for strict enum error reporting */ +template +inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) +{ + JSON_THROW(::nlohmann::detail::type_error::create( + 302, + std::string("invalid value for ") + enum_type + ": " + j.dump(), + &j)); +} + #define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ @@ -274,15 +285,7 @@ }); \ j = ((it != std::end(m)) ? it : std::begin(m))->second; \ } \ - /* helper for strict enum error reporting */ \ template \ - inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) \ - { \ - JSON_THROW(::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + enum_type + ": " + j.dump(), \ - &j)); \ - } \ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ { \ /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ @@ -294,11 +297,12 @@ { \ return ej_pair.second == j; \ }); \ - if (it == std::end(m)) \ + if (it != std::end(m)) \ { \ - throw_enum_error(j, #ENUM_TYPE); \ + e = it->first; \ + return; \ } \ - e = it->first; \ + throw_enum_error(j, #ENUM_TYPE); \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index c258e244e3..5ed9c4a38b 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2623,6 +2623,17 @@ JSON_HEDLEY_DIAGNOSTIC_POP @def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT @since version 3.12.0 */ + +/* helper for strict enum error reporting */ +template +inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) +{ + JSON_THROW(::nlohmann::detail::type_error::create( + 302, + std::string("invalid value for ") + enum_type + ": " + j.dump(), + &j)); +} + #define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ @@ -2638,15 +2649,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP }); \ j = ((it != std::end(m)) ? it : std::begin(m))->second; \ } \ - /* helper for strict enum error reporting */ \ template \ - inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) \ - { \ - JSON_THROW(::nlohmann::detail::type_error::create( \ - 302, \ - std::string("invalid value for ") + enum_type + ": " + j.dump(), \ - &j)); \ - } \ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ { \ /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ @@ -2658,11 +2661,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP { \ return ej_pair.second == j; \ }); \ - if (it == std::end(m)) \ + if (it != std::end(m)) \ { \ - throw_enum_error(j, #ENUM_TYPE); \ + e = it->first; \ + return; \ } \ - e = it->first; \ + throw_enum_error(j, #ENUM_TYPE); \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They From 12319044db42395e8709fd58a04e79dad51fceb1 Mon Sep 17 00:00:00 2001 From: Ash-Jose Date: Fri, 14 Nov 2025 03:56:45 +0530 Subject: [PATCH 38/38] migrated helper to include/nlohmann/detail/conversions/from_json.hpp Signed-off-by: Ash-Jose Signed-off-by: Ash-Jose --- .../nlohmann/detail/conversions/from_json.hpp | 10 ++++++++++ include/nlohmann/detail/macro_scope.hpp | 10 ---------- single_include/nlohmann/json.hpp | 20 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 34270e2368..4c0aa25fa4 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -29,6 +29,16 @@ #include #include +/* helper for strict enum error reporting */ +template +inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) +{ + JSON_THROW(::nlohmann::detail::type_error::create( + 302, + std::string("invalid value for ") + enum_type + ": " + j.dump(), + &j)); +} + // include after macro_scope.hpp #ifdef JSON_HAS_CPP_17 #include // optional diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index b71445e7c9..bd4bdc6f3a 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -260,16 +260,6 @@ @since version 3.12.0 */ -/* helper for strict enum error reporting */ -template -inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) -{ - JSON_THROW(::nlohmann::detail::type_error::create( - 302, - std::string("invalid value for ") + enum_type + ": " + j.dump(), - &j)); -} - #define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 5ed9c4a38b..cafb246a00 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2624,16 +2624,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP @since version 3.12.0 */ -/* helper for strict enum error reporting */ -template -inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) -{ - JSON_THROW(::nlohmann::detail::type_error::create( - 302, - std::string("invalid value for ") + enum_type + ": " + j.dump(), - &j)); -} - #define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ @@ -4914,6 +4904,16 @@ NLOHMANN_JSON_NAMESPACE_END // #include +/* helper for strict enum error reporting */ +template +inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) +{ + JSON_THROW(::nlohmann::detail::type_error::create( + 302, + std::string("invalid value for ") + enum_type + ": " + j.dump(), + &j)); +} + // include after macro_scope.hpp #ifdef JSON_HAS_CPP_17 #include // optional