summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasynts <asynts@gmail.com>2020-09-29 14:07:39 +0200
committerAndreas Kling <kling@serenityos.org>2020-09-29 16:14:58 +0200
commit1175ecf1dd520262dbb383decedae2cdebfbd0cc (patch)
tree8600433dd8bd8fb8818be2339f5d834097d6565a
parentf221a95a7177716335f94cb0ac22b3649d7fbbc5 (diff)
downloadserenity-1175ecf1dd520262dbb383decedae2cdebfbd0cc.zip
AK+Format: Add support for integer to character casts.
Now the following is possible: outf("{:c}", 75); // K
-rw-r--r--AK/Format.cpp45
-rw-r--r--AK/Tests/TestFormat.cpp6
2 files changed, 48 insertions, 3 deletions
diff --git a/AK/Format.cpp b/AK/Format.cpp
index a72c0874a0..e09a160d10 100644
--- a/AK/Format.cpp
+++ b/AK/Format.cpp
@@ -366,10 +366,8 @@ void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(StringB
{
if (m_precision != value_not_set)
ASSERT_NOT_REACHED();
- if (m_mode == Mode::Character)
- TODO();
- u8 base;
+ u8 base = 0;
bool upper_case = false;
if (m_mode == Mode::Binary) {
base = 2;
@@ -385,12 +383,53 @@ void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(StringB
} else if (m_mode == Mode::HexadecimalUppercase) {
base = 16;
upper_case = true;
+ } else if (m_mode == Mode::Character) {
+ // special case
} else {
ASSERT_NOT_REACHED();
}
auto width = decode_value(m_width, context);
+ const auto put_padding = [&](size_t amount, char fill) {
+ for (size_t i = 0; i < amount; ++i)
+ builder.append(fill);
+ };
+
+ if (m_mode == Mode::Character) {
+ // FIXME: We just support ASCII for now, in the future maybe unicode?
+ ASSERT(value >= 0 && value <= 127);
+
+ const size_t used_by_value = 1;
+ const auto used_by_padding = width < used_by_value ? 0 : width - used_by_value;
+
+ if (m_align == Align::Left || m_align == Align::Default) {
+ const auto used_by_right_padding = used_by_padding;
+
+ builder.append(static_cast<char>(value));
+ 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);
+ builder.append(static_cast<char>(value));
+ 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);
+ builder.append(static_cast<char>(value));
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+ }
+
PrintfImplementation::Align align;
if (m_align == Align::Left)
align = PrintfImplementation::Align::Left;
diff --git a/AK/Tests/TestFormat.cpp b/AK/Tests/TestFormat.cpp
index 18994250fd..fa26f0caf2 100644
--- a/AK/Tests/TestFormat.cpp
+++ b/AK/Tests/TestFormat.cpp
@@ -130,4 +130,10 @@ TEST_CASE(complex_string_specifiers)
EXPECT_EQ(String::formatted("{:^9}", "abcd"), " abcd ");
}
+TEST_CASE(cast_integer_to_character)
+{
+ EXPECT_EQ(String::formatted("{:c}", static_cast<int>('a')), "a");
+ EXPECT_EQ(String::formatted("{:c}", static_cast<unsigned int>('f')), "f");
+}
+
TEST_MAIN(Format)