mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
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:
1 parent
7641d1cb0e
commit
0edf35889a
3 files changed
+31
-5
No files matched your search
@@ -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
|
||||
|
||||
@@ -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") }));
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user