This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC/Patch] Change _M_overflow to call _M_convert_to_external onlyonce


Hi again,

this is the interesting part, based on an idea developed
with Nathan.

Basically, the put area is still _M_buf_size sized, but there
is one more allocated char at _M_out_end, which can host
the overflow char of a full buffer.

Everything is quite straightforward, apart from a corner case,
about which I particularly need feedback: what happens for
a setbuf(*, n), n = 1?

In the proposal below, I simply ignore the request: only n = 0
(with the stream closed) and n > 1 have an effect: seems not
a real limitation, considering the actual uses of setbuf
buffers.

Alternately, we could change n = 1 to n = 0 and deal with this
case as I tentatively did for the not-a-bug 9423:

http://gcc.gnu.org/ml/libstdc++/2003-04/msg00088.html

The below is missing comments but passed make check (and a few
other sanity checks).

Thanks,
Paolo.

///////
diff -prN libstdc++-v3-1/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
*** libstdc++-v3-1/include/bits/fstream.tcc	Sun May 11 17:22:17 2003
--- libstdc++-v3/include/bits/fstream.tcc	Sun May 11 18:47:38 2003
*************** namespace std
*** 51,57 ****
        if (!this->_M_buf && this->_M_buf_size)
  	{
  	  // Allocate internal buffer.
! 	  this->_M_buf = new char_type[this->_M_buf_size];
  	  _M_buf_allocated = true;
  	}
      }
--- 51,57 ----
        if (!this->_M_buf && this->_M_buf_size)
  	{
  	  // Allocate internal buffer.
! 	  this->_M_buf = new char_type[this->_M_buf_size + 1];
  	  _M_buf_allocated = true;
  	}
      }
*************** namespace std
*** 76,82 ****
      basic_filebuf<_CharT, _Traits>::
      basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), 
      _M_state_cur(__state_type()), _M_state_beg(__state_type()), 
!     _M_buf(NULL), _M_buf_size(BUFSIZ), _M_buf_allocated(false),
      _M_last_overflowed(false), _M_pback_cur_save(0),
      _M_pback_end_save(0), _M_pback_init(false)
      { this->_M_buf_unified = true; }
--- 76,82 ----
      basic_filebuf<_CharT, _Traits>::
      basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), 
      _M_state_cur(__state_type()), _M_state_beg(__state_type()), 
!     _M_buf(NULL), _M_buf_size(BUFSIZ-1), _M_buf_allocated(false),
      _M_last_overflowed(false), _M_pback_cur_save(0),
      _M_pback_end_save(0), _M_pback_init(false)
      { this->_M_buf_unified = true; }
*************** namespace std
*** 433,478 ****
      _M_overflow(int_type __c)
      {
        int_type __ret = traits_type::eof();
!       const bool __testput = this->_M_out_beg < this->_M_out_lim;
        const bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size;
  
!       if (__testput || __testunbuffered)
  	{
  	  // Need to restore current position. The position of the external
  	  // byte sequence (_M_file) corresponds to _M_filepos, and we need
  	  // to move it to _M_out_beg for the write.
! 	  if (_M_filepos && _M_filepos != this->_M_out_beg)
! 	    {
! 	      off_type __off = this->_M_out_beg - _M_filepos;
! 	      _M_file.seekoff(__off, ios_base::cur);
! 	    }
  
! 	  // Convert internal buffer to external representation, output.
! 	  // NB: In the unbuffered case, no internal buffer exists.
! 	  if (__testunbuffered || _M_convert_to_external(this->_M_out_beg,
! 							 this->_M_out_lim
! 							 - this->_M_out_beg))
! 	    {
! 	      // Convert pending sequence to external representation, output.
! 	      // If eof, then just attempt sync.
! 	      if (!traits_type::eq_int_type(__c, traits_type::eof()))
! 		{
! 		  char_type __pending = traits_type::to_char_type(__c);
! 		  // User code must flush when switching modes (thus
! 		  // don't sync).
! 		  if (_M_convert_to_external(&__pending, 1))
! 		    {
! 		      _M_set_indeterminate();
! 		      __ret = traits_type::not_eof(__c);
! 		    }
! 		}
! 	      else if (!_M_file.sync())
! 		{
! 		  _M_set_indeterminate();
! 		  __ret = traits_type::not_eof(__c);
! 		}
! 	    }
  	}
        _M_last_overflowed = true;	
        return __ret;
      }
