1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 05:17:34 +00:00

AK: Add Formatter<FormatString> as helper class.

This commit is contained in:
asynts 2021-01-09 01:00:22 +01:00 committed by Andreas Kling
parent 9a842ec419
commit 1160817a9e
13 changed files with 64 additions and 94 deletions

View file

@ -521,6 +521,11 @@ void Formatter<StringView>::format(FormatBuilder& builder, StringView value)
builder.put_string(value, m_align, m_width.value(), m_precision.value(), m_fill); builder.put_string(value, m_align, m_width.value(), m_precision.value(), m_fill);
} }
void Formatter<FormatString>::vformat(FormatBuilder& builder, StringView fmtstr, TypeErasedFormatParams params)
{
return Formatter<String>::format(builder, String::vformatted(fmtstr, params));
}
template<typename T> template<typename T>
void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(FormatBuilder& builder, T value) void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(FormatBuilder& builder, T value)
{ {

View file

@ -359,7 +359,7 @@ struct Formatter<std::nullptr_t> : Formatter<FlatPtr> {
} }
}; };
void vformat(StringBuilder& builder, StringView fmtstr, TypeErasedFormatParams); void vformat(StringBuilder&, StringView fmtstr, TypeErasedFormatParams);
void vformat(const LogStream& stream, StringView fmtstr, TypeErasedFormatParams); void vformat(const LogStream& stream, StringView fmtstr, TypeErasedFormatParams);
#ifndef KERNEL #ifndef KERNEL
@ -435,6 +435,20 @@ template<typename T>
struct Formatter<FormatIfSupported<T>> : __FormatIfSupported<T, HasFormatter<T>::value> { struct Formatter<FormatIfSupported<T>> : __FormatIfSupported<T, HasFormatter<T>::value> {
}; };
// This is a helper class, the idea is that if you want to implement a formatter you can inherit
// from this class to "break down" the formatting.
struct FormatString {
};
template<>
struct Formatter<FormatString> : Formatter<String> {
template<typename... Parameters>
void format(FormatBuilder& builder, StringView fmtstr, const Parameters&... parameters)
{
vformat(builder, fmtstr, VariadicFormatParams { parameters... });
}
void vformat(FormatBuilder& builder, StringView fmtstr, TypeErasedFormatParams params);
};
} // namespace AK } // namespace AK
#ifndef KERNEL #ifndef KERNEL
@ -448,3 +462,4 @@ using AK::warnln;
using AK::dbgln; using AK::dbgln;
using AK::FormatIfSupported; using AK::FormatIfSupported;
using AK::FormatString;

View file

@ -274,4 +274,20 @@ TEST_CASE(format_nullptr)
EXPECT_EQ(String::formatted("{}", nullptr), String::formatted("{:p}", static_cast<FlatPtr>(0))); EXPECT_EQ(String::formatted("{}", nullptr), String::formatted("{:p}", static_cast<FlatPtr>(0)));
} }
struct C {
int i;
};
template<>
struct AK::Formatter<C> : AK::Formatter<FormatString> {
void format(FormatBuilder& builder, C c)
{
return AK::Formatter<FormatString>::format(builder, "C(i={})", c.i);
}
};
TEST_CASE(use_format_string_formatter)
{
EXPECT_EQ(String::formatted("{:*<10}", C { 42 }), "C(i=42)***");
}
TEST_MAIN(Format) TEST_MAIN(Format)

View file

@ -206,7 +206,6 @@ set(KERNEL_SOURCES
VM/Region.cpp VM/Region.cpp
VM/SharedInodeVMObject.cpp VM/SharedInodeVMObject.cpp
VM/VMObject.cpp VM/VMObject.cpp
VirtualAddress.cpp
WaitQueue.cpp WaitQueue.cpp
init.cpp init.cpp
kprintf.cpp kprintf.cpp

View file

@ -1,36 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <AK/String.h>
#include <Kernel/VirtualAddress.h>
namespace AK {
void Formatter<VirtualAddress>::format(FormatBuilder& builder, const VirtualAddress& value)
{
Formatter<StringView>::format(builder, String::formatted("V{:p}", value.get()));
}
}

View file

@ -76,11 +76,10 @@ inline const LogStream& operator<<(const LogStream& stream, VirtualAddress value
return stream << 'V' << value.as_ptr(); return stream << 'V' << value.as_ptr();
} }
namespace AK {
template<> template<>
struct Formatter<VirtualAddress> : Formatter<StringView> { struct AK::Formatter<VirtualAddress> : AK::Formatter<FormatString> {
void format(FormatBuilder&, const VirtualAddress&); void format(FormatBuilder& builder, const VirtualAddress& value)
{
return AK::Formatter<FormatString>::format(builder, "V{}", value.as_ptr());
}
}; };
}

View file

