浏览代码

AK+Format: Add support for integer to character casts.

Now the following is possible:

    outf("{:c}", 75); // K
asynts 4 年之前
父节点
当前提交
1175ecf1dd
共有 2 个文件被更改,包括 48 次插入3 次删除
  1. 42 3
      AK/Format.cpp
  2. 6 0
      AK/Tests/TestFormat.cpp

+ 42 - 3
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;

+ 6 - 0
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)