mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:04:59 +00:00
AK: Resolve format related circular dependencies properly.
With this commit, <AK/Format.h> has a more supportive role and isn't used directly. Essentially, there now is a public 'vformat' function ('v' for vector) which takes already type erased parameters. The name is choosen to indicate that this function behaves similar to C-style functions taking a va_list equivalent. The interface for frontend users are now 'String::formatted' and 'StringBuilder::appendff'.
This commit is contained in:
parent
3224fb7d55
commit
b7a4c4482f
8 changed files with 105 additions and 100 deletions
|
@ -27,9 +27,10 @@
|
|||
#include <AK/Format.h>
|
||||
#include <AK/GenericLexer.h>
|
||||
#include <AK/PrintfImplementation.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
|
||||
namespace AK::Detail::Format {
|
||||
namespace {
|
||||
|
||||
struct FormatSpecifier {
|
||||
StringView flags;
|
||||
|
@ -102,14 +103,11 @@ static bool parse_format_specifier(StringView input, FormatSpecifier& specifier)
|
|||
return true;
|
||||
}
|
||||
|
||||
String format(StringView fmtstr, AK::Span<TypeErasedFormatter> formatters, size_t argument_index)
|
||||
{
|
||||
StringBuilder builder;
|
||||
format(builder, fmtstr, formatters, argument_index);
|
||||
return builder.to_string();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void format(StringBuilder& builder, StringView fmtstr, AK::Span<TypeErasedFormatter> formatters, size_t argument_index)
|
||||
namespace AK {
|
||||
|
||||
void vformat(StringBuilder& builder, StringView fmtstr, AK::Span<const TypeErasedParameter> parameters, size_t argument_index)
|
||||
{
|
||||
size_t opening;
|
||||
if (!find_next_unescaped(opening, fmtstr, '{')) {
|
||||
|
@ -135,19 +133,24 @@ void format(StringBuilder& builder, StringView fmtstr, AK::Span<TypeErasedFormat
|
|||
if (specifier.index == NumericLimits<size_t>::max())
|
||||
specifier.index = argument_index++;
|
||||
|
||||
if (specifier.index >= formatters.size())
|
||||
if (specifier.index >= parameters.size())
|
||||
ASSERT_NOT_REACHED();
|
||||
|
||||
auto& formatter = formatters[specifier.index];
|
||||
if (!formatter.format(builder, formatter.parameter, specifier.flags))
|
||||
auto& parameter = parameters[specifier.index];
|
||||
if (!parameter.formatter(builder, parameter.value, specifier.flags))
|
||||
ASSERT_NOT_REACHED();
|
||||
|
||||
format(builder, fmtstr.substring_view(closing + 1), formatters, argument_index);
|
||||
vformat(builder, fmtstr.substring_view(closing + 1), parameters, argument_index);
|
||||
}
|
||||
|
||||
} // namespace AK::Detail::Format
|
||||
|
||||
namespace AK {
|
||||
bool Formatter<StringView>::parse(StringView flags)
|
||||
{
|
||||
return flags.is_empty();
|
||||
}
|
||||
void Formatter<StringView>::format(StringBuilder& builder, StringView value)
|
||||
{
|
||||
builder.append(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::parse(StringView flags)
|
||||
|
@ -159,14 +162,13 @@ bool Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::parse(StringVi
|
|||
|
||||
auto field_width = lexer.consume_while([](char ch) { return StringView { "0123456789" }.contains(ch); });
|
||||
if (field_width.length() > 0)
|
||||
this->field_width = Detail::Format::parse_number(field_width);
|
||||
this->field_width = parse_number(field_width);
|
||||
|
||||
if (lexer.consume_specific('x'))
|
||||
hexadecimal = true;
|
||||
|
||||
return lexer.is_eof();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(StringBuilder& builder, T value)
|
||||
{
|
||||
|
@ -180,8 +182,6 @@ void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(StringB
|
|||
PrintfImplementation::print_i64([&](auto, char ch) { builder.append(ch); }, bufptr, value, false, zero_pad, field_width);
|
||||
}
|
||||
|
||||
template struct Formatter<StringView>;
|
||||
template struct Formatter<String>;
|
||||
template struct Formatter<unsigned char, void>;
|
||||
template struct Formatter<unsigned short, void>;
|
||||
template struct Formatter<unsigned int, void>;
|
||||
|
@ -192,8 +192,6 @@ template struct Formatter<short, void>;
|
|||
template struct Formatter<int, void>;
|
||||
template struct Formatter<long, void>;
|
||||
template struct Formatter<long long, void>;
|
||||
|
||||
// C++ is weird.
|
||||
template struct Formatter<signed char, void>;
|
||||
|
||||
} // namespace AK
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue