mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:57:45 +00:00
AK: Support long doubles in format strings
This commit is contained in:
parent
f4072a5038
commit
8ed3315dec
2 changed files with 91 additions and 0 deletions
|
@ -380,6 +380,53 @@ void FormatBuilder::put_f64(
|
||||||
|
|
||||||
put_string(string_builder.string_view(), align, min_width, NumericLimits<size_t>::max(), fill);
|
put_string(string_builder.string_view(), align, min_width, NumericLimits<size_t>::max(), fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormatBuilder::put_f80(
|
||||||
|
long double value,
|
||||||
|
u8 base,
|
||||||
|
bool upper_case,
|
||||||
|
Align align,
|
||||||
|
size_t min_width,
|
||||||
|
size_t precision,
|
||||||
|
char fill,
|
||||||
|
SignMode sign_mode)
|
||||||
|
{
|
||||||
|
StringBuilder string_builder;
|
||||||
|
FormatBuilder format_builder { string_builder };
|
||||||
|
|
||||||
|
bool is_negative = value < 0.0;
|
||||||
|
if (is_negative)
|
||||||
|
value = -value;
|
||||||
|
|
||||||
|
format_builder.put_u64(static_cast<u64>(value), base, false, upper_case, false, Align::Right, 0, ' ', sign_mode, is_negative);
|
||||||
|
|
||||||
|
if (precision > 0) {
|
||||||
|
// FIXME: This is a terrible approximation but doing it properly would be a lot of work. If someone is up for that, a good
|
||||||
|
// place to start would be the following video from CppCon 2019:
|
||||||
|
// https://youtu.be/4P_kbF0EbZM (Stephan T. Lavavej “Floating-Point <charconv>: Making Your Code 10x Faster With C++17's Final Boss”)
|
||||||
|
value -= static_cast<i64>(value);
|
||||||
|
|
||||||
|
long double epsilon = 0.5;
|
||||||
|
for (size_t i = 0; i < precision; ++i)
|
||||||
|
epsilon /= 10.0;
|
||||||
|
|
||||||
|
size_t visible_precision = 0;
|
||||||
|
for (; visible_precision < precision; ++visible_precision) {
|
||||||
|
if (value - static_cast<i64>(value) < epsilon)
|
||||||
|
break;
|
||||||
|
value *= 10.0;
|
||||||
|
epsilon *= 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visible_precision > 0) {
|
||||||
|
string_builder.append('.');
|
||||||
|
format_builder.put_u64(static_cast<u64>(value), base, false, upper_case, true, Align::Right, visible_precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
put_string(string_builder.string_view(), align, min_width, NumericLimits<size_t>::max(), fill);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void FormatBuilder::put_hexdump(ReadonlyBytes bytes, size_t width, char fill)
|
void FormatBuilder::put_hexdump(ReadonlyBytes bytes, size_t width, char fill)
|
||||||
|
@ -608,6 +655,29 @@ void Formatter<bool>::format(FormatBuilder& builder, bool value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef KERNEL
|
#ifndef KERNEL
|
||||||
|
void Formatter<long double>::format(FormatBuilder& builder, long double value)
|
||||||
|
{
|
||||||
|
u8 base;
|
||||||
|
bool upper_case;
|
||||||
|
if (m_mode == Mode::Default || m_mode == Mode::Float) {
|
||||||
|
base = 10;
|
||||||
|
upper_case = false;
|
||||||
|
} else if (m_mode == Mode::Hexfloat) {
|
||||||
|
base = 16;
|
||||||
|
upper_case = false;
|
||||||
|
} else if (m_mode == Mode::HexfloatUppercase) {
|
||||||
|
base = 16;
|
||||||
|
upper_case = true;
|
||||||
|
} else {
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_width = m_width.value_or(0);
|
||||||
|
m_precision = m_precision.value_or(6);
|
||||||
|
|
||||||
|
builder.put_f80(value, base, upper_case, m_align, m_width.value(), m_precision.value(), m_fill, m_sign_mode);
|
||||||
|
}
|
||||||
|
|
||||||
void Formatter<double>::format(FormatBuilder& builder, double value)
|
void Formatter<double>::format(FormatBuilder& builder, double value)
|
||||||
{
|
{
|
||||||
u8 base;
|
u8 base;
|
||||||
|
|
21
AK/Format.h
21
AK/Format.h
|
@ -185,6 +185,16 @@ public:
|
||||||
SignMode sign_mode = SignMode::OnlyIfNeeded);
|
SignMode sign_mode = SignMode::OnlyIfNeeded);
|
||||||
|
|
||||||
#ifndef KERNEL
|
#ifndef KERNEL
|
||||||
|
void put_f80(
|
||||||
|
long double value,
|
||||||
|
u8 base = 10,
|
||||||
|
bool upper_case = false,
|
||||||
|
Align align = Align::Right,
|
||||||
|
size_t min_width = 0,
|
||||||
|
size_t precision = 6,
|
||||||
|
char fill = ' ',
|
||||||
|
SignMode sign_mode = SignMode::OnlyIfNeeded);
|
||||||
|
|
||||||
void put_f64(
|
void put_f64(
|
||||||
double value,
|
double value,
|
||||||
u8 base = 10,
|
u8 base = 10,
|
||||||
|
@ -397,6 +407,17 @@ struct Formatter<double> : StandardFormatter {
|
||||||
|
|
||||||
void format(FormatBuilder&, double value);
|
void format(FormatBuilder&, double value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Formatter<long double> : StandardFormatter {
|
||||||
|
Formatter() = default;
|
||||||
|
explicit Formatter(StandardFormatter formatter)
|
||||||
|
: StandardFormatter(formatter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void format(FormatBuilder&, long double value);
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue