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]

[Patch] Step1: don't use _M_out_lim in stringbuf, etc...


Hi,

this is the first step of the planned major changes to
filebuf, stringbuf (and streambuf): I briefly recall here to
the casual reader that the final goal is that of removing
completely any use of _M_out_lim and having filebuf non
unified, thus simplifying _M_move_out_cur and _M_move_in_cur
to their bare bones pbump and gbump. This means better
performance for *all* the streambuf inlines.

In the first step, which brings stringbuf very close to its
final form, we stop using _M_out_lim in stringbuf,
replaced instead by egptr(). The latter is updated by
the virtuals, as part of _M_sync inner logic or via
the new specific _M_update_egptr.

For details, see the Changelog entry.

I took the occasion to start using the correct documented
interface to streambuf (gptr(), pbump, setp, etc, etc) in
sstream.tcc and std_sstream.h.

Tested x86-linux, ok with everyone?

Paolo.

///////////
2003-06-20  Paolo Carlini  <pcarlini@unitus.it>
	    Nathan C. Myers  <ncm-nospam@cantrip.org>


	* include/std/std_streambuf.h (_M_move_out_cur): _M_out_lim
	is now used only for filebuf, when _M_buf_unified is true.
	epgtr() plays the role of _M_out_lim but it's only updated
	upon overflow, underflow, uflow, seekoff/pos.
	* include/bits/sstream.tcc (_M_underflow): New, implements
	stringbuf::underflow and uflow.
	(seekoff, seekpos): Tweak, use  _M_update_egptr.
	* include/std/std_sstream.h (str): Rewrote, deal correctly
	with the current logic, in particular, when pptr() > egptr().
	(_M_sync): When __testout && !__testin set all the get area
	pointers to the current string end.
	(_M_update_egptr): New, internal function updating egptr()
	to the actual string end.
	(_M_underflow): New, declare.
	(underflow): Dispatch to _M_underflow(false).
	(uflow): Dispatch to _M_underflow(true).

	* include/bits/sstream.tcc (pbackfail, overflow, seekoff,
	seekpos): Use only the documented derivation interface to
	basic_streambuf (gptr(), setg(), etc.) to work right with
	user specializations.
	* include/std/std_sstream.h (str, _M_sync): Likewise.
diff -cprN libstdc++-v3-orig/include/bits/sstream.tcc libstdc++-v3/include/bits/sstream.tcc
*** libstdc++-v3-orig/include/bits/sstream.tcc	Wed Jun 18 20:34:09 2003
--- libstdc++-v3/include/bits/sstream.tcc	Fri Jun 20 12:33:21 2003
*************** namespace std
*** 49,59 ****
        int_type __ret = traits_type::eof();
        const bool __testeof = traits_type::eq_int_type(__c, __ret);
        
!       if (this->_M_in_beg < this->_M_in_cur)
  	{
  	  const bool __testeq = traits_type::eq(traits_type::to_char_type(__c),
! 						this->_M_in_cur[-1]);
! 	  --this->_M_in_cur;
  
  	  // Try to put back __c into input sequence in one of three ways.
  	  // Order these tests done in is unspecified by the standard.
--- 49,59 ----
        int_type __ret = traits_type::eof();
        const bool __testeof = traits_type::eq_int_type(__c, __ret);
        
!       if (this->eback() < this->gptr())
  	{
  	  const bool __testeq = traits_type::eq(traits_type::to_char_type(__c),
! 						this->gptr()[-1]);
! 	  this->gbump(-1);
  
  	  // Try to put back __c into input sequence in one of three ways.
  	  // Order these tests done in is unspecified by the standard.
*************** namespace std
*** 63,69 ****
  	    __ret = traits_type::not_eof(__c);
  	  else
  	    {
! 	      *this->_M_in_cur = traits_type::to_char_type(__c);
  	      __ret = __c;
  	    }
  	}
--- 63,69 ----
  	    __ret = traits_type::not_eof(__c);
  	  else
  	    {
! 	      *this->gptr() = traits_type::to_char_type(__c);
  	      __ret = __c;
  	    }
  	}
*************** namespace std
*** 88,96 ****
        // experimental value (pronounced "arbitrary" in some of the
        // hipper english-speaking countries), and can be changed to
        // suit particular needs.
