diff --git a/include/boost/charconv/detail/dragonbox/floff.hpp b/include/boost/charconv/detail/dragonbox/floff.hpp index 8eaaffd8..f67ce829 100644 --- a/include/boost/charconv/detail/dragonbox/floff.hpp +++ b/include/boost/charconv/detail/dragonbox/floff.hpp @@ -1764,7 +1764,7 @@ BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision, const auto initial_digits = static_cast(prod >> 32); - buffer -= (initial_digits < 10 && buffer != first ? 1 : 0); + buffer -= (initial_digits < 10 && buffer != first && precision != 0 ? 1 : 0); remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0)); // Avoid the situation where we have a leading 0 that we don't need diff --git a/include/boost/charconv/detail/ryu/ryu_generic_128.hpp b/include/boost/charconv/detail/ryu/ryu_generic_128.hpp index 2047d9a7..054039fe 100644 --- a/include/boost/charconv/detail/ryu/ryu_generic_128.hpp +++ b/include/boost/charconv/detail/ryu/ryu_generic_128.hpp @@ -436,14 +436,18 @@ static inline int generic_to_chars_fixed(const struct floating_decimal_128 v, ch { current_len = static_cast(shift_width) + precision; } + else + { + current_len = static_cast(shift_width) - 1; + } precision = 0; - // Since we wrote additional characters into the buffer we need to add a null terminator, + // Since we wrote additional characters into the buffer, we need to add a null terminator, // so they are not read const auto round_val = result[current_len]; result[current_len] = '\0'; - // More complicated rounding situations like 9999.999999 are already handled + // More complicated rounding situations like 9999.999999 are already handled, // so we don't need to worry about rounding past the decimal point if (round_val >= '5') { diff --git a/test/Jamfile b/test/Jamfile index e542ed77..8c6f6c98 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -75,3 +75,4 @@ run github_issue_267.cpp ; run github_issue_280.cpp ; run github_issue_282.cpp ; run github_issue_int128_320.cpp ; +run github_issue_296.cpp ; diff --git a/test/github_issue_296.cpp b/test/github_issue_296.cpp new file mode 100644 index 00000000..c75a5278 --- /dev/null +++ b/test/github_issue_296.cpp @@ -0,0 +1,67 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// See: https://github.com/boostorg/charconv/issues/296 + +#include +#include + +template +void test() +{ + const T value = -125.125; + + char buffer[64]; + const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, boost::charconv::chars_format::fixed, 0); + BOOST_TEST(r); + *r.ptr = '\0'; + + BOOST_TEST_CSTR_EQ(buffer, "-125"); +} + +template +void test_pos() +{ + const T value = 125.125; + + char buffer[64]; + const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, boost::charconv::chars_format::fixed, 0); + BOOST_TEST(r); + *r.ptr = '\0'; + + BOOST_TEST_CSTR_EQ(buffer, "125"); +} + +template +void test_prec_1() +{ + const T value = -125.125; + + char buffer[64]; + const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, boost::charconv::chars_format::fixed, 1); + BOOST_TEST(r); + *r.ptr = '\0'; + + BOOST_TEST_CSTR_EQ(buffer, "-125.1"); +} + +int main() +{ + test(); + test(); + + test_pos(); + test_pos(); + + test_prec_1(); + test_prec_1(); + + #if !defined(BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE) && BOOST_CHARCONV_LDBL_BITS < 128 + test(); + test_pos(); + test_prec_1(); + #endif + + return boost::report_errors(); +}