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)
 | 
			
		||||
        {
 | 
			
		||||
            *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
 | 
			
		||||
            n_chars = 1 + count_digits(abs_value);
 | 
			
		||||
| 
						 | 
				
			
			@ -811,6 +811,32 @@ class serializer
 | 
			
		|||
        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:
 | 
			
		||||
    /// the output of the serializer
 | 
			
		||||
    output_adapter_t<char> o = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14267,7 +14267,7 @@ class serializer
 | 
			
		|||
        if (is_negative)
 | 
			
		||||
        {
 | 
			
		||||
            *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
 | 
			
		||||
            n_chars = 1 + count_digits(abs_value);
 | 
			
		||||
| 
						 | 
				
			
			@ -14448,6 +14448,32 @@ class serializer
 | 
			
		|||
        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:
 | 
			
		||||
    /// the output of the serializer
 | 
			
		||||
    output_adapter_t<char> o = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1802,6 +1802,13 @@ TEST_CASE("regression tests")
 | 
			
		|||
        json j = json::parse("[-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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -189,3 +189,20 @@ TEST_CASE("serialization")
 | 
			
		|||
        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…
	
	Add table
		Add a link
		
	
		Reference in a new issue