diff --git a/AK/PrintfImplementation.h b/AK/PrintfImplementation.h index e67f480c59e..a1cd9243b07 100644 --- a/AK/PrintfImplementation.h +++ b/AK/PrintfImplementation.h @@ -164,7 +164,7 @@ ALWAYS_INLINE int print_decimal(PutChFunc putch, CharType*& bufptr, u64 number, } #ifndef KERNEL template -ALWAYS_INLINE int print_double(PutChFunc putch, CharType*& bufptr, double number, bool always_sign, bool left_pad, bool zero_pad, u32 field_width, u32 precision) +ALWAYS_INLINE int print_double(PutChFunc putch, CharType*& bufptr, double number, bool always_sign, bool left_pad, bool zero_pad, u32 field_width, u32 precision, bool trailing_zeros) { int length = 0; @@ -200,14 +200,22 @@ ALWAYS_INLINE int print_double(PutChFunc putch, CharType*& bufptr, double number length = print_decimal(putch, bufptr, (i64)number, sign, always_sign, left_pad, zero_pad, whole_width, false, 1); if (precision > 0) { - putch(bufptr, '.'); - length++; double fraction = number - (i64)number; for (u32 i = 0; i < precision; ++i) fraction = fraction * 10; + if (trailing_zeros || fraction) { + length++; + putch(bufptr, '.'); - return length + print_decimal(putch, bufptr, (i64)fraction, false, false, false, true, precision, false, 1); + i64 ifraction = fraction; + while (!trailing_zeros && ifraction % 10 == 0) { + ifraction /= 10; + precision--; + } + + return length + print_decimal(putch, bufptr, ifraction, false, false, false, true, precision, false, 1); + } } return length; @@ -393,11 +401,12 @@ struct PrintfImpl { #ifndef KERNEL ALWAYS_INLINE int format_g(ModifierState const& state, ArgumentListRefT ap) const { - return format_f(state, ap); + // FIXME: Exponent notation + return print_double(m_putch, m_bufptr, NextArgument()(ap), state.always_sign, state.left_pad, state.zero_pad, state.field_width, state.precision, false); } ALWAYS_INLINE int format_f(ModifierState const& state, ArgumentListRefT ap) const { - return print_double(m_putch, m_bufptr, NextArgument()(ap), state.always_sign, state.left_pad, state.zero_pad, state.field_width, state.precision); + return print_double(m_putch, m_bufptr, NextArgument()(ap), state.always_sign, state.left_pad, state.zero_pad, state.field_width, state.precision, true); } #endif ALWAYS_INLINE int format_o(ModifierState const& state, ArgumentListRefT ap) const diff --git a/Tests/LibC/TestSnprintf.cpp b/Tests/LibC/TestSnprintf.cpp index a22d675b2e1..055a64b37c0 100644 --- a/Tests/LibC/TestSnprintf.cpp +++ b/Tests/LibC/TestSnprintf.cpp @@ -325,3 +325,11 @@ TEST_CASE(truncation) EXPECT(test_single({ LITERAL("xxxxxxxxxxxxxxxxxxx"), "|%llx|", ULLONG_MAX, 18, LITERAL("|ffffffffffffffff|\0") })); EXPECT(test_single({ LITERAL("xxxxxxxxxxxxxxxxxxx"), "|%llX|", ULLONG_MAX, 18, LITERAL("|FFFFFFFFFFFFFFFF|\0") })); } + +TEST_CASE(g_format) +{ + EXPECT(test_single({ LITERAL("xxxx"), "|%g|", 0.0, 3, LITERAL("|0|\0") })); + EXPECT(test_single({ LITERAL("xxxx"), "|%g|", 1.0, 3, LITERAL("|1|\0") })); + EXPECT(test_single({ LITERAL("xxxxxx"), "|%g|", 1.1, 5, LITERAL("|1.1|\0") })); + EXPECT(test_single({ LITERAL("xxxxxxxx"), "|%g|", -1.12, 7, LITERAL("|-1.12|\0") })); +}