!       __size_type __len = std::max(__size_type(_M_string.capacity() + 1),
! 				   __size_type(512));
!       const bool __testput = this->_M_out_cur < this->_M_out_end;
        if (__builtin_expect(!__testput && __len > _M_string.max_size(), false))
  	return traits_type::eof();
  
--- 88,96 ----
        // experimental value (pronounced "arbitrary" in some of the
        // hipper english-speaking countries), and can be changed to
        // suit particular needs.
!       const __size_type __len = std::max(__size_type(_M_string.capacity() + 1),
! 					 __size_type(512));
!       const bool __testput = this->pptr() < this->epptr();
        if (__builtin_expect(!__testput && __len > _M_string.max_size(), false))
  	return traits_type::eof();
  
*************** namespace std
*** 103,121 ****
  	  // growth policy builtin into basic_string.
  	  __string_type __tmp;
  	  __tmp.reserve(__len);
! 	  __tmp.assign(_M_string.data(),
! 		       this->_M_out_end - this->_M_out_beg);
  	  _M_string.swap(__tmp);
- 	  // Just to be sure...
- 	  _M_string.reserve(__len);
  	  _M_sync(const_cast<char_type*>(_M_string.data()),
! 		  this->_M_in_cur - this->_M_in_beg, 
! 		  this->_M_out_cur - this->_M_out_beg);
  	}
        return this->sputc(traits_type::to_char_type(__c));
      }
  
    template <class _CharT, class _Traits, class _Alloc>
      typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
      basic_stringbuf<_CharT, _Traits, _Alloc>::
      seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
--- 103,140 ----
  	  // growth policy builtin into basic_string.
  	  __string_type __tmp;
  	  __tmp.reserve(__len);
! 	  __tmp.assign(_M_string.data(), this->epptr() - this->pbase());
  	  _M_string.swap(__tmp);
  	  _M_sync(const_cast<char_type*>(_M_string.data()),
! 		  this->gptr() - this->eback(), 
! 		  this->pptr() - this->pbase());
  	}
        return this->sputc(traits_type::to_char_type(__c));
      }
  
    template <class _CharT, class _Traits, class _Alloc>
+     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 
+     basic_stringbuf<_CharT, _Traits, _Alloc>::
+     _M_underflow(bool __bump)
+     {
+       int_type __ret = traits_type::eof();
+       const bool __testin = this->_M_mode & ios_base::in;
+       if (__testin)
+ 	{
+ 	  // Update egptr() to match the actual string end.
+ 	  _M_update_egptr();
+ 
+ 	  if (this->gptr() < this->egptr())
+ 	    {
+ 	      __ret = traits_type::to_int_type(*this->gptr());
+ 	      if (__bump)
+ 		this->gbump(1);
+ 	    }
+ 	}
+       return __ret;
+     }
+ 
+   template <class _CharT, class _Traits, class _Alloc>
      typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
      basic_stringbuf<_CharT, _Traits, _Alloc>::
      seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
*************** namespace std
*** 129,163 ****
  
        if (_M_string.capacity() && (__testin || __testout || __testboth))
  	{
! 	  char_type* __beg = __testin ? this->_M_in_beg : this->_M_out_beg;
  
  	  off_type __newoffi = 0;
  	  off_type __newoffo = 0;
  	  if (__way == ios_base::cur)
  	    {
! 	      __newoffi = this->_M_in_cur - __beg;
! 	      __newoffo = this->_M_out_cur - __beg;
  	    }
  	  else if (__way == ios_base::end)
! 	    {
! 	      __newoffi = this->_M_in_end - __beg;
! 	      // Due to the resolution of DR169, ios_base::end
! 	      // is this->_M_out_lim, not _M_out_end.
! 	      __newoffo = this->_M_out_lim - __beg;
! 	    }
  
  	  if ((__testin || __testboth)
  	      && __newoffi + __off >= 0 
! 	      && this->_M_in_end - __beg >= __newoffi + __off)
  	    {
! 	      this->_M_in_cur = __beg + __newoffi + __off;
  	      __ret = pos_type(__newoffi);
  	    }
  	  if ((__testout || __testboth)
  	      && __newoffo + __off >= 0 
! 	      && this->_M_out_lim - __beg >= __newoffo + __off)
  	    {
! 	      this->_M_out_cur = __beg + __newoffo + __off;
  	      __ret = pos_type(__newoffo);
  	    }
  	}
