This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[v3] libstdc++/9339


Removes some of the overflow complexity, adds in unbuffered. Still
related bugs (9024). Also, the unbuffered input bits need to be taken
care of.

tested x86/linux

2003-05-26  Benjamin Kosnik  <bkoz@redhat.com>

	PR libstdc++/9339
	* include/std/std_fstream.h (basic_filebuf::_M_overflow): Remove.
	(_M_pback): No array necessary.
	* include/bits/fstream.tcc (basic_filebuf::_M_overflow): Add
	unbuffered case, coalesec into ...
	(basic_filebuf::overflow): ...this.
	* testsuite/27_io/basic_filebuf/sputn/char/9339.cc: New.
	* testsuite/27_io/basic_filebuf/sputc/char/2.cc: Unbuffered.
	

Index: include/bits/fstream.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/fstream.tcc,v
retrieving revision 1.78
diff -c -p -r1.78 fstream.tcc
*** include/bits/fstream.tcc	22 May 2003 22:16:39 -0000	1.78
--- include/bits/fstream.tcc	26 May 2003 14:51:19 -0000
*************** namespace std
*** 73,79 ****
      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), _M_codecvt(0)
      { 
        this->_M_buf_unified = true; 	  
--- 73,79 ----
      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_filepos(0), _M_pback_cur_save(0),
      _M_pback_end_save(0), _M_pback_init(false), _M_codecvt(0)
      { 
        this->_M_buf_unified = true; 	  
*************** namespace std
*** 125,131 ****
  	      const bool __testput = this->_M_out_beg < this->_M_out_lim;
  
  	      if (__testput 
! 		  && traits_type::eq_int_type(_M_overflow(__eof), __eof))
  		__testfail = true;
  
  #if 0
--- 125,131 ----
  	      const bool __testput = this->_M_out_beg < this->_M_out_lim;
  
  	      if (__testput 
! 		  && traits_type::eq_int_type(this->overflow(), __eof))
  		__testfail = true;
  
  #if 0
*************** namespace std
*** 133,139 ****
  	      if (_M_last_overflowed)
  		{
  		  _M_output_unshift();
! 		  _M_overflow(__eof);
  		}
  #endif
  	    }
--- 133,139 ----
  	      if (_M_last_overflowed)
  		{
  		  _M_output_unshift();
! 		  this->overflow();
  		}
  #endif
  	    }
*************** namespace std
*** 204,210 ****
  
  	  // Sync internal and external buffers.
  	  if (__testout && this->_M_out_beg < this->_M_out_lim)
