Use _Streambuf_sink directly in vprint_nonunicode instead of
formatting to an intermediate string (_Str_sink) and then writing
it to the stream.  This avoids the temporary string allocation and
extra copy, and allows zero-copy writes into the streambuf's put
area.

I/O errors are tracked internally by _Streambuf_sink and reported
after formatting completes via setstate(badbit), so that exceptions
from vformat (format_error, bad_alloc) propagate without setting
badbit, meeting [ostream.formatted.print]/(4.2).

libstdc++-v3/ChangeLog:

        * include/bits/ostream_print.h (vprint_nonunicode): Use
        _Streambuf_sink instead of _Str_sink + __ostream_write.

Signed-off-by: Anlai Lu <[email protected]>
---
 libstdc++-v3/include/bits/ostream_print.h | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/include/bits/ostream_print.h 
b/libstdc++-v3/include/bits/ostream_print.h
index 0adf16d4f..4542bfcbf 100644
--- a/libstdc++-v3/include/bits/ostream_print.h
+++ b/libstdc++-v3/include/bits/ostream_print.h
@@ -61,21 +61,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     ostream::sentry __cerb(__os);
     if (__cerb)
       {
-       __format::_Str_sink<char> __buf;
-       std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
-       auto __out = __buf.view();
-
+       __format::_Streambuf_sink<char> __sink(__os.rdbuf());
        __try
          {
-           std::__ostream_write(__os, __out.data(), __out.size());
+           std::vformat_to(__sink.out(), __os.getloc(), __fmt, __args);
+           std::move(__sink)._M_finish();
          }
        __catch(const __cxxabiv1::__forced_unwind&)
          {
            __os._M_setstate(ios_base::badbit);
            __throw_exception_again;
          }
-       __catch(...)
-         { __os._M_setstate(ios_base::badbit); }
+       if (__sink._M_failed())
+         __os.setstate(ios_base::badbit);
       }
   }
 
-- 
2.34.1

Reply via email to