mirror of
https://github.com/nlohmann/json.git
synced 2026-10-16 11:17:13 +00:00
Allow the same type for number_integer_t and number_unsigned_t (#5815)
* Allow the same type for number_integer_t and number_unsigned_t basic_json did not compile with NumberUnsignedType == NumberIntegerType because overloads on both types collided. Such a basic_json now stores every integer as number_integer: the colliding overloads take a placeholder type, unsigned C++ integers are converted to number_integer_t, and value_t::number_unsigned maps to number_integer. Also fixes two problems this configuration would hit: the unsigned integer parser accepted values that wrap around to negative numbers, and dump() overflowed when computing the absolute value of the minimum. A repeated NumberFloatType gets a static_assert. Refs #2573 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Use json::with_integers_t in the test and the docs Signed-off-by: Niels Lohmann <mail@nlohmann.me> * ✅ skip patch test on GCC 5 to avoid internal compiler error Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix CI: name the unsigned overload type through template parameters basic_json used number_unsigned_overload_t<basic_json> while the class was still incomplete. MSVC rejected it as a recursive alias declaration and GCC 4.9, 5 and 7 crashed with an internal compiler error. basic_json now uses number_unsigned_overload_type<NumberIntegerType, NumberUnsignedType>, which also makes the GCC 5 workaround in the patch test unnecessary. Infer reported a null dereference for the number_unsigned case in from_json, which cannot happen for a basic_json whose number_unsigned_t is number_integer_t; assert it. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Address review: conjunction/negation trait, astyle-friendly alias, docs table order Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 parent
6261d1e432
commit
ce28c722bc
13 files changed
+460
-92
No files matched your search
@@ -19,7 +19,7 @@
|
||||
#include <cstring> // memcpy
|
||||
#include <limits> // numeric_limits
|
||||
#include <string> // string
|
||||
#include <type_traits> // conditional, integral_constant, true_type, false_type
|
||||
#include <type_traits> // conditional, integral_constant, is_signed, true_type, false_type
|
||||
#include <utility> // move
|
||||
|
||||
#include <nlohmann/detail/bit_ops.hpp>
|
||||
@@ -50,6 +50,20 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// whether an integer of a signed type is negative; the overload for other types
|
||||
// avoids comparing an unsigned value with zero
|
||||
template<typename NumberType>
|
||||
constexpr bool is_negative_integer(NumberType x, std::true_type /*is_signed*/) noexcept
|
||||
{
|
||||
return x < 0;
|
||||
}
|
||||
|
||||
template<typename NumberType>
|
||||
constexpr bool is_negative_integer(NumberType /*unused*/, std::false_type /*is_signed*/) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief fast integer parser for an already-validated unsigned integer
|
||||
|
||||
@@ -83,8 +97,10 @@ bool parse_integer_unsigned(const char* first, const char* last, NumberUnsignedT
|
||||
x = (x * 10u) + digit;
|
||||
}
|
||||
value = static_cast<NumberUnsignedType>(x);
|
||||
// reject values that do not round-trip into a narrower NumberUnsignedType
|
||||
return static_cast<std::uint64_t>(value) == x;
|
||||
// reject values that do not round-trip into a narrower NumberUnsignedType,
|
||||
// and values that wrap around to negative numbers if it is a signed type
|
||||
// (number_unsigned_t may be the same type as number_integer_t, #2573)
|
||||
return static_cast<std::uint64_t>(value) == x && !is_negative_integer(value, std::is_signed<NumberUnsignedType>());
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
Reference in new issue
Block a user