@@ -833,40 +833,59 @@ typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>
833833 *this ->pptr () = traits_type::to_char_type (__c);
834834 this ->pbump (1 );
835835 }
836- if (this ->pptr () != this ->pbase ()) {
837- if (__always_noconv_) {
838- size_t __nmemb = static_cast <size_t >(this ->pptr () - this ->pbase ());
839- if (std::fwrite (this ->pbase (), sizeof (char_type), __nmemb, __file_) != __nmemb)
836+
837+ // There is nothing to write, early return
838+ if (this ->pptr () == this ->pbase ()) {
839+ return traits_type::not_eof (__c);
840+ }
841+
842+ if (__always_noconv_) {
843+ size_t __n = static_cast <size_t >(this ->pptr () - this ->pbase ());
844+ if (std::fwrite (this ->pbase (), sizeof (char_type), __n, __file_) != __n)
845+ return traits_type::eof ();
846+ } else {
847+ if (!__cv_)
848+ std::__throw_bad_cast ();
849+
850+ // See [filebuf.virtuals]
851+ char_type* __b = this ->pbase ();
852+ char_type* __p = this ->pptr ();
853+ const char_type* __end;
854+ char * __extbuf_end = __extbuf_;
855+ do {
856+ codecvt_base::result __r = __cv_->out (__st_, __b, __p, __end, __extbuf_, __extbuf_ + __ebs_, __extbuf_end);
857+ if (__end == __b)
840858 return traits_type::eof ();
841- } else {
842- char * __extbe = __extbuf_;
843- codecvt_base::result __r;
844- do {
845- if (!__cv_)
846- std::__throw_bad_cast ();
847859
848- const char_type* __e;
849- __r = __cv_->out (__st_, this ->pbase (), this ->pptr (), __e, __extbuf_, __extbuf_ + __ebs_, __extbe);
850- if (__e == this ->pbase ())
860+ // No conversion needed: output characters directly to the file, done.
861+ if (__r == codecvt_base::noconv) {
862+ size_t __n = static_cast <size_t >(__p - __b);
863+ if (std::fwrite (__b, 1 , __n, __file_) != __n)
851864 return traits_type::eof ();
852- if (__r == codecvt_base::noconv) {
853- size_t __nmemb = static_cast <size_t >(this ->pptr () - this ->pbase ());
854- if (std::fwrite (this ->pbase (), 1 , __nmemb, __file_) != __nmemb)
855- return traits_type::eof ();
856- } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) {
857- size_t __nmemb = static_cast <size_t >(__extbe - __extbuf_);
858- if (std::fwrite (__extbuf_, 1 , __nmemb, __file_) != __nmemb)
859- return traits_type::eof ();
860- if (__r == codecvt_base::partial) {
861- this ->setp (const_cast <char_type*>(__e), this ->pptr ());
862- this ->__pbump (this ->epptr () - this ->pbase ());
863- }
864- } else
865+ break ;
866+
867+ // Conversion successful: output the converted characters to the file, done.
868+ } else if (__r == codecvt_base::ok) {
869+ size_t __n = static_cast <size_t >(__extbuf_end - __extbuf_);
870+ if (std::fwrite (__extbuf_, 1 , __n, __file_) != __n)
865871 return traits_type::eof ();
866- } while (__r == codecvt_base::partial);
867- }
868- this ->setp (__pb_save, __epb_save);
872+ break ;
873+
874+ // Conversion partially successful: output converted characters to the file and repeat with the
875+ // remaining characters.
876+ } else if (__r == codecvt_base::partial) {
877+ size_t __n = static_cast <size_t >(__extbuf_end - __extbuf_);
878+ if (std::fwrite (__extbuf_, 1 , __n, __file_) != __n)
879+ return traits_type::eof ();
880+ __b = const_cast <char_type*>(__end);
881+ continue ;
882+
883+ } else {
884+ return traits_type::eof ();
885+ }
886+ } while (true );
869887 }
888+ this ->setp (__pb_save, __epb_save);
870889 return traits_type::not_eof (__c);
871890}
872891
0 commit comments