Skip to content

[lib++][print] Don't pad the ostream output. #128354

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

Merged
merged 1 commit into from
Feb 26, 2025

Conversation

mordante
Copy link
Member

Per [ostream.formatted.reqmts]/3 padding should only be done when explicitly stated.

Fixes: #116054

Per [ostream.formatted.reqmts]/3 padding should only be done when
explicitly stated.

Fixes: llvm#116054
@mordante mordante requested a review from a team as a code owner February 22, 2025 12:36
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 22, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 22, 2025

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

Per [ostream.formatted.reqmts]/3 padding should only be done when explicitly stated.

Fixes: #116054


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

4 Files Affected:

  • (modified) libcxx/include/__ostream/print.h (+2-12)
  • (modified) libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/print.pass.cpp (+7-23)
  • (modified) libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_nonunicode.pass.cpp (+7-23)
  • (modified) libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_unicode.pass.cpp (+7-23)
diff --git a/libcxx/include/__ostream/print.h b/libcxx/include/__ostream/print.h
index eb4233342214d..a4d7506cffc48 100644
--- a/libcxx/include/__ostream/print.h
+++ b/libcxx/include/__ostream/print.h
@@ -49,21 +49,11 @@ __vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args, bool _
     if (__write_nl)
       __o += '\n';
 