--- 148,179 ----
  
        if (_M_string.capacity() && (__testin || __testout || __testboth))
  	{
! 	  char_type* __beg = __testin ? this->eback() : this->pbase();
! 
! 	  _M_update_egptr();
  
  	  off_type __newoffi = 0;
  	  off_type __newoffo = 0;
  	  if (__way == ios_base::cur)
  	    {
! 	      __newoffi = this->gptr() - __beg;
! 	      __newoffo = this->pptr() - __beg;
  	    }
  	  else if (__way == ios_base::end)
! 	    __newoffo = __newoffi = this->egptr() - __beg;
  
  	  if ((__testin || __testboth)
  	      && __newoffi + __off >= 0 
! 	      && this->egptr() - __beg >= __newoffi + __off)
  	    {
! 	      this->gbump((__beg + __newoffi + __off) - this->gptr());
  	      __ret = pos_type(__newoffi);
  	    }
  	  if ((__testout || __testboth)
  	      && __newoffo + __off >= 0 
! 	      && this->egptr() - __beg >= __newoffo + __off)
  	    {
! 	      this->pbump((__beg + __newoffo + __off) - this->pptr());
  	      __ret = pos_type(__newoffo);
  	    }
  	}
*************** namespace std
*** 176,198 ****
  	  off_type __pos = __sp; // Use streamoff operator to do conversion.
  	  const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
  	  const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
! 	  char_type* __beg = __testin ? this->_M_in_beg : this->_M_out_beg;
  	  
! 	  // NB: Ordered.
! 	  bool __testposi = false;
! 	  bool __testposo = false;
! 	  if (__testin && 0 <= __pos
! 	      && __pos <=  this->_M_in_end - __beg)
! 	    __testposi = true;
! 	  if (__testout && 0 <= __pos
! 	      && __pos <=  this->_M_out_lim - __beg)
! 	    __testposo = true;
! 	  if (__testposi || __testposo)
! 	    {
! 	      if (__testposi)
! 		this->_M_in_cur = __beg + __pos;
! 	      if (__testposo)
! 	        this->_M_out_cur = __beg + __pos;
  	      __ret = pos_type(off_type(__pos));
  	    }
  	}
--- 192,209 ----
  	  off_type __pos = __sp; // Use streamoff operator to do conversion.
  	  const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
  	  const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
! 	  char_type* __beg = __testin ? this->eback() : this->pbase();
  	  
! 	  _M_update_egptr();
! 
! 	  const bool __testpos = 0 <= __pos
! 	                         && __pos <=  this->egptr() - __beg;
! 	  if ((__testin || __testout) && __testpos)
! 	    {
! 	      if (__testin)
! 		this->gbump((__beg + __pos) - this->gptr());
! 	      if (__testout)
!                 this->pbump((__beg + __pos) - this->pptr());
  	      __ret = pos_type(off_type(__pos));
  	    }
  	}
