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