AK+printf: Add support for formatting long double

This shares the same implementation as the double formatter, so it has
all the same limitations :^)
This commit is contained in:
Lucas Chollet committed 2026-08-30 21:52:53 +02:00
1 parent 7641d1cb0e
commit 0edf35889a
3 files changed
+31 -5

No files matched your search

+9 -5
View File
@@ -164,7 +164,7 @@ ALWAYS_INLINE int print_decimal(PutChFunc putch, CharType*& bufptr, u64 number,
}
#ifndef KERNEL
template<typename PutChFunc, typename CharType>
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)
ALWAYS_INLINE int print_double(PutChFunc putch, CharType*& bufptr, long double number, bool always_sign, bool left_pad, bool zero_pad, u32 field_width, u32 precision, bool trailing_zeros)
{
int length = 0;
@@ -329,10 +329,10 @@ struct ModifierState {
unsigned precision { 6 };
unsigned short_qualifiers { 0 }; // TODO: Unimplemented.
unsigned long_qualifiers { 0 };
bool intmax_qualifier { false }; // TODO: Unimplemented.
bool ptrdiff_qualifier { false }; // TODO: Unimplemented.
bool long_double_qualifier { false }; // TODO: Unimplemented.
bool size_qualifier { false }; // TODO: Unimplemented.
bool intmax_qualifier { false }; // TODO: Unimplemented.
bool ptrdiff_qualifier { false }; // TODO: Unimplemented.
bool long_double_qualifier { false };
bool size_qualifier { false }; // TODO: Unimplemented.
bool alternate_form { 0 };
bool always_sign { false };
};
@@ -404,10 +404,14 @@ struct PrintfImpl {
ALWAYS_INLINE int format_g(ModifierState const& state, ArgumentListRefT ap) const
{
// FIXME: Exponent notation
if (state.long_double_qualifier)
return print_double(m_putch, m_bufptr, NextArgument<long double>()(ap), state.always_sign, state.left_pad, state.zero_pad, state.field_width, state.precision, false);
return print_double(m_putch, m_bufptr, NextArgument<double>()(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
{
if (state.long_double_qualifier)
return print_double(m_putch, m_bufptr, NextArgument<long double>()(ap), state.always_sign, state.left_pad, state.zero_pad, state.field_width, state.precision, true);
return print_double(m_putch, m_bufptr, NextArgument<double>()(ap), state.always_sign, state.left_pad, state.zero_pad, state.field_width, state.precision, true);
}
#endif
+9
View File
@@ -362,4 +362,13 @@ TEST_CASE(g_format)
EXPECT(test_single<double>({ LITERAL("xxxxxxxx"), "|%g|", -1.12, 7, LITERAL("|-1.12|\0") }));
EXPECT(test_single<double>({ LITERAL("xxxxx"), "|%g|", 10.0000001, 4, LITERAL("|10|\0") }));
EXPECT(test_single<double>({ LITERAL("xxxxx"), "|%g|", 10.0000000001, 4, LITERAL("|10|\0") }));
EXPECT(test_single<long double>({ LITERAL("xxxxx"), "|%Lg|", 10L, 4, LITERAL("|10|\0") }));
EXPECT(test_single<long double>({ LITERAL("xxxxxx"), "|%Lg|", -10L, 5, LITERAL("|-10|\0") }));
}
TEST_CASE(f_format)
{
EXPECT(test_single<long double>({ LITERAL("xxxxxxxxxxxx"), "|%Lf|", 10L, 11, LITERAL("|10.000000|\0") }));
EXPECT(test_single<long double>({ LITERAL("xxxxxxxxxxxxx"), "|%Lf|", -10L, 12, LITERAL("|-10.000000|\0") }));
}
+13
View File
@@ -220,6 +220,19 @@ struct ArgvNextArgument<double, V> {
}
};
template<typename V>
struct ArgvNextArgument<long double, V> {
ALWAYS_INLINE long double operator()(V arg) const
{
if (arg.argc == 0)
return 0;
auto result = *arg.argv++;
--arg.argc;
return strtold(result, nullptr);
}
};
template<typename V>
struct ArgvNextArgument<int*, V> {
ALWAYS_INLINE int* operator()(V) const