Merge pull request #1722 from t-b/fix-int64-min-issue
Fix int64 min issue
This commit is contained in:
commit
06ccd43a2a
4 changed files with 78 additions and 2 deletions
|
@ -630,7 +630,7 @@ class serializer
|
||||||
if (is_negative)
|
if (is_negative)
|
||||||
{
|
{
|
||||||
*buffer_ptr = '-';
|
*buffer_ptr = '-';
|
||||||
abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
|
abs_value = remove_sign(x);
|
||||||
|
|
||||||
// account one more byte for the minus sign
|
// account one more byte for the minus sign
|
||||||
n_chars = 1 + count_digits(abs_value);
|
n_chars = 1 + count_digits(abs_value);
|
||||||
|
@ -811,6 +811,32 @@ class serializer
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overload to make the compiler happy while it is instantiating
|
||||||
|
* dump_integer for number_unsigned_t.
|
||||||
|
* Must never be called.
|
||||||
|
*/
|
||||||
|
number_unsigned_t remove_sign(number_unsigned_t x)
|
||||||
|
{
|
||||||
|
assert(false); // LCOV_EXCL_LINE
|
||||||
|
return x; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function for dump_integer
|
||||||
|
*
|
||||||
|
* This function takes a negative signed integer and returns its absolute
|
||||||
|
* value as unsigned integer. The plus/minus shuffling is necessary as we can
|
||||||
|
* not directly remove the sign of an arbitrary signed integer as the
|
||||||
|
* absolute values of INT_MIN and INT_MAX are usually not the same. See
|
||||||
|
* #1708 for details.
|
||||||
|
*/
|
||||||
|
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
|
||||||
|
{
|
||||||
|
assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
|
||||||
|
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// the output of the serializer
|
/// the output of the serializer
|
||||||
output_adapter_t<char> o = nullptr;
|
output_adapter_t<char> o = nullptr;
|
||||||
|
|
|
@ -14267,7 +14267,7 @@ class serializer
|
||||||
if (is_negative)
|
if (is_negative)
|
||||||
{
|
{
|
||||||
*buffer_ptr = '-';
|
*buffer_ptr = '-';
|
||||||
abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
|
abs_value = remove_sign(x);
|
||||||
|
|
||||||
// account one more byte for the minus sign
|
// account one more byte for the minus sign
|
||||||
n_chars = 1 + count_digits(abs_value);
|
n_chars = 1 + count_digits(abs_value);
|
||||||
|
@ -14448,6 +14448,32 @@ class serializer
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overload to make the compiler happy while it is instantiating
|
||||||
|
* dump_integer for number_unsigned_t.
|
||||||
|
* Must never be called.
|
||||||
|
*/
|
||||||
|
number_unsigned_t remove_sign(number_unsigned_t x)
|
||||||
|
{
|
||||||
|
assert(false); // LCOV_EXCL_LINE
|
||||||
|
return x; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function for dump_integer
|
||||||
|
*
|
||||||
|
* This function takes a negative signed integer and returns its absolute
|
||||||
|
* value as unsigned integer. The plus/minus shuffling is necessary as we can
|
||||||
|
* not directly remove the sign of an arbitrary signed integer as the
|
||||||
|
* absolute values of INT_MIN and INT_MAX are usually not the same. See
|
||||||
|
* #1708 for details.
|
||||||
|
*/
|
||||||
|
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
|
||||||
|
{
|
||||||
|
assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
|
||||||
|
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// the output of the serializer
|
/// the output of the serializer
|
||||||
output_adapter_t<char> o = nullptr;
|
output_adapter_t<char> o = nullptr;
|
||||||
|
|
|
@ -1802,6 +1802,13 @@ TEST_CASE("regression tests")
|
||||||
json j = json::parse("[-9223372036854775808]");
|
json j = json::parse("[-9223372036854775808]");
|
||||||
CHECK(j.dump() == "[-9223372036854775808]");
|
CHECK(j.dump() == "[-9223372036854775808]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("issue #1708 - minimum value of int64_t can be outputted")
|
||||||
|
{
|
||||||
|
constexpr auto smallest = (std::numeric_limits<int64_t>::min)();
|
||||||
|
json j = smallest;
|
||||||
|
CHECK(j.dump() == std::to_string(smallest));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if not defined(JSON_NOEXCEPTION)
|
#if not defined(JSON_NOEXCEPTION)
|
||||||
|
|
|
@ -189,3 +189,20 @@ TEST_CASE("serialization")
|
||||||
test("[3,\"false\",false]", "[3,\\\"false\\\",false]");
|
test("[3,\"false\",false]", "[3,\\\"false\\\",false]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_TEMPLATE("serialization for extreme integer values", T, int32_t, uint32_t, int64_t, uint64_t)
|
||||||
|
{
|
||||||
|
SECTION("minimum")
|
||||||
|
{
|
||||||
|
constexpr auto minimum = (std::numeric_limits<T>::min)();
|
||||||
|
json j = minimum;
|
||||||
|
CHECK(j.dump() == std::to_string(minimum));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("maximum")
|
||||||
|
{
|
||||||
|
constexpr auto maximum = (std::numeric_limits<T>::max)();
|
||||||
|
json j = maximum;
|
||||||
|
CHECK(j.dump() == std::to_string(maximum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue