1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 09:24:57 +00:00

AK+Format: Support all format specifiers for strings.

The following is now possible:

    outf("{:.4}", "abcdef"); // abcd
    outf("{:*<8}", "abcdef"); // abcdef**
This commit is contained in:
asynts 2020-09-29 13:55:58 +02:00 committed by Andreas Kling
parent c0d9daadb0
commit 71b7ef0992
3 changed files with 58 additions and 9 deletions

View file

@ -300,24 +300,65 @@ void StandardFormatter::parse(FormatterContext& context)
ASSERT(parser.is_eof());
}
void Formatter<StringView>::format(StringBuilder& builder, StringView value, FormatterContext&)
void Formatter<StringView>::format(StringBuilder& builder, StringView value, FormatterContext& context)
{
if (m_align != Align::Default)
TODO();
if (m_sign != Sign::Default)
ASSERT_NOT_REACHED();
if (m_alternative_form)
ASSERT_NOT_REACHED();
if (m_zero_pad)
ASSERT_NOT_REACHED();
if (m_width != value_not_set)
TODO();
if (m_precision != value_not_set)
TODO();
if (m_mode != Mode::Default && m_mode != Mode::String)
ASSERT_NOT_REACHED();
if (m_width != value_not_set && m_precision != value_not_set)
ASSERT_NOT_REACHED();
builder.append(value);
if (m_align == Align::Default)
m_align = Align::Left;
const auto width = decode_value(m_width, context);
const auto precision = decode_value(m_precision, context);
const auto put_padding = [&](size_t amount, char fill) {
for (size_t i = 0; i < amount; ++i)
builder.append(fill);
};
const auto put_bytes = [&](ReadonlyBytes bytes) {
for (size_t i = 0; i < bytes.size(); ++i)
builder.append(static_cast<char>(bytes[i]));
};
auto used_by_string = value.length();
if (precision != value_not_set)
used_by_string = min(used_by_string, precision);
const auto used_by_padding = width < used_by_string ? 0 : width - used_by_string;
if (m_align == Align::Left) {
const auto used_by_right_padding = used_by_padding;
put_bytes(value.bytes().trim(used_by_string));
put_padding(used_by_right_padding, m_fill);
return;
}
if (m_align == Align::Center) {
const auto used_by_left_padding = used_by_padding / 2;
const auto used_by_right_padding = ceil_div<size_t, size_t>(used_by_padding, 2);
put_padding(used_by_left_padding, m_fill);
put_bytes(value.bytes().trim(used_by_string));
put_padding(used_by_right_padding, m_fill);
return;
}
if (m_align == Align::Right) {
const auto used_by_left_padding = used_by_padding;
put_padding(used_by_left_padding, m_fill);
put_bytes(value.bytes().trim(used_by_string));
return;
}
ASSERT_NOT_REACHED();
}
template<typename T>