-    const char* __str = __o.data();
-    size_t __len      = __o.size();
-
 #    if _LIBCPP_HAS_EXCEPTIONS
     try {
 #    endif // _LIBCPP_HAS_EXCEPTIONS
-      typedef ostreambuf_iterator<char> _Ip;
-      if (std::__pad_and_output(
-              _Ip(__os),
-              __str,
-              (__os.flags() & ios_base::adjustfield) == ios_base::left ? __str + __len : __str,
-              __str + __len,
-              __os,
-              __os.fill())
-              .failed())
+      if (auto __rdbuf = __os.rdbuf();
+          !__rdbuf || __rdbuf->sputn(__o.data(), __o.size()) != static_cast<streamsize>(__o.size()))
         __os.setstate(ios_base::badbit | ios_base::failbit);
 
 #    if _LIBCPP_HAS_EXCEPTIONS
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/print.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/print.pass.cpp
index 711152ba6f32a..1f188b36db9a3 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/print.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/print.pass.cpp
@@ -133,6 +133,7 @@ static void test_write_failure() {
   assert(os.fail());
 }
 
+// Test the formatting does no padding.
 static void test_stream_formatting() {
   std::stringstream sstr;
   auto test = [&]<class... Args>(std::string_view expected, test_format_string<char, Args...> fmt, Args&&... args) {
@@ -148,37 +149,20 @@ static void test_stream_formatting() {
   test("hello", "{}", "hello");
 
   sstr.width(10);
-  test("     hello", "{}", "hello");
+  test("hello", "{}", "hello");
+  assert(sstr.width() == 10);
 
   sstr.fill('+');
 
   sstr.width(10);
-  test("+++++hello", "{}", "hello");
+  test("hello", "{}", "hello");
+  assert(sstr.width() == 10);
 
   // *** Test embedded NUL character ***
   using namespace std::literals;
   sstr.width(15);
-  test("++++hello\0world"sv, "hello{}{}", '\0', "world");
-
-  // *** Test Unicode ***
-  // Streams count code units not code points
-  // 2-byte code points
-  sstr.width(5);
-  test("+++\u00a1", "{}", "\u00a1"); // INVERTED EXCLAMATION MARK
-  sstr.width(5);
-  test("+++\u07ff", "{}", "\u07ff"); // NKO TAMAN SIGN
-
-  // 3-byte code points
-  sstr.width(5);
-  test("++\u0800", "{}", "\u0800"); // SAMARITAN LETTER ALAF
-  sstr.width(5);
-  test("++\ufffd", "{}", "\ufffd"); // REPLACEMENT CHARACTER
-
-  // 4-byte code points
-  sstr.width(5);
-  test("+\U00010000", "{}", "\U00010000"); // LINEAR B SYLLABLE B008 A
-  sstr.width(5);
-  test("+\U0010FFFF", "{}", "\U0010FFFF"); // Undefined Character
+  test("hello\0world"sv, "hello{}{}", '\0', "world");
+  assert(sstr.width() == 15);
 }
 
 int main(int, char**) {
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_nonunicode.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_nonunicode.pass.cpp
index 73ad19132f17f..7aa7390216adc 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_nonunicode.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_nonunicode.pass.cpp
@@ -149,6 +149,7 @@ static void test_write_failure() {
   assert(os.fail());
 }
 
+// Test the formatting does no padding.
 static void test_stream_formatting() {
   std::stringstream sstr;
   auto test = [&]<class... Args>(std::string_view expected, test_format_string<char, Args...> fmt, Args&&... args) {
@@ -164,37 +165,20 @@ static void test_stream_formatting() {
   test("hello", "{}", "hello");
 
   sstr.width(10);
-  test("     hello", "{}", "hello");
+  test("hello", "{}", "hello");
+  assert(sstr.width() == 10);
 
   sstr.fill('+');
 
   sstr.width(10);
-  test("+++++hello", "{}", "hello");
+  test("hello", "{}", "hello");
+  assert(sstr.width() == 10);
 
   // *** Test embedded NUL character ***
   using namespace std::literals;
   sstr.width(15);
-  test("++++hello\0world"sv, "hello{}{}", '\0', "world");
-
-  // *** Test Unicode ***
-  // Streams count code units not code points
-  // 2-byte code points
-  sstr.width(5);
-  test("+++\u00a1", "{}", "\u00a1"); // INVERTED EXCLAMATION MARK
-  sstr.width(5);
-  test("+++\u07ff", "{}", "\u07ff"); // NKO TAMAN SIGN
-
-  // 3-byte code points
-  sstr.width(5);
-  test("++\u0800", "{}", "\u0800"); // SAMARITAN LETTER ALAF
-  sstr.width(5);
-  test("++\ufffd", "{}", "\ufffd"); // REPLACEMENT CHARACTER
-
-  // 4-byte code points
-  sstr.width(5);
-  test("+\U00010000", "{}", "\U00010000"); // LINEAR B SYLLABLE B008 A
-  sstr.width(5);
-  test("+\U0010FFFF", "{}", "\U0010FFFF"); // Undefined Character
+  test("hello\0world"sv, "hello{}{}", '\0', "world");
+  assert(sstr.width() == 15);
 }
 
 int main(int, char**) {
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_unicode.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_unicode.pass.cpp
index 21f6654d5f9cf..8b43a71215ade 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_unicode.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/vprint_unicode.pass.cpp
@@ -149,6 +149,7 @@ static void test_write_failure() {
   assert(os.fail());
 }
 
+// Test the formatting does no padding.
 static void test_stream_formatting() {
   std::stringstream sstr;
   auto test = [&]<class... Args>(std::string_view expected, test_format_string<char, Args...> fmt, Args&&... args) {
@@ -164,37 +165,20 @@ static void test_stream_formatting() {
   test("hello", "{}", "hello");
 
   sstr.width(10);
-  test("     hello", "{}", "hello");
+  test("hello", "{}", "hello");
+  assert(sstr.width() == 10);
 
   sstr.fill('+');
 
   sstr.width(10);
-  test("+++++hello", "{}", "hello");
+  test("hello", "{}", "hello");
+  assert(sstr.width() == 10);
 
   // *** Test embedded NUL character ***
   using namespace std::literals;
   sstr.width(15);
-  test("++++hello\0world"sv, "hello{}{}", '\0', "world");
-
-  // *** Test Unicode ***
-  // Streams count code units not code points
-  // 2-byte code points
-  sstr.width(5);
-  test("+++\u00a1", "{}", "\u00a1"); // INVERTED EXCLAMATION MARK
-  sstr.width(5);
-  test("+++\u07ff", "{}", "\u07ff"); // NKO TAMAN SIGN
-
-  // 3-byte code points
-  sstr.width(5);
-  test("++\u0800", "{}", "\u0800"); // SAMARITAN LETTER ALAF
-  sstr.width(5);
-  test("++\ufffd", "{}", "\ufffd"); // REPLACEMENT CHARACTER
-
-  // 4-byte code points
-  sstr.width(5);
-  test("+\U00010000", "{}", "\U00010000"); // LINEAR B SYLLABLE B008 A
-  sstr.width(5);
-  test("+\U0010FFFF", "{}", "\U0010FFFF"); // Undefined Character
+  test("hello\0world"sv, "hello{}{}", '\0', "world");
+  assert(sstr.width() == 15);
 }
 
 int main(int, char**) {

@mordante mordante merged commit a841cf9 into llvm:main Feb 26, 2025
79 of 83 checks passed
@mordante mordante deleted the review/print_do_not_pad_ostream branch February 26, 2025 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc++] vprint_[non]unicode(ostream &, string_view, Args&&...) should not pad the output
3 participants