Handle large precision

This commit is contained in:
Victor Zverovich
2025-06-01 08:26:53 -07:00
parent 6332a38529
commit fc0c76a075
2 changed files with 28 additions and 5 deletions

View File

@ -2392,7 +2392,7 @@ FMT_CONSTEXPR20 auto write_fixed(OutputIt out, const DecimalFP& f,
using iterator = reserve_iterator<OutputIt>;
int exp = f.exponent + significand_size;
int size = significand_size + (s != sign::none ? 1 : 0);
long long size = significand_size + (s != sign::none ? 1 : 0);
if (f.exponent >= 0) {
// 1234e5 -> 123400000[.0+]
size += f.exponent;
@ -2466,7 +2466,7 @@ FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f,
// Write value in the exponential format.
int num_zeros = 0;
int size = significand_size + (s != sign::none ? 1 : 0);
long long size = significand_size + (s != sign::none ? 1 : 0);
if (specs.alt()) {
num_zeros = max_of(specs.precision - significand_size, 0);
size += num_zeros;

View File

@ -1095,9 +1095,6 @@ TEST(format_test, precision) {
EXPECT_THROW_MSG(
(void)fmt::format(runtime("{0:.2f}"), reinterpret_cast<void*>(0xcafe)),
format_error, "invalid format specifier");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:.{}e}"), 42.0,
fmt::detail::max_value<int>()),
format_error, "number is too big");
EXPECT_THROW_MSG(
(void)fmt::format("{:.2147483646f}", -2.2121295195081227E+304),
format_error, "number is too big");
@ -1109,6 +1106,32 @@ TEST(format_test, precision) {
EXPECT_EQ(fmt::format("{0:.6}", "123456\xad"), "123456");
}
TEST(format_test, large_precision) {
// Iterator used to abort the actual output.
struct throwing_iterator {
auto operator=(char) -> throwing_iterator& {
throw std::runtime_error("aborted");
return *this;
}
auto operator*() -> throwing_iterator& { return *this; }
auto operator++() -> throwing_iterator& { return *this; }
auto operator++(int) -> throwing_iterator { return *this; }
};
auto it = throwing_iterator();
EXPECT_THROW_MSG(fmt::format_to(it, fmt::runtime("{:#.{}}"), 1.0,
fmt::detail::max_value<int>()),
std::runtime_error, "aborted");
EXPECT_THROW_MSG(fmt::format_to(it, fmt::runtime("{:#.{}e}"), 1.0,
fmt::detail::max_value<int>() - 1),
std::runtime_error, "aborted");
EXPECT_THROW_MSG((void)fmt::format(fmt::runtime("{:.{}e}"), 42.0,
fmt::detail::max_value<int>()),
format_error, "number is too big");
}
TEST(format_test, utf8_precision) {
auto result = fmt::format("{:.4}", "caf\u00e9s"); // cafés
EXPECT_EQ(fmt::detail::compute_width(result), 4);