@ -268,12 +268,3 @@ const LogStream& operator<<(const LogStream& stream, const Object& object)
} }
} }
namespace AK {
void Formatter<Core::Object>::format(FormatBuilder& builder, const Core::Object& value)
{
Formatter<StringView>::format(builder, String::formatted("{}({})", value.class_name(), &value));
}
}

View file

@ -173,12 +173,13 @@ private:
} }
namespace AK {
template<> template<>
struct Formatter<Core::Object> : Formatter<StringView> { struct AK::Formatter<Core::Object> : AK::Formatter<FormatString> {
void format(FormatBuilder&, const Core::Object&); void format(FormatBuilder& builder, const Core::Object& value)
{
return AK::Formatter<FormatString>::format(builder, "{}({})", value.class_name(), &value);
}
}; };
}
namespace Core { namespace Core {
template<typename T, typename Callback> template<typename T, typename Callback>

View file

@ -47,17 +47,3 @@ const LogStream& operator<<(const LogStream& stream, const ModelIndex& value)
} }
} }
namespace AK {
void Formatter<GUI::ModelIndex>::format(FormatBuilder& builder, const GUI::ModelIndex& value)
{
Formatter<StringView> formatter { *this };
if (value.internal_data())
formatter.format(builder, String::formatted("ModelIndex({},{},{:p})", value.row(), value.column(), value.internal_data()));
else
formatter.format(builder, String::formatted("ModelIndex({},{})", value.row(), value.column()));
}
}

View file

@ -82,8 +82,14 @@ const LogStream& operator<<(const LogStream&, const ModelIndex&);
namespace AK { namespace AK {
template<> template<>
struct Formatter<GUI::ModelIndex> : Formatter<StringView> { struct Formatter<GUI::ModelIndex> : Formatter<FormatString> {
void format(FormatBuilder&, const GUI::ModelIndex&); void format(FormatBuilder& builder, const GUI::ModelIndex& value)
{
if (value.internal_data())
return Formatter<FormatString>::format(builder, "ModelIndex({},{},{})", value.row(), value.column(), value.internal_data());
else
return Formatter<FormatString>::format(builder, "ModelIndex({},{})", value.row(), value.column());
}
}; };
template<> template<>

View file

@ -66,17 +66,13 @@ inline const LogStream& operator<<(const LogStream& stream, const TextPosition&
} }
namespace AK {
template<> template<>
struct Formatter<GUI::TextPosition> : Formatter<StringView> { struct AK::Formatter<GUI::TextPosition> : AK::Formatter<FormatString> {
void format(FormatBuilder& builder, const GUI::TextPosition& value) void format(FormatBuilder& builder, const GUI::TextPosition& value)
{ {
if (value.is_valid()) if (value.is_valid())
Formatter<StringView>::format(builder, String::formatted("({},{})", value.line(), value.column())); Formatter<FormatString>::format(builder, "({},{})", value.line(), value.column());
else else
Formatter<StringView>::format(builder, "GUI::TextPosition(Invalid)"); Formatter<FormatString>::format(builder, "GUI::TextPosition(Invalid)");
} }
}; };
}

View file

@ -94,17 +94,13 @@ inline const LogStream& operator<<(const LogStream& stream, const TextRange& val
} }
namespace AK {
template<> template<>
struct Formatter<GUI::TextRange> : Formatter<StringView> { struct AK::Formatter<GUI::TextRange> : AK::Formatter<FormatString> {
void format(FormatBuilder& builder, const GUI::TextRange& value) void format(FormatBuilder& builder, const GUI::TextRange& value)
{ {
if (value.is_valid()) if (value.is_valid())
Formatter<StringView>::format(builder, String::formatted("{}-{}", value.start(), value.end())); return Formatter<FormatString>::format(builder, "{}-{}", value.start(), value.end());
else else
Formatter<StringView>::format(builder, "GUI::TextRange(Invalid)"); return Formatter<FormatString>::format(builder, "GUI::TextRange(Invalid)");
} }
}; };
}

View file

@ -75,17 +75,13 @@ private:
} }
namespace AK {
template<> template<>
struct Formatter<JS::Cell> : Formatter<StringView> { struct AK::Formatter<JS::Cell> : AK::Formatter<FormatString> {
void format(FormatBuilder& builder, const JS::Cell* cell) void format(FormatBuilder& builder, const JS::Cell* cell)
{ {
if (!cell) if (!cell)
Formatter<StringView>::format(builder, "Cell{nullptr}"); Formatter<FormatString>::format(builder, "Cell{nullptr}");
else else
Formatter<StringView>::format(builder, String::formatted("{}{{{}}}", cell->class_name(), static_cast<const void*>(cell))); Formatter<FormatString>::format(builder, "{}({})", cell->class_name(), cell);
} }
}; };
}