summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AK/Format.cpp5
-rw-r--r--AK/Format.h17
-rw-r--r--AK/Tests/TestFormat.cpp16
-rw-r--r--Kernel/CMakeLists.txt1
-rw-r--r--Kernel/VirtualAddress.cpp36
-rw-r--r--Kernel/VirtualAddress.h11
-rw-r--r--Libraries/LibCore/Object.cpp9
-rw-r--r--Libraries/LibCore/Object.h9
-rw-r--r--Libraries/LibGUI/ModelIndex.cpp14
-rw-r--r--Libraries/LibGUI/ModelIndex.h10
-rw-r--r--Libraries/LibGUI/TextPosition.h10
-rw-r--r--Libraries/LibGUI/TextRange.h10
-rw-r--r--Libraries/LibJS/Runtime/Cell.h10
13 files changed, 64 insertions, 94 deletions
diff --git a/AK/Format.cpp b/AK/Format.cpp
index 14ed0459dd..0132807ed4 100644
--- a/AK/Format.cpp
+++ b/AK/Format.cpp
@@ -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);
}
+void Formatter<FormatString>::vformat(FormatBuilder& builder, StringView fmtstr, TypeErasedFormatParams params)
+{
+ return Formatter<String>::format(builder, String::vformatted(fmtstr, params));
+}
+
template<typename T>
void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(FormatBuilder& builder, T value)
{
diff --git a/AK/Format.h b/AK/Format.h
index 90030765ec..63b1d3fab2 100644
--- a/AK/Format.h
+++ b/AK/Format.h
@@ -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);
#ifndef KERNEL
@@ -435,6 +435,20 @@ template<typename T>
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
#ifndef KERNEL
@@ -448,3 +462,4 @@ using AK::warnln;
using AK::dbgln;
using AK::FormatIfSupported;
+using AK::FormatString;
diff --git a/AK/Tests/TestFormat.cpp b/AK/Tests/TestFormat.cpp
index cfe7fe2950..609582b6ae 100644
--- a/AK/Tests/TestFormat.cpp
+++ b/AK/Tests/TestFormat.cpp
@@ -274,4 +274,20 @@ TEST_CASE(format_nullptr)
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)
diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt
index 8a3bdcaf1e..5b1c8b11f3 100644
--- a/Kernel/CMakeLists.txt
+++ b/Kernel/CMakeLists.txt
@@ -206,7 +206,6 @@ set(KERNEL_SOURCES
VM/Region.cpp
VM/SharedInodeVMObject.cpp
VM/VMObject.cpp
- VirtualAddress.cpp
WaitQueue.cpp
init.cpp
kprintf.cpp
diff --git a/Kernel/VirtualAddress.cpp b/Kernel/VirtualAddress.cpp
deleted file mode 100644
index 945cc0e99c..0000000000
--- a/Kernel/VirtualAddress.cpp
+++ /dev/null
@@ -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()));
-}
-
-}
diff --git a/Kernel/VirtualAddress.h b/Kernel/VirtualAddress.h
index 3a0fa6691f..78602aa8db 100644
--- a/Kernel/VirtualAddress.h
+++ b/Kernel/VirtualAddress.h
@@ -76,11 +76,10 @@ inline const LogStream& operator<<(const LogStream& stream, VirtualAddress value
return stream << 'V' << value.as_ptr();
}
-namespace AK {
-
template<>
-struct Formatter<VirtualAddress> : Formatter<StringView> {
- void format(FormatBuilder&, const VirtualAddress&);
+struct AK::Formatter<VirtualAddress> : AK::Formatter<FormatString> {
+ void format(FormatBuilder& builder, const VirtualAddress& value)
+ {
+ return AK::Formatter<FormatString>::format(builder, "V{}", value.as_ptr());
+ }
};
-
-}
diff --git a/Libraries/LibCore/Object.cpp b/Libraries/LibCore/Object.cpp
index 27d5985d00..cf16b4aadf 100644
--- a/Libraries/LibCore/Object.cpp
+++ b/Libraries/LibCore/Object.cpp
@@ -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));
-}
-
-}
diff --git a/Libraries/LibCore/Object.h b/Libraries/LibCore/Object.h
index f8e81743c6..ef568f84d5 100644
--- a/Libraries/LibCore/Object.h
+++ b/Libraries/LibCore/Object.h
@@ -173,12 +173,13 @@ private:
}
-namespace AK {
template<>
-struct Formatter<Core::Object> : Formatter<StringView> {
- void format(FormatBuilder&, const Core::Object&);
+struct AK::Formatter<Core::Object> : AK::Formatter<FormatString> {
+ void format(FormatBuilder& builder, const Core::Object& value)
+ {
+ return AK::Formatter<FormatString>::format(builder, "{}({})", value.class_name(), &value);
+ }
};
-}
namespace Core {
template<typename T, typename Callback>
diff --git a/Libraries/LibGUI/ModelIndex.cpp b/Libraries/LibGUI/ModelIndex.cpp
index 6b87d4a70b..ea6a97c28f 100644
--- a/Libraries/LibGUI/ModelIndex.cpp
+++ b/Libraries/LibGUI/ModelIndex.cpp
@@ -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()));
-}
-
-}
diff --git a/Libraries/LibGUI/ModelIndex.h b/Libraries/LibGUI/ModelIndex.h
index f0cf6a978c..5f8e088798 100644
--- a/Libraries/LibGUI/ModelIndex.h
+++ b/Libraries/LibGUI/ModelIndex.h
@@ -82,8 +82,14 @@ const LogStream& operator<<(const LogStream&, const ModelIndex&);
namespace AK {
template<>
-struct Formatter<GUI::ModelIndex> : Formatter<StringView> {
- void format(FormatBuilder&, const GUI::ModelIndex&);
+struct Formatter<GUI::ModelIndex> : Formatter<FormatString> {
+ 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<>
diff --git a/Libraries/LibGUI/TextPosition.h b/Libraries/LibGUI/TextPosition.h
index 8785341004..47ccc71e47 100644
--- a/Libraries/LibGUI/TextPosition.h
+++ b/Libraries/LibGUI/TextPosition.h
@@ -66,17 +66,13 @@ inline const LogStream& operator<<(const LogStream& stream, const TextPosition&
}
-namespace AK {
-
template<>
-struct Formatter<GUI::TextPosition> : Formatter<StringView> {
+struct AK::Formatter<GUI::TextPosition> : AK::Formatter<FormatString> {
void format(FormatBuilder& builder, const GUI::TextPosition& value)
{
if (value.is_valid())
- Formatter<StringView>::format(builder, String::formatted("({},{})", value.line(), value.column()));
+ Formatter<FormatString>::format(builder, "({},{})", value.line(), value.column());
else
- Formatter<StringView>::format(builder, "GUI::TextPosition(Invalid)");
+ Formatter<FormatString>::format(builder, "GUI::TextPosition(Invalid)");
}
};
-
-}
diff --git a/Libraries/LibGUI/TextRange.h b/Libraries/LibGUI/TextRange.h
index 4b10a4568f..222edbca01 100644
--- a/Libraries/LibGUI/TextRange.h
+++ b/Libraries/LibGUI/TextRange.h
@@ -94,17 +94,13 @@ inline const LogStream& operator<<(const LogStream& stream, const TextRange& val
}
-namespace AK {
-
template<>
-struct Formatter<GUI::TextRange> : Formatter<StringView> {
+struct AK::Formatter<GUI::TextRange> : AK::Formatter<FormatString> {
void format(FormatBuilder& builder, const GUI::TextRange& value)
{
if (value.is_valid())
- Formatter<StringView>::format(builder, String::formatted("{}-{}", value.start(), value.end()));
+ return Formatter<FormatString>::format(builder, "{}-{}", value.start(), value.end());
else
- Formatter<StringView>::format(builder, "GUI::TextRange(Invalid)");
+ return Formatter<FormatString>::format(builder, "GUI::TextRange(Invalid)");
}
};
-
-}
diff --git a/Libraries/LibJS/Runtime/Cell.h b/Libraries/LibJS/Runtime/Cell.h
index 0f1ff18860..df4a19f19a 100644
--- a/Libraries/LibJS/Runtime/Cell.h
+++ b/Libraries/LibJS/Runtime/Cell.h
@@ -75,17 +75,13 @@ private:
}
-namespace AK {
-
template<>
-struct Formatter<JS::Cell> : Formatter<StringView> {
+struct AK::Formatter<JS::Cell> : AK::Formatter<FormatString> {
void format(FormatBuilder& builder, const JS::Cell* cell)
{
if (!cell)
- Formatter<StringView>::format(builder, "Cell{nullptr}");
+ Formatter<FormatString>::format(builder, "Cell{nullptr}");
else
- Formatter<StringView>::format(builder, String::formatted("{}{{{}}}", cell->class_name(), static_cast<const void*>(cell)));
+ Formatter<FormatString>::format(builder, "{}({})", cell->class_name(), cell);
}
};
-
-}