-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[libc] Support %lc in printf #169301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] Support %lc in printf #169301
Conversation
|
@llvm/pr-subscribers-libc Author: Shubh Pachchigar (shubhe25p) ChangesAdd %lc support to libc printf by utilizing wctomb internal function, also added relevant unit tests. Resolves #166598 Full diff: https://github.com/llvm/llvm-project/pull/169301.diff 3 Files Affected:
diff --git a/libc/src/stdio/printf_core/char_converter.h b/libc/src/stdio/printf_core/char_converter.h
index fd2eb2553887a..58ade4fbf9a53 100644
--- a/libc/src/stdio/printf_core/char_converter.h
+++ b/libc/src/stdio/printf_core/char_converter.h
@@ -13,6 +13,7 @@
#include "src/stdio/printf_core/converter_utils.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/writer.h"
+#include "src/wchar/wctomb.h"
namespace LIBC_NAMESPACE_DECL {
namespace printf_core {
@@ -20,8 +21,10 @@ namespace printf_core {
template <WriteMode write_mode>
LIBC_INLINE int convert_char(Writer<write_mode> *writer,
const FormatSection &to_conv) {
- char c = static_cast<char>(to_conv.conv_val_raw);
-
+ char c;
+ wchar_t wc;
+ char mb_str[MB_LEN_MAX];
+ int ret = 0;
constexpr int STRING_LEN = 1;
size_t padding_spaces =
@@ -33,7 +36,20 @@ LIBC_INLINE int convert_char(Writer<write_mode> *writer,
RET_IF_RESULT_NEGATIVE(writer->write(' ', padding_spaces));
}
- RET_IF_RESULT_NEGATIVE(writer->write(c));
+ if (to_conv.length_modifier == LengthModifier::l) {
+ wc = static_cast<wchar_t>(to_conv.conv_val_raw);
+ ret = wctomb(mb_str, wc);
+ if (ret <= 0) {
+ return INT_CONVERSION_ERROR;
+ }
+ for (int i = 0; i < ret; ++i) {
+ RET_IF_RESULT_NEGATIVE(writer->write(mb_str[i]));
+ }
+ }
+ else {
+ c = static_cast<char>(to_conv.conv_val_raw);
+ RET_IF_RESULT_NEGATIVE(writer->write(c));
+ }
// If the padding is on the right side, write the spaces last.
if (padding_spaces > 0 &&
diff --git a/libc/test/src/stdio/printf_core/CMakeLists.txt b/libc/test/src/stdio/printf_core/CMakeLists.txt
index ff7ebbc4f5fd0..f075b8bd5ec52 100644
--- a/libc/test/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/test/src/stdio/printf_core/CMakeLists.txt
@@ -35,4 +35,6 @@ add_libc_unittest(
libc.src.stdio.printf_core.converter
libc.src.stdio.printf_core.writer
libc.src.stdio.printf_core.core_structs
+ libc.src.wchar.wctomb
+ libc.hdr.types.wchar_t
)
diff --git a/libc/test/src/stdio/printf_core/converter_test.cpp b/libc/test/src/stdio/printf_core/converter_test.cpp
index 2dae2a22c864c..2f7842fa97168 100644
--- a/libc/test/src/stdio/printf_core/converter_test.cpp
+++ b/libc/test/src/stdio/printf_core/converter_test.cpp
@@ -255,3 +255,54 @@ TEST_F(LlvmLibcPrintfConverterTest, OctConversion) {
ASSERT_STREQ(str, "1234");
ASSERT_EQ(writer.get_chars_written(), size_t{4});
}
+
+TEST_F(LlvmLibcPrintfConverterTest, WideCharConversion) {
+
+ LIBC_NAMESPACE::printf_core::FormatSection section;
+ section.has_conv = true;
+ section.raw_string = "%c";
+ section.conv_name = 'c';
+ section.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::l;
+ section.conv_val_raw = static_cast<wchar_t>(L'S');
+
+ LIBC_NAMESPACE::printf_core::convert(&writer, section);
+
+ wb.buff[wb.buff_cur] = '\0';
+
+ ASSERT_STREQ(str, "S");
+ ASSERT_EQ(writer.get_chars_written(), size_t{1});
+}
+
+TEST_F(LlvmLibcPrintfConverterTest, WideCharConversionLeftJustified) {
+ LIBC_NAMESPACE::printf_core::FormatSection left_justified_conv;
+ left_justified_conv.has_conv = true;
+ left_justified_conv.raw_string = "%-4c";
+ left_justified_conv.conv_name = 'c';
+ left_justified_conv.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::l;
+ left_justified_conv.flags =
+ LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED;
+ left_justified_conv.min_width = 4;
+ left_justified_conv.conv_val_raw = static_cast<wchar_t>(L'S');
+
+ LIBC_NAMESPACE::printf_core::convert(&writer, left_justified_conv);
+ wb.buff[wb.buff_cur] = '\0';
+
+ ASSERT_STREQ(str, "S ");
+ ASSERT_EQ(writer.get_chars_written(), size_t{4});
+}
+
+TEST_F(LlvmLibcPrintfConverterTest, WideCharConversionRightJustified) {
+ LIBC_NAMESPACE::printf_core::FormatSection right_justified_conv;
+ right_justified_conv.has_conv = true;
+ right_justified_conv.raw_string = "%4c";
+ right_justified_conv.conv_name = 'c';
+ right_justified_conv.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::l;
+ right_justified_conv.min_width = 4;
+ right_justified_conv.conv_val_raw = static_cast<wchar_t>(L'S');
+
+ LIBC_NAMESPACE::printf_core::convert(&writer, right_justified_conv);
+ wb.buff[wb.buff_cur] = '\0';
+
+ ASSERT_STREQ(str, " S");
+ ASSERT_EQ(writer.get_chars_written(), size_t{4});
+}
|
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions h,cpp -- libc/src/stdio/printf_core/char_converter.h libc/test/src/stdio/printf_core/converter_test.cpp --diff_from_common_commit
View the diff from clang-format here.diff --git a/libc/src/stdio/printf_core/char_converter.h b/libc/src/stdio/printf_core/char_converter.h
index 3c6dc854b..6cb3fbc99 100644
--- a/libc/src/stdio/printf_core/char_converter.h
+++ b/libc/src/stdio/printf_core/char_converter.h
@@ -27,7 +27,7 @@ LIBC_INLINE int convert_char(Writer<write_mode> *writer,
char mb_str[MB_LEN_MAX];
static internal::mbstate internal_mbstate;
int ret = 0;
-
+
char c = static_cast<char>(to_conv.conv_val_raw);
constexpr int STRING_LEN = 1;
diff --git a/libc/test/src/stdio/printf_core/converter_test.cpp b/libc/test/src/stdio/printf_core/converter_test.cpp
index c181175e6..cf479abf9 100644
--- a/libc/test/src/stdio/printf_core/converter_test.cpp
+++ b/libc/test/src/stdio/printf_core/converter_test.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
+#include "libc/hdr/types/wchar_t.h"
#include "src/stdio/printf_core/converter.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/writer.h"
-#include "libc/hdr/types/wchar_t.h"
#include "test/UnitTest/Test.h"
class LlvmLibcPrintfConverterTest : public LIBC_NAMESPACE::testing::Test {
|
|
I think there are some build and clang formatter error, fixing those |
🐧 Linux x64 Test ResultsThe build failed before running any tests. Click on a failure below to see the details. libc/src/stdio/CMakeFiles/libc.src.stdio.snprintf.__internal__.dir/snprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.vsnprintf.__internal__.dir/vsnprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.asprintf.__internal__.dir/asprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.asprintf.dir/asprintf.cpp.olibc/src/stdlib/CMakeFiles/libc.src.stdlib.strfroml.__internal__.dir/strfroml.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.vsprintf.dir/vsprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.vasprintf.dir/vasprintf.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.vprintf.__internal__.dir/vprintf.cpp.olibc/src/stdlib/CMakeFiles/libc.src.stdlib.strfromd.dir/strfromd.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.sprintf.__internal__.dir/sprintf.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.fprintf.dir/fprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.vsprintf.__internal__.dir/vsprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.snprintf.dir/snprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.vasprintf.__internal__.dir/vasprintf.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.printf.dir/printf.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.vfprintf.__internal__.dir/vfprintf.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.vprintf.dir/vprintf.cpp.olibc/src/stdlib/CMakeFiles/libc.src.stdlib.strfromf.dir/strfromf.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.vfprintf.dir/vfprintf.cpp.olibc/src/stdlib/CMakeFiles/libc.src.stdlib.strfromf.__internal__.dir/strfromf.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.fprintf.__internal__.dir/fprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.vsnprintf.dir/vsnprintf.cpp.olibc/src/stdio/CMakeFiles/libc.src.stdio.sprintf.dir/sprintf.cpp.olibc/src/stdlib/CMakeFiles/libc.src.stdlib.strfromd.__internal__.dir/strfromd.cpp.olibc/src/stdio/generic/CMakeFiles/libc.src.stdio.generic.printf.__internal__.dir/printf.cpp.olibc/src/stdlib/CMakeFiles/libc.src.stdlib.strfroml.dir/strfroml.cpp.oIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
d1e951c to
03948a1
Compare
Add %lc support to libc printf by utilizing wcrtomb internal function, also added relevant unit tests.
03948a1 to
5bed042
Compare
Add %lc support to libc printf by utilizing wctomb internal function, also added relevant unit tests.