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]

[FYI] Forward movement on 9404


Hi,

in case someone would like to help on testing/adding comments and
what else, before taking a little bit of sleep I'm sending my current
best attempt at fixing 9404 in a clean way, i.e., implementing the
more general points of Nathan's outline for a post-DR169 asset.

I'm quite happy with it! Of course the regression tests are ok and
everything seems quite clean: overflow now happens _always_ when it
should (pptr == epptr) both for filestreams and stringstreams.

I would appreciate, in particular, some help on the legacy <strstream>
bits, which must be broken right now.

Ciao, Paolo

//////////
diff -urN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
--- libstdc++-v3-orig/include/bits/fstream.tcc	2003-02-16 20:02:52.000000000 +0100
+++ libstdc++-v3/include/bits/fstream.tcc	2003-02-21 21:45:11.000000000 +0100
@@ -49,7 +49,8 @@
 	  this->_M_buf_size = this->_M_buf_size_opt;
 
 	  // Allocate internal buffer.
-	  this->_M_buf = new char_type[this->_M_buf_size]; 
+	  this->_M_buf = new char_type[this->_M_buf_size];
+	  this->_M_out_end = this->_M_buf + this->_M_buf_size;
 	  _M_buf_allocated = true;
 	}
     }
@@ -125,7 +126,7 @@
 	{
 	  const int_type __eof = traits_type::eof();
 	  bool __testput = this->_M_out_cur
-	    && this->_M_out_beg < this->_M_out_end;
+	    && this->_M_out_beg < this->_M_out_lim;
 	  if (__testput 
 	      && traits_type::eq_int_type(_M_really_overflow(__eof), __eof))
 	    return __ret;
@@ -245,8 +246,7 @@
     overflow(int_type __c)
     {
       int_type __ret = traits_type::eof();
-      bool __testput = this->_M_out_cur
-	&& this->_M_out_cur < this->_M_buf + this->_M_buf_size;
+      bool __testput = this->_M_out_cur && _M_out_buf_size();
       bool __testout = this->_M_mode & ios_base::out;
       
       if (__testout)
@@ -314,7 +314,7 @@
 	  if (__r == codecvt_base::partial)
 	    {
 	      const char_type* __iresume = __iend;
-	      streamsize __rlen = this->_M_out_end - __iend;
+	      streamsize __rlen = this->_M_out_lim - __iend;
 	      __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen, 
 			      __iend, __buf, __buf + __blen, __bend);
 	      if (__r != codecvt_base::error)
@@ -336,7 +336,7 @@
     _M_really_overflow(int_type __c)
     {
       int_type __ret = traits_type::eof();
-      bool __testput = this->_M_out_cur && this->_M_out_beg < this->_M_out_end;
+      bool __testput = this->_M_out_cur && this->_M_out_beg < this->_M_out_lim;
       bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size_opt;
 
       if (__testput || __testunbuffered)
@@ -358,7 +358,7 @@
 	  // NB: In the unbuffered case, no internal buffer exists. 
 	  if (!__testunbuffered)
 	    _M_convert_to_external(this->_M_out_beg,
-				   this->_M_out_end - this->_M_out_beg, 
+				   this->_M_out_lim - this->_M_out_beg, 
 				   __elen, __plen);
 
 	  // Convert pending sequence to external representation, output.
@@ -404,6 +404,7 @@
 	  // Step 2: Use the external array.
 	  this->_M_buf = __s;
 	  this->_M_buf_size_opt = this->_M_buf_size = __n;
+	  this->_M_out_end = this->_M_buf + this->_M_buf_size;
 	  _M_set_indeterminate();
 	}
       _M_last_overflowed = false;	
@@ -437,7 +438,7 @@
 	      bool __testget = this->_M_in_cur
 		&& this->_M_in_beg < this->_M_in_end;
 	      bool __testput = this->_M_out_cur
-		&& this->_M_out_beg < this->_M_out_end;
+		&& this->_M_out_beg < this->_M_out_lim;
 	      // Sync the internal and external streams.
 	      // out
 	      if (__testput || _M_last_overflowed)
diff -urN libstdc++-v3-orig/include/bits/sstream.tcc libstdc++-v3/include/bits/sstream.tcc
--- libstdc++-v3-orig/include/bits/sstream.tcc	2003-02-20 02:09:53.000000000 +0100
+++ libstdc++-v3/include/bits/sstream.tcc	2003-02-21 23:53:26.000000000 +0100
@@ -82,7 +82,6 @@
     {
       int_type __ret = traits_type::eof();
       bool __testeof = traits_type::eq_int_type(__c, __ret);
-      bool __testwrite = this->_M_out_cur < this->_M_buf + this->_M_buf_size;
       bool __testout = this->_M_mode & ios_base::out;
 
       // Try to append __c into output sequence in one of two ways.
@@ -91,18 +90,20 @@
 	{
 	  if (!__testeof)
 	    {
+	      // The following exponential grow policy can be adopted
+	      // thanks to the resolution of DR 169 (TC).
 	      __size_type __len = std::max(this->_M_buf_size, 
 					   this->_M_buf_size_opt);
 	      __len *= 2;
 
-	      if (__testwrite)
+	      if (_M_out_buf_size())
 		__ret = this->sputc(traits_type::to_char_type(__c));
 	      else if (__len <= _M_string.max_size())
 		{
 		  // Force-allocate, re-sync.
 		  _M_string = this->str();
 		  _M_string.reserve(__len);
-		  this->_M_buf_size = __len;
+		  this->_M_buf_size = _M_string.capacity();
 		  _M_really_sync(this->_M_in_cur - this->_M_in_beg, 
 				 this->_M_out_cur - this->_M_out_beg);
 		  __ret = this->sputc(traits_type::to_char_type(__c));
@@ -142,7 +143,7 @@
 	  if (__testout || __testboth)
 	    {
 	      __curo = this->pptr();
-	      __endo = this->epptr();
+	      __endo = this->_M_out_lim;
 	    }
 
 	  off_type __newoffi = 0;
@@ -205,7 +206,7 @@
 	  if (__testout || __testboth)
 	    {
 	      __beg = this->pbase();
-	      __end = this->_M_buf + this->_M_buf_size;
+	      __end = this->epptr();
 	      if (0 <= __pos && __pos <= __end - __beg)
 		__testposo = true;
 	    }
diff -urN libstdc++-v3-orig/include/std/std_fstream.h libstdc++-v3/include/std/std_fstream.h
--- libstdc++-v3-orig/include/std/std_fstream.h	2003-02-17 20:22:11.000000000 +0100
+++ libstdc++-v3/include/std/std_fstream.h	2003-02-21 23:40:11.000000000 +0100
@@ -312,14 +312,14 @@
       sync()
       {
 	bool __testput = this->_M_out_cur
-	  && this->_M_out_beg < this->_M_out_end;
+	  && this->_M_out_beg < this->_M_out_lim;
 
 	// Make sure that the internal buffer resyncs its idea of
 	// the file position with the external file.
 	if (__testput)
 	  {
 	    // Need to restore current position after the write.
-	    off_type __off = this->_M_out_cur - this->_M_out_end;
+	    off_type __off = this->_M_out_cur - this->_M_out_lim;
 	    _M_really_overflow(); // _M_file.sync() will be called within
 	    if (__off)
 	      _M_file.seekoff(__off, ios_base::cur);
@@ -387,10 +387,15 @@
       void
       _M_set_indeterminate(void)
       {
-	if (this->_M_mode & ios_base::in)
+	bool __testin = this->_M_mode & ios_base::in;
+	bool __testout = this->_M_mode & ios_base::out;
+	if (__testin)
 	  this->setg(this->_M_buf, this->_M_buf, this->_M_buf);
-	if (this->_M_mode & ios_base::out)
-	  this->setp(this->_M_buf, this->_M_buf);
+	if (__testout)
+	  {
+	    this->_M_out_beg = this->_M_out_cur = this->_M_buf;
+	    this->_M_out_lim = this->_M_buf;
+	  }
 	_M_filepos = this->_M_buf;
       }
 
@@ -407,7 +412,10 @@
 	if (__testin)
 	  this->setg(this->_M_buf, this->_M_buf, this->_M_buf + __off);
 	if (__testout)
-	  this->setp(this->_M_buf, this->_M_buf + __off);
+	  {
+	    this->_M_out_beg = this->_M_out_cur = this->_M_buf;
+	    this->_M_out_lim = this->_M_buf + __off;
+	  }
 	_M_filepos = this->_M_buf + __off;
       }
 
@@ -428,7 +436,7 @@
 		&& this->_M_in_cur == this->_M_in_end;
 	    if (this->_M_mode & ios_base::out)
 	      __ret = this->_M_out_beg == this->_M_out_cur
-		&& this->_M_out_cur == this->_M_out_end;
+		&& this->_M_out_cur == this->_M_out_lim;
 	  }
 	return __ret;
       }
diff -urN libstdc++-v3-orig/include/std/std_sstream.h libstdc++-v3/include/std/std_sstream.h
--- libstdc++-v3-orig/include/std/std_sstream.h	2003-02-18 14:29:19.000000000 +0100
+++ libstdc++-v3/include/std/std_sstream.h	2003-02-21 22:23:54.000000000 +0100
@@ -140,8 +140,8 @@
 	    // _M_string, and may not be the correct size of the
 	    // current stringbuf internal buffer.
 	    __size_type __len = _M_string.size();
-	    if (this->_M_out_end > this->_M_out_beg)
-	      __len = std::max(__size_type(this->_M_out_end 
+	    if (this->_M_out_lim > this->_M_out_beg)
+	      __len = std::max(__size_type(this->_M_out_lim 
 					   - this->_M_out_beg), __len);
 	    return __string_type(this->_M_out_beg, this->_M_out_beg + __len);
 	  }
@@ -179,8 +179,8 @@
 	// necessary as ostringstreams are implemented with the
 	// streambufs having control of the allocation and
 	// re-allocation of the internal string object, _M_string.
-	this->_M_buf_size = _M_string.size();
-
+	this->_M_buf_size = _M_string.capacity();
+ 
 	// NB: Start ostringstream buffers at 512 bytes. This is an
 	// experimental value (pronounced "arbitrary" in some of the
 	// hipper english-speaking countries), and can be changed to
@@ -188,7 +188,7 @@
 	this->_M_buf_size_opt = 512;
 	this->_M_mode = __mode;
 	if (this->_M_mode & (ios_base::ate | ios_base::app))
-	  _M_really_sync(0, this->_M_buf_size);
+	  _M_really_sync(0, _M_string.size());
 	else
 	  _M_really_sync(0, 0);
       }
@@ -268,7 +268,8 @@
 	    this->setg(__base, __base + __i, __base + __len);
 	if (__testout)
 	  {
-	    this->setp(__base, __base + __len);
+	    this->setp(__base, __base + this->_M_buf_size);
+	    this->_M_out_lim = __base + __len;
 	    this->_M_out_cur += __o;
 	  }
 	return 0;
diff -urN libstdc++-v3-orig/include/std/std_streambuf.h libstdc++-v3/include/std/std_streambuf.h
--- libstdc++-v3-orig/include/std/std_streambuf.h	2003-01-23 23:53:35.000000000 +0100
+++ libstdc++-v3/include/std/std_streambuf.h	2003-02-21 23:51:12.000000000 +0100
@@ -207,7 +207,9 @@
       char_type* 		_M_in_end;	// End of get area. 
       char_type* 		_M_out_beg; 	// Start of put area. 
       char_type* 		_M_out_cur;  	// Current put area. 
-      char_type* 		_M_out_end;  	// End of put area. 
+      char_type* 		_M_out_end;  	// End of put area.
+
+      char_type*                _M_out_lim;     // Right limit of used put area.
       //@}
 
       /**
@@ -305,11 +307,11 @@
       }
 
       // Correctly sets the _M_out_cur pointer, and bumps the
-      // appropriate _M_*_end pointers as well. Necessary for the
-      // un-tied stringbufs, in in|out mode.
+      // appropriate _M_out_lim and _M_in_end pointers as well. Necessary
+      // for the un-tied stringbufs, in in|out mode.
       // Invariant:
-      // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
-      // Assuming all _M_*_[beg, cur, end] pointers are operating on
+      // __n + _M_out_[cur, lim] <= _M_buf + _M_buf_size
+      // Assuming all _M_out_[beg, cur, lim] pointers are operating on
       // the same range:
       // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
       void 
@@ -320,32 +322,23 @@
 	_M_out_cur += __n;
 	if (__testin && _M_buf_unified)
 	  _M_in_cur += __n;
-	if (_M_out_cur > _M_out_end)
+	if (_M_out_cur > _M_out_lim)
 	  {
-	    _M_out_end = _M_out_cur;
+	    _M_out_lim = _M_out_cur;
 	    // NB: in | out buffers drag the _M_in_end pointer along...
 	    if (__testin)
 	      _M_in_end += __n;
 	  }
       }
 
-      // Return the size of the output buffer.  This depends on the
-      // buffer in use: allocated buffers have a stored size in
-      // _M_buf_size and setbuf() buffers don't.
+      // Returns zero if the output buffer is full (-> overflow).
       off_type
       _M_out_buf_size()
       {
-	off_type __ret = 0;
 	if (_M_out_cur)
-	  {
-	    // Using allocated buffer.
-	    if (_M_out_beg == _M_buf)
-	      __ret = _M_out_beg + _M_buf_size - _M_out_cur;
-	    // Using non-allocated buffer.
-	    else
-	      __ret = _M_out_end - _M_out_cur;
-	  }
-	return __ret;
+	  return _M_out_end - _M_out_cur;
+	else
+	  return off_type(0);
       }
 
   public:
@@ -569,7 +562,7 @@
       basic_streambuf()
       : _M_buf(NULL), _M_buf_size(0), _M_buf_size_opt(BUFSIZ), 
       _M_buf_unified(false), _M_in_beg(0), _M_in_cur(0), _M_in_end(0), 
-      _M_out_beg(0), _M_out_cur(0), _M_out_end(0), 
+	_M_out_beg(0), _M_out_cur(0), _M_out_end(0), _M_out_lim(0),
       _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()), 
       _M_pback_cur_save(0), _M_pback_end_save(0), 
       _M_pback_init(false)
@@ -666,7 +659,7 @@
       setp(char_type* __pbeg, char_type* __pend)
       { 
 	_M_out_beg = _M_out_cur = __pbeg; 
-	_M_out_end = __pend; 
+	_M_out_end = __pend;
 	if (!(_M_mode & ios_base::out) && __pbeg && __pend)
 	  _M_mode = _M_mode | ios_base::out;
       }
diff -urN libstdc++-v3-orig/testsuite/27_io/stringbuf_virtuals.cc libstdc++-v3/testsuite/27_io/stringbuf_virtuals.cc
--- libstdc++-v3-orig/testsuite/27_io/stringbuf_virtuals.cc	2003-01-23 23:53:35.000000000 +0100
+++ libstdc++-v3/testsuite/27_io/stringbuf_virtuals.cc	2003-02-21 22:02:44.000000000 +0100
@@ -92,6 +92,45 @@
   VERIFY( ob.getloc() == loc_de );
 }
 
+bool called = false;
+
+class Derived_stringbuf : public std::stringbuf
+{
+public:
+  int_type overflow(int_type c)
+  {
+    called = true;
+    return std::stringbuf::overflow(c);
+  }
+  
+  const char_type* pub_epptr() const
+  {
+    return epptr();
+  }
+  
+  const char_type* pub_pptr() const
+  {
+    return pptr();
+  }
+};
+
+// libstdc++/9404
+void test09()
+{
+  bool test = true;
+
+  Derived_stringbuf dsbuf;
+  dsbuf.sputc('s');
+  VERIFY( called );
+  
+  called = false;
+  dsbuf.sputc('i');
+  VERIFY( !called );
+
+  dsbuf.sputc('l');
+  VERIFY( dsbuf.str() == "sil" );
+}
+
 int main() 
 {
   using namespace std;
@@ -106,5 +145,6 @@
   test02(in3, false);
 
   test08();
+  test09();
   return 0;
 }

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