diff -cprN libstdc++-v3-orig/include/std/std_sstream.h libstdc++-v3/include/std/std_sstream.h
*** libstdc++-v3-orig/include/std/std_sstream.h	Thu Jun 19 15:02:20 2003
--- libstdc++-v3/include/std/std_sstream.h	Fri Jun 20 14:16:33 2003
*************** namespace std
*** 133,143 ****
        __string_type
        str() const
        {
- 	__string_type __ret = _M_string;
  	const bool __testout = this->_M_mode & ios_base::out;
! 	if (__testout && this->_M_out_beg < this->_M_out_lim)
! 	  __ret = __string_type(this->_M_out_beg, this->_M_out_lim);
! 	return __ret;
        }
  
        /**
--- 133,149 ----
        __string_type
        str() const
        {
  	const bool __testout = this->_M_mode & ios_base::out;
! 	if (__testout)
! 	  {
! 	    // The current egptr() may not be the actual string end.
! 	    if (this->pptr() > this->egptr())
! 	      return __string_type(this->pbase(), this->pptr());
! 	    else
!  	      return __string_type(this->pbase(), this->egptr());
! 	  }
! 	else
! 	  return _M_string;
        }
  
        /**
*************** namespace std
*** 173,190 ****
  	_M_sync(const_cast<char_type*>(_M_string.data()), 0, __len);
        }
  
!       // Overridden virtual functions:
        // [documentation is inherited]
        virtual int_type
        underflow()
!       {
! 	int_type __ret;
! 	if (this->_M_in_cur < this->_M_in_end)
! 	  __ret = traits_type::to_int_type(*this->_M_in_cur);
! 	else
! 	  __ret = traits_type::eof();
! 	return __ret;
!       }
  
        // [documentation is inherited]
        virtual int_type
--- 179,196 ----
  	_M_sync(const_cast<char_type*>(_M_string.data()), 0, __len);
        }
  
!       int_type
!       _M_underflow(bool __bump);
! 
        // [documentation is inherited]
        virtual int_type
        underflow()
!       { return _M_underflow(false); }
! 
!       // [documentation is inherited]
!       virtual int_type
!       uflow()
!       { return _M_underflow(true); }
  
        // [documentation is inherited]
        virtual int_type
*************** namespace std
*** 250,267 ****
        {
  	const bool __testin = this->_M_mode & ios_base::in;
  	const bool __testout = this->_M_mode & ios_base::out;
! 	__size_type __len = _M_string.size();
  
  	if (__testin)
  	  this->setg(__base, __base + __i, __base + __len);
  	if (__testout)
  	  {
  	    this->setp(__base, __base + _M_string.capacity());
! 	    // _M_out_lim points to the string end.
! 	    this->_M_out_lim += __len;
! 	    this->_M_out_cur += __o;
  	  }
        }
      };
  
  
--- 256,292 ----
        {
  	const bool __testin = this->_M_mode & ios_base::in;
  	const bool __testout = this->_M_mode & ios_base::out;
! 	const __size_type __len = _M_string.size();
  
  	if (__testin)
  	  this->setg(__base, __base + __i, __base + __len);
  	if (__testout)
  	  {
  	    this->setp(__base, __base + _M_string.capacity());
! 	    this->pbump(__o);
! 	    // We need a pointer to the string end anyway, even when
! 	    // !__testin: in that case, however, for the correct
! 	    // functioning of the streambuf inlines all the get area
! 	    // pointers must be identical.
! 	    if (!__testin)
! 	      this->setg(__base + __len, __base + __len, __base + __len);
  	  }
        }
+ 
+       // Internal function for correctly updating egptr() to the actual
+       // string end.
+       void
+       _M_update_egptr()
+       {
+ 	const bool __testin = this->_M_mode & ios_base::in;
+ 	const bool __testout = this->_M_mode & ios_base::out;
+ 
+ 	if (__testout && this->pptr() > this->egptr())
+ 	  if (__testin)
+ 	    this->setg(this->eback(), this->gptr(), this->pptr());
+ 	  else
+ 	    this->setg(this->pptr(), this->pptr(), this->pptr());
+       }
      };
  
  
diff -cprN libstdc++-v3-orig/include/std/std_streambuf.h libstdc++-v3/include/std/std_streambuf.h
*** libstdc++-v3-orig/include/std/std_streambuf.h	Wed Jun 11 00:00:43 2003
--- libstdc++-v3/include/std/std_streambuf.h	Fri Jun 20 00:02:29 2003
*************** namespace std
*** 238,254 ****
        void 
        _M_move_out_cur(off_type __n) // argument needs to be +-
        {
- 	const bool __testin = _M_in_cur;
- 
  	_M_out_cur += __n;
! 	if (__testin && _M_buf_unified)
! 	  _M_in_cur += __n;
! 	if (_M_out_cur > _M_out_lim)
  	  {
! 	    _M_out_lim = _M_out_cur;
! 	    // NB: in | out buffers drag the _M_in_end pointer along...
  	    if (__testin)
! 	      _M_in_end += __n;
  	  }
        }
  
--- 238,256 ----
        void 
        _M_move_out_cur(off_type __n) // argument needs to be +-
        {
  	_M_out_cur += __n;
! 	if (__builtin_expect(_M_buf_unified, false))
  	  {
! 	    const bool __testin = _M_in_cur;
  	    if (__testin)
! 	      _M_in_cur += __n;
! 	    if (_M_out_cur > _M_out_lim)
! 	      {
! 		_M_out_lim = _M_out_cur;
! 		// NB: in | out buffers drag the _M_in_end pointer along...
! 		if (__testin)
! 		  _M_in_end += __n;
! 	      }
  	  }
        }
  

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