--- 433,469 ----
      _M_overflow(int_type __c)
      {
        int_type __ret = traits_type::eof();
!       const bool __testeof = traits_type::eq_int_type(__c, __ret);
        const bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size;
+       bool __convok = false;
  
!       if (this->_M_out_beg < this->_M_out_lim)
  	{
  	  // Need to restore current position. The position of the external
  	  // byte sequence (_M_file) corresponds to _M_filepos, and we need
  	  // to move it to _M_out_beg for the write.
! 	  if (_M_filepos != this->_M_out_beg)
! 	    _M_file.seekoff(this->_M_out_beg - _M_filepos, ios_base::cur);
! 	  if (!__testeof)
! 	    *this->_M_out_lim++ = traits_type::to_char_type(__c);
! 	  __convok = _M_convert_to_external(this->_M_out_beg,
! 					    this->_M_out_lim
! 					    - this->_M_out_beg);
! 	}
!       else if (__testunbuffered && !__testeof)
! 	{
! 	  char_type __pending = traits_type::to_char_type(__c);
! 	  __convok = _M_convert_to_external(&__pending, 1);
! 	}
!       else if (__testunbuffered && __testeof && !_M_file.sync())
! 	__convok = true;
  
!       if (__convok)
! 	{
! 	  _M_set_indeterminate();
! 	  __ret = traits_type::not_eof(__c);
  	}
+ 
        _M_last_overflowed = true;	
        return __ret;
      }
*************** namespace std
*** 484,490 ****
      {
        if (!this->is_open() && __s == 0 && __n == 0)
  	this->_M_buf_size = 0;
!       else if (__s && __n)
  	{
  	  // This is implementation-defined behavior, and assumes
  	  // that an external char_type array of length (__s + __n)
--- 475,481 ----
      {
        if (!this->is_open() && __s == 0 && __n == 0)
  	this->_M_buf_size = 0;
!       else if (__s && __n > 1)
  	{
  	  // This is implementation-defined behavior, and assumes
  	  // that an external char_type array of length (__s + __n)
*************** namespace std
*** 496,502 ****
  	  
  	  // Step 2: Use the external array.
  	  this->_M_buf = __s;
! 	  this->_M_buf_size = __n;
  	  _M_set_indeterminate();
  	}
        _M_last_overflowed = false;	
--- 487,493 ----
  	  
  	  // Step 2: Use the external array.
  	  this->_M_buf = __s;
! 	  this->_M_buf_size = __n - 1;
  	  _M_set_indeterminate();
  	}
        _M_last_overflowed = false;	
diff -prN libstdc++-v3-1/include/ext/stdio_filebuf.h libstdc++-v3/include/ext/stdio_filebuf.h
*** libstdc++-v3-1/include/ext/stdio_filebuf.h	Sun May 11 06:20:55 2003
--- libstdc++-v3/include/ext/stdio_filebuf.h	Sun May 11 18:09:44 2003
*************** namespace __gnu_cxx
*** 121,127 ****
        if (this->is_open())
  	{
  	  this->_M_mode = __mode;
! 	  this->_M_buf_size = __size;
  	  _M_allocate_internal_buffer();
  	  _M_set_indeterminate();
  	}
--- 121,127 ----
        if (this->is_open())
  	{
  	  this->_M_mode = __mode;
! 	  this->_M_buf_size = __size > 1 ? __size - 1 : 0;
  	  _M_allocate_internal_buffer();
  	  _M_set_indeterminate();
  	}
*************** namespace __gnu_cxx
*** 136,142 ****
        if (this->is_open())
  	{
  	  this->_M_mode = __mode;
! 	  this->_M_buf_size = __size;
  	  _M_allocate_internal_buffer();
  	  _M_set_indeterminate();
  	}
--- 136,142 ----
        if (this->is_open())
  	{
  	  this->_M_mode = __mode;
! 	  this->_M_buf_size = __size > 1 ? __size - 1 : 0;
  	  _M_allocate_internal_buffer();
  	  _M_set_indeterminate();
  	}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]