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