[libc-commits] [libc] [libc] Support C23 'b' (binary) modifier in printf (PR #80851)

via libc-commits libc-commits at lists.llvm.org
Tue Feb 6 07:40:10 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Artem Tyurin (agentcooper)

<details>
<summary>Changes</summary>

Reference: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2612.pdf.

Fixes https://github.com/llvm/llvm-project/issues/80727.

---
Full diff: https://github.com/llvm/llvm-project/pull/80851.diff


4 Files Affected:

- (modified) libc/src/stdio/printf_core/converter.cpp (+2) 
- (modified) libc/src/stdio/printf_core/int_converter.h (+5-1) 
- (modified) libc/src/stdio/printf_core/parser.h (+4) 
- (modified) libc/test/src/stdio/printf_core/converter_test.cpp (+14) 


``````````diff
diff --git a/libc/src/stdio/printf_core/converter.cpp b/libc/src/stdio/printf_core/converter.cpp
index 74a36cbf7432fb..52412aef3c5c15 100644
--- a/libc/src/stdio/printf_core/converter.cpp
+++ b/libc/src/stdio/printf_core/converter.cpp
@@ -58,6 +58,8 @@ int convert(Writer *writer, const FormatSection &to_conv) {
   case 'o':
   case 'x':
   case 'X':
+  case 'b':
+  case 'B':
     return convert_int(writer, to_conv);
 #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT
   case 'f':
diff --git a/libc/src/stdio/printf_core/int_converter.h b/libc/src/stdio/printf_core/int_converter.h
index 7744d801cbc189..8520f12c0372ce 100644
--- a/libc/src/stdio/printf_core/int_converter.h
+++ b/libc/src/stdio/printf_core/int_converter.h
@@ -33,6 +33,7 @@ using HexFmt = IntegerToString<uintmax_t, radix::Hex>;
 using HexFmtUppercase = IntegerToString<uintmax_t, radix::Hex::Uppercase>;
 using OctFmt = IntegerToString<uintmax_t, radix::Oct>;
 using DecFmt = IntegerToString<uintmax_t>;
+using BinFmt = IntegerToString<uintmax_t, radix::Bin>;
 
 LIBC_INLINE constexpr size_t num_buf_size() {
   constexpr auto max = [](size_t a, size_t b) -> size_t {
@@ -40,7 +41,8 @@ LIBC_INLINE constexpr size_t num_buf_size() {
   };
   return max(HexFmt::buffer_size(),
              max(HexFmtUppercase::buffer_size(),
-                 max(OctFmt::buffer_size(), DecFmt::buffer_size())));
+                 max(OctFmt::buffer_size(),
+                     max(DecFmt::buffer_size(), BinFmt::buffer_size()))));
 }
 
 LIBC_INLINE cpp::optional<cpp::string_view>
@@ -52,6 +54,8 @@ num_to_strview(uintmax_t num, cpp::span<char> bufref, char conv_name) {
       return HexFmtUppercase::format_to(bufref, num);
   } else if (conv_name == 'o') {
     return OctFmt::format_to(bufref, num);
+  } else if (to_lower(conv_name) == 'b') {
+    return BinFmt::format_to(bufref, num);
   } else {
     return DecFmt::format_to(bufref, num);
   }
diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index ab491655275fb9..1e7d2e58c924a6 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -159,6 +159,8 @@ template <typename ArgProvider> class Parser {
       case ('x'):
       case ('X'):
       case ('u'):
+      case ('b'):
+      case ('B'):
         switch (lm) {
         case (LengthModifier::hh):
         case (LengthModifier::h):
@@ -484,6 +486,8 @@ template <typename ArgProvider> class Parser {
         case ('x'):
         case ('X'):
         case ('u'):
+        case ('b'):
+        case ('B'):
           switch (lm) {
           case (LengthModifier::hh):
           case (LengthModifier::h):
diff --git a/libc/test/src/stdio/printf_core/converter_test.cpp b/libc/test/src/stdio/printf_core/converter_test.cpp
index 8404ef6ec7db4d..9da749f3b8ad1a 100644
--- a/libc/test/src/stdio/printf_core/converter_test.cpp
+++ b/libc/test/src/stdio/printf_core/converter_test.cpp
@@ -210,6 +210,20 @@ TEST_F(LlvmLibcPrintfConverterTest, HexConversion) {
   ASSERT_EQ(writer.get_chars_written(), 18);
 }
 
+TEST_F(LlvmLibcPrintfConverterTest, BinaryConversion) {
+  LIBC_NAMESPACE::printf_core::FormatSection section;
+  section.has_conv = true;
+  section.raw_string = "%b";
+  section.conv_name = 'b';
+  section.conv_val_raw = 42;
+  LIBC_NAMESPACE::printf_core::convert(&writer, section);
+
+  wb.buff[wb.buff_cur] = '\0';
+
+  ASSERT_STREQ(str, "101010");
+  ASSERT_EQ(writer.get_chars_written(), 6);
+}
+
 TEST_F(LlvmLibcPrintfConverterTest, PointerConversion) {
 
   LIBC_NAMESPACE::printf_core::FormatSection section;

``````````

</details>


https://github.com/llvm/llvm-project/pull/80851


More information about the libc-commits mailing list