! 	    _M_overflow();
  
  	  if (_M_buf_size > 1)
  	    {
--- 204,210 ----
  
  	  // Sync internal and external buffers.
  	  if (__testout && this->_M_out_beg < this->_M_out_lim)
! 	    this->overflow();
  
  	  if (_M_buf_size > 1)
  	    {
*************** namespace std
*** 324,387 ****
    template<typename _CharT, typename _Traits>
      typename basic_filebuf<_CharT, _Traits>::int_type 
      basic_filebuf<_CharT, _Traits>::
-     _M_overflow(int_type __c)
-     {
-       int_type __ret = traits_type::eof();
-       const bool __testeof = traits_type::eq_int_type(__c, __ret);
-       const bool __testput = this->_M_out_beg < this->_M_out_lim;
- 
-       if (__testput)
-  	{
-  	  // 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 appropriate, append the overflow char.
- 	  if (!__testeof)
- 	    *this->_M_out_lim++ = traits_type::to_char_type(__c);
- 
- 	  // Convert pending sequence to external representation,
- 	  // output. 
- 	  if (_M_convert_to_external(this->_M_out_beg,
- 				     this->_M_out_lim - this->_M_out_beg)
- 	      && (!__testeof || (__testeof && !_M_file.sync())))
- 	    {
- 	      _M_set_buffer(0);
- 	      __ret = traits_type::not_eof(__c);
- 	    }
- 	}
-       _M_last_overflowed = true;	
-       return __ret;
-     }
- 
-   template<typename _CharT, typename _Traits>
-     typename basic_filebuf<_CharT, _Traits>::int_type 
-     basic_filebuf<_CharT, _Traits>::
      overflow(int_type __c)
      {
        int_type __ret = traits_type::eof();
!       const bool __testput = this->_M_out_cur < this->_M_out_end;
        const bool __testout = this->_M_mode & ios_base::out;
        
-       // Perhaps set below in _M_overflow.
-       _M_last_overflowed = false;
- 
        if (__testout)
  	{
! 	  if (traits_type::eq_int_type(__c, traits_type::eof()))
! 	    __ret = traits_type::not_eof(__c);
! 	  else if (__testput)
  	    {
!  	      *this->_M_out_cur = traits_type::to_char_type(__c);
! 	      _M_move_out_cur(1);
! 	      __ret = traits_type::not_eof(__c);
  	    }
- 	  else 
- 	    __ret = this->_M_overflow(__c);
  	}
        return __ret;
      }
    
--- 324,369 ----
    template<typename _CharT, typename _Traits>
      typename basic_filebuf<_CharT, _Traits>::int_type 
      basic_filebuf<_CharT, _Traits>::
      overflow(int_type __c)
      {
        int_type __ret = traits_type::eof();
!       const bool __testeof = traits_type::eq_int_type(__c, __ret);
        const bool __testout = this->_M_mode & ios_base::out;
        
        if (__testout)
  	{
! 	  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 appropriate, append the overflow char.
! 	      if (!__testeof)
! 		*this->_M_out_lim++ = traits_type::to_char_type(__c);
! 	      
! 	      // Convert pending sequence to external representation,
! 	      // output.
! 	      if (_M_convert_to_external(this->_M_out_beg,
! 					 this->_M_out_lim - this->_M_out_beg)
! 		  && (!__testeof || (__testeof && !_M_file.sync())))
! 		{
! 		  _M_set_buffer(0);
! 		  __ret = traits_type::not_eof(__c);
! 		}
! 	    }
! 	  else
  	    {
! 	      // Unbuffered.
! 	      char_type __conv = traits_type::to_char_type(__c);
! 	      if (!__testeof && _M_convert_to_external(&__conv, 1))
! 		__ret = __c;
  	    }
  	}
+       _M_last_overflowed = true;	
        return __ret;
      }
    
Index: include/bits/streambuf.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/streambuf.tcc,v
retrieving revision 1.38
diff -c -p -r1.38 streambuf.tcc
*** include/bits/streambuf.tcc	2 May 2003 18:35:24 -0000	1.38
--- include/bits/streambuf.tcc	26 May 2003 14:51:19 -0000
*************** namespace std 
*** 115,121 ****
        while (__ret < __n)
  	{
  	  const size_t __buf_len = _M_in_end - _M_in_cur;
! 	  if (__buf_len > 0)
  	    {
  	      const size_t __remaining = __n - __ret;
  	      const size_t __len = std::min(__buf_len, __remaining);
--- 115,121 ----
        while (__ret < __n)
  	{
  	  const size_t __buf_len = _M_in_end - _M_in_cur;
! 	  if (__buf_len)
  	    {
  	      const size_t __remaining = __n - __ret;
  	      const size_t __len = std::min(__buf_len, __remaining);
*************** namespace std 
*** 149,155 ****
        while (__ret < __n)
  	{
  	  const size_t __buf_len = _M_out_end - _M_out_cur;
! 	  if (__buf_len > 0)
  	    {
  	      const size_t __remaining = __n - __ret;
  	      const size_t __len = std::min(__buf_len, __remaining);
--- 149,155 ----
        while (__ret < __n)
  	{
  	  const size_t __buf_len = _M_out_end - _M_out_cur;
! 	  if (__buf_len)
  	    {
  	      const size_t __remaining = __n - __ret;
  	      const size_t __len = std::min(__buf_len, __remaining);
*************** namespace std 
*** 161,167 ****
  
  	  if (__ret < __n)
  	    {
! 	      const int_type __c = this->overflow(traits_type::to_int_type(*__s));
  	      if (!traits_type::eq_int_type(__c, traits_type::eof()))
  		{
  		  ++__ret;
--- 161,167 ----
  
  	  if (__ret < __n)
  	    {
! 	      int_type __c = this->overflow(traits_type::to_int_type(*__s));
  	      if (!traits_type::eq_int_type(__c, traits_type::eof()))
  		{
  		  ++__ret;
Index: include/std/std_fstream.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_fstream.h,v
retrieving revision 1.40
diff -c -p -r1.40 std_fstream.h
*** include/std/std_fstream.h	22 May 2003 22:16:40 -0000	1.40
--- include/std/std_fstream.h	26 May 2003 14:51:19 -0000
*************** namespace std
*** 158,164 ****
         *  @note pbacks of over one character are not currently supported.
         *  @endif
        */
!       char_type			_M_pback[1]; 
        char_type*		_M_pback_cur_save;
        char_type*		_M_pback_end_save;
        bool			_M_pback_init; 
--- 158,164 ----
         *  @note pbacks of over one character are not currently supported.
         *  @endif
        */
!       char_type			_M_pback; 
        char_type*		_M_pback_cur_save;
        char_type*		_M_pback_end_save;
        bool			_M_pback_init; 
*************** namespace std
*** 177,183 ****
  	  {
  	    _M_pback_cur_save = this->_M_in_cur;
  	    _M_pback_end_save = this->_M_in_end;
! 	    this->setg(_M_pback, _M_pback, _M_pback + 1);
  	    _M_pback_init = true;
  	  }
        }
--- 177,183 ----
  	  {
  	    _M_pback_cur_save = this->_M_in_cur;
  	    _M_pback_end_save = this->_M_in_end;
! 	    this->setg(&_M_pback, &_M_pback, &_M_pback + 1);
  	    _M_pback_init = true;
  	  }
        }
*************** namespace std
*** 191,198 ****
  	if (_M_pback_init)
  	  {
  	    // Length _M_in_cur moved in the pback buffer.
! 	    const size_t __off_cur = this->_M_in_cur - _M_pback;
! 	    this->setg(this->_M_buf, _M_pback_cur_save + __off_cur, 
  		       _M_pback_end_save);
  	    _M_pback_init = false;
  	  }
--- 191,198 ----
  	if (_M_pback_init)
  	  {
  	    // Length _M_in_cur moved in the pback buffer.
! 	    const size_t __off = this->_M_in_cur == &_M_pback ? 0 : 1;
! 	    this->setg(this->_M_buf, _M_pback_cur_save + __off, 
  		       _M_pback_end_save);
  	    _M_pback_init = false;
  	  }
*************** namespace std
*** 311,329 ****
        virtual int_type
        pbackfail(int_type __c = _Traits::eof());
  
-       // NB: For what the standard expects of the overflow function,
-       // see _M_overflow(), below. Because basic_streambuf's
-       // sputc/sputn call overflow directly, and the complications of
-       // this implementation's setting of the initial pointers all
-       // equal to _M_buf when initializing, it seems essential to have
-       // this in actuality be a helper function that checks for the
-       // eccentricities of this implementation, and then call
-       // overflow() if indeed the buffer is full.
- 
-       // [documentation is inherited]
-       virtual int_type
-       overflow(int_type __c = _Traits::eof());
- 
        // Stroustrup, 1998, p 648
        // The overflow() function is called to transfer characters to the
        // real output destination when the buffer is full. A call to
--- 311,316 ----
*************** namespace std
*** 336,343 ****
         *  @doctodo
         *  @endif
        */
!       int_type
!       _M_overflow(int_type __c = _Traits::eof());
  
        // Convert internal byte sequence to external, char-based
        // sequence via codecvt.
--- 323,330 ----
         *  @doctodo
         *  @endif
        */
!       virtual int_type
!       overflow(int_type __c = _Traits::eof());
  
        // Convert internal byte sequence to external, char-based
        // sequence via codecvt.
*************** namespace std
*** 389,395 ****
  	    off_type __off = this->_M_out_cur - this->_M_out_lim;
  
  	    // _M_file.sync() will be called within
! 	    if (traits_type::eq_int_type(_M_overflow(), traits_type::eof()))
  	      __ret = -1;
  	    else if (__off)
  	      _M_file.seekoff(__off, ios_base::cur);
--- 376,382 ----
  	    off_type __off = this->_M_out_cur - this->_M_out_lim;
  
  	    // _M_file.sync() will be called within
! 	    if (traits_type::eq_int_type(this->overflow(), traits_type::eof()))
  	      __ret = -1;
  	    else if (__off)
  	      _M_file.seekoff(__off, ios_base::cur);
*************** namespace std
*** 444,450 ****
  
        // This function sets the pointers of the internal buffer, both get
        // and put areas. Typically, __off == _M_in_end - _M_in_beg upon
!       // _M_underflow; __off == 0 upon _M_overflow, seekoff, open, setbuf.
        // 
        // NB: _M_out_end - _M_out_beg == _M_buf_size - 1, since _M_buf_size
        // reflects the actual allocated memory and the last cell is reserved
--- 431,437 ----
  
        // This function sets the pointers of the internal buffer, both get
        // and put areas. Typically, __off == _M_in_end - _M_in_beg upon
!       // _M_underflow; __off == 0 upon overflow, seekoff, open, setbuf.
        // 
        // NB: _M_out_end - _M_out_beg == _M_buf_size - 1, since _M_buf_size
        // reflects the actual allocated memory and the last cell is reserved
Index: testsuite/27_io/basic_filebuf/sputc/char/2.cc
===================================================================
RCS file: testsuite/27_io/basic_filebuf/sputc/char/2.cc
diff -N testsuite/27_io/basic_filebuf/sputc/char/2.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/27_io/basic_filebuf/sputc/char/2.cc	26 May 2003 14:51:20 -0000
***************
*** 0 ****
--- 1,129 ----
+ // 2003-05-21 Benjamin Kosnik  <bkoz@redhat.com>
+ 
+ // Copyright (C) 2003 Free Software Foundation, Inc.
+ //
+ // This file is part of the GNU ISO C++ Library.  This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ 
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ // GNU General Public License for more details.
+ 
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING.  If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+ 
+ // 27.8.1.4 Overridden virtual functions
+ 
+ #include <fstream>
+ #include <testsuite_hooks.h>
+ 
+ // @require@ %-*.tst %-*.txt
+ // @diff@ %-*.tst %*.txt
+ 
+ // NB: This test assumes that _M_buf_size == 40, and not the usual
+ // buffer_size length of BUFSIZ (8192), so that overflow/underflow can be
+ // simulated a bit more readily.
+ // NRB (Nota Really Bene): setting it to 40 breaks the test, as intended.
+ const int buffer_size = 8192;
+ //const int buffer_size = 40;
+ 
+ const char name_01[] = "filebuf_virtuals-1.txt"; // file with data in it
+ const char name_02[] = "filebuf_virtuals-2.txt"; // empty file, need to create
+ const char name_03[] = "filebuf_virtuals-3.txt"; // empty file, need to create
+ 
+ class derived_filebuf: public std::filebuf
+ {
+  public:
+   void
+   set_size(int_type __size) { _M_buf_size = __size; }
+ };
+ 
+ derived_filebuf fb_01; // in 
+ derived_filebuf fb_02; // out
+ derived_filebuf fb_03; // in | out
+ 
+ // Initialize filebufs to be the same size regardless of platform.
+ void test03()
+ {
+   fb_01.set_size(buffer_size);
+   fb_02.set_size(buffer_size);
+   fb_03.set_size(buffer_size);
+ }
+ 
+ // Test overloaded virtual functions.
+ void test05() 
+ {
+   typedef std::filebuf::int_type 	int_type;
+   typedef std::filebuf::traits_type 	traits_type;
+   typedef std::filebuf::pos_type 	pos_type;
+   typedef std::filebuf::off_type 	off_type;
+   typedef size_t 			size_type;
+ 
+   bool 					test = true;
+   std::filebuf 				f_tmp;
+   std::streamsize 			strmsz_1, strmsz_2;
+   std::streamoff  			strmof_1, strmof_2;
+   int 					i = 0, j = 0, k = 0;
+ 
+   // Unbuffered
+   fb_01.pubsetbuf(0, 0);
+   fb_02.pubsetbuf(0, 0);
+   fb_03.pubsetbuf(0, 0);
+ 
+   fb_01.open(name_01, std::ios_base::in);
+   fb_02.open(name_02, std::ios_base::out | std::ios_base::trunc);
+   fb_03.open(name_03, std::ios_base::out | std::ios_base::in | std::ios_base::trunc);
+ 
+   int_type c1 = fb_01.sbumpc();
+   int_type c2 = fb_02.sbumpc();
+   int_type c3 = fb_01.sbumpc();
+   int_type c4 = fb_02.sbumpc();
+   int_type c5 = fb_03.sbumpc();
+   int_type c6 = fb_01.sgetc();
+   int_type c7 = fb_02.sgetc();
+   int_type c8 = fb_01.sgetc();
+   int_type c9 = fb_02.sgetc();
+ 
+   // PUT
+   // int_type sputc(char_type c)
+   // if out_cur not avail, return overflow(traits_type::to_int_type(c)) 
+   // else, stores c at out_cur,
+   // increments out_cur, and returns c as int_type
+   // strmsz_1 = fb_03.in_avail();  // XXX valid for in|out??
+   c1 = fb_02.sputc('a'); 
+   c2 = fb_03.sputc('b'); 
+   VERIFY( c1 != c2 );
+   c1 = fb_02.sputc('c'); 
+   c2 = fb_03.sputc('d'); 
+   VERIFY( c1 != c2 );
+   // strmsz_2 = fb_03.in_avail();
+   // VERIFY( strmsz_1 != strmsz_2 );
+   for (int i = 50; i <= 90; ++i) 
+     c2 = fb_02.sputc(char(i));
+   // 27filebuf-2.txt == ac23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+   // fb_02._M_out_cur = '2'
+   strmsz_1 = fb_03.in_avail();
+   for (int i = 50; i <= 90; ++i) 
+     c2 = fb_03.sputc(char(i));
+   strmsz_2 = fb_03.in_avail();
+   // VERIFY( strmsz_1 != strmsz_2 );
+   // VERIFY( strmsz_1 > 0 );
+   // VERIFY( strmsz_2 > 0 );
+   // 27filebuf-2.txt == bd23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+   // fb_02._M_out_cur = '2'
+   c3 = fb_01.sputc('a'); // should be EOF because this is read-only
+   VERIFY( c3 == traits_type::eof() );
+ }
+ 
+ main() 
+ {
+   test03();
+   test05();
+   return 0;
+ }
Index: testsuite/27_io/basic_filebuf/sputn/char/9339.cc
===================================================================
RCS file: testsuite/27_io/basic_filebuf/sputn/char/9339.cc
diff -N testsuite/27_io/basic_filebuf/sputn/char/9339.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/27_io/basic_filebuf/sputn/char/9339.cc	26 May 2003 14:51:20 -0000
***************
*** 0 ****
--- 1,46 ----
+ // Copyright (C) 2003 Free Software Foundation, Inc.
+ //
+ // This file is part of the GNU ISO C++ Library.  This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ 
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ // GNU General Public License for more details.
+ 
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING.  If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+ 
+ #include <fstream>
+ #include <testsuite_hooks.h>
+ 
+ // libstdc++/9339
+ void test01()
+ {
+   using namespace std;
+   bool test = true;
+ 
+   filebuf fbuf01;
+   int len = 35;
+   fbuf01.pubsetbuf(0, 0);
+   fbuf01.open("tmp_9339", ios_base::out | ios_base::trunc);
+   streamsize s1 = fbuf01.sputn("Pete Goldlust @ Carl Hammer Gallery", len);
+   VERIFY( s1 == len );
+ 
+   filebuf fbuf02;
+   char buf[256];
+   fbuf02.open("tmp_9339", ios_base::in);
+   streamsize s2 = fbuf02.sgetn(buf, 256);
+   VERIFY( s2 == len );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }


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