This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Reimplement (and split) istream::ignore
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Sun, 20 Jun 2004 17:22:02 +0200
- Subject: [Patch] Reimplement (and split) istream::ignore
Hi,
eventually I went ahead with the idea sketched some time ago. Similarly
to what other implementations are already doing, the mandated
ignore(streamsize __n = 1, int_type __delim = traits_type::eof())
can be profitably "split" into:
ignore()
ignore(streamsize __n)
ignore(streamsize __n, int_type __delim)
since this allows much simpler and better performing implementations of
the first two. Also, the last two can thus exploit the same mechanism
already used for istream::getline.
To give you some numbers, on x86-64-2GHz, "ignoring" 2400000 lines each
200 char long and '\n' terminated of a disk file takes:
current
-------
1.971u 0.347s 0:02.31 100.0% 0+0k 0+0io 0pf+0w
patched
-------
0.180u 0.381s 0:00.56 100.0% 0+0k 0+0io 0pf+0w
and this is the "worst" case, since the first two overloads are faster
than the general case.
Regtested x86/x86-64.
Paolo.
////////////////
2004-06-21 Paolo Carlini <pcarlini@suse.de>
* include/std/std_istream.h (ignore(streamsize __n = 1,
int_type __delim = traits_type::eof())): Split into...
(ignore(), ignore(streamsize __n), ignore(streamsize __n,
int_type __delim)): The first two can be much more simpler
and efficient than the fully general case; also, the last
two can take advantage of the same mechanism already used
for getline.
* include/bits/istream.tcc (ignore(streamsize __n = 1,
int_type __delim = traits_type::eof()): Remove.
(ignore(), ignore(streamsize __n), ignore(streamsize __n,
int_type __delim)): New.
diff -prN libstdc++-v3-orig/include/bits/istream.tcc libstdc++-v3/include/bits/istream.tcc
*** libstdc++-v3-orig/include/bits/istream.tcc Thu Jun 10 21:54:59 2004
--- libstdc++-v3/include/bits/istream.tcc Sun Jun 20 12:08:29 2004
*************** namespace std
*** 644,651 ****
--- 644,734 ----
template<typename _CharT, typename _Traits>
basic_istream<_CharT, _Traits>&
basic_istream<_CharT, _Traits>::
+ ignore(void)
+ {
+ _M_gcount = 0;
+ sentry __cerb(*this, true);
+ if (__cerb)
+ {
+ ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+ try
+ {
+ const int_type __eof = traits_type::eof();
+ __streambuf_type* __sb = this->rdbuf();
+
+ if (traits_type::eq_int_type(__sb->sbumpc(), __eof))
+ __err |= ios_base::eofbit;
+ else
+ _M_gcount = 1;
+ }
+ catch(...)
+ { this->_M_setstate(ios_base::badbit); }
+ if (__err)
+ this->setstate(__err);
+ }
+ return *this;
+ }
+
+ template<typename _CharT, typename _Traits>
+ basic_istream<_CharT, _Traits>&
+ basic_istream<_CharT, _Traits>::
+ ignore(streamsize __n)
+ {
+ if (__n == 1)
+ return ignore();
+
+ _M_gcount = 0;
+ sentry __cerb(*this, true);
+ if (__cerb && __n > 0)
+ {
+ ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+ try
+ {
+ const int_type __eof = traits_type::eof();
+ __streambuf_type* __sb = this->rdbuf();
+ int_type __c = __sb->sgetc();
+
+ const bool __bound = __n != numeric_limits<streamsize>::max();
+ if (__bound)
+ --__n;
+ while (_M_gcount <= __n
+ && !traits_type::eq_int_type(__c, __eof))
+ {
+ streamsize __size = __sb->egptr() - __sb->gptr();
+ if (__bound)
+ __size = std::min(__size, __n - _M_gcount + 1);
+
+ if (__size > 1)
+ {
+ __sb->gbump(__size);
+ _M_gcount += __size;
+ __c = __sb->sgetc();
+ }
+ else
+ {
+ ++_M_gcount;
+ __c = __sb->snextc();
+ }
+ }
+ if (traits_type::eq_int_type(__c, __eof))
+ __err |= ios_base::eofbit;
+ }
+ catch(...)
+ { this->_M_setstate(ios_base::badbit); }
+ if (__err)
+ this->setstate(__err);
+ }
+ return *this;
+ }
+
+ template<typename _CharT, typename _Traits>
+ basic_istream<_CharT, _Traits>&
+ basic_istream<_CharT, _Traits>::
ignore(streamsize __n, int_type __delim)
{
+ if (traits_type::eq_int_type(__delim, traits_type::eof()))
+ return ignore(__n);
+
_M_gcount = 0;
sentry __cerb(*this, true);
if (__cerb && __n > 0)
*************** namespace std
*** 653,673 ****
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
try
{
const int_type __eof = traits_type::eof();
__streambuf_type* __sb = this->rdbuf();
! int_type __c = __eof;
! if (__n != numeric_limits<streamsize>::max())
--__n;
while (_M_gcount <= __n
! && !traits_type::eq_int_type(__c = __sb->sbumpc(), __eof))
{
! ++_M_gcount;
! if (traits_type::eq_int_type(__c, __delim))
! break;
}
if (traits_type::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
}
catch(...)
{ this->_M_setstate(ios_base::badbit); }
--- 736,781 ----
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
try
{
+ const char_type __cdelim = traits_type::to_char_type(__delim);
const int_type __eof = traits_type::eof();
__streambuf_type* __sb = this->rdbuf();
! int_type __c = __sb->sgetc();
! const bool __bound = __n != numeric_limits<streamsize>::max();
! if (__bound)
--__n;
while (_M_gcount <= __n
! && !traits_type::eq_int_type(__c, __eof)
! && !traits_type::eq_int_type(__c, __delim))
{
! streamsize __size = __sb->egptr() - __sb->gptr();
! if (__bound)
! __size = std::min(__size, __n - _M_gcount + 1);
!
! if (__size > 1)
! {
! const char_type* __p = traits_type::find(__sb->gptr(),
! __size,
! __cdelim);
! if (__p)
! __size = __p - __sb->gptr();
! __sb->gbump(__size);
! _M_gcount += __size;
! __c = __sb->sgetc();
! }
! else
! {
! ++_M_gcount;
! __c = __sb->snextc();
! }
}
if (traits_type::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
+ else if (traits_type::eq_int_type(__c, __delim))
+ {
+ ++_M_gcount;
+ __sb->sbumpc();
+ }
}
catch(...)
{ this->_M_setstate(ios_base::badbit); }
diff -prN libstdc++-v3-orig/include/std/std_istream.h libstdc++-v3/include/std/std_istream.h
*** libstdc++-v3-orig/include/std/std_istream.h Wed Feb 11 13:08:22 2004
--- libstdc++-v3/include/std/std_istream.h Sun Jun 20 16:47:36 2004
*************** namespace std
*** 412,420 ****
* - the next character equals @a delim (in this case, the character
* is extracted); note that this condition will never occur if
* @a delim equals @c traits::eof().
*/
__istream_type&
! ignore(streamsize __n = 1, int_type __delim = traits_type::eof());
/**
* @brief Looking ahead in the stream
--- 412,430 ----
* - the next character equals @a delim (in this case, the character
* is extracted); note that this condition will never occur if
* @a delim equals @c traits::eof().
+ *
+ * NB: Conformingly, we provide three overloads, instead of the single
+ * function (with defaults) mandated by the Standard: this leads to a
+ * better performing implementation.
*/
__istream_type&
! ignore();
!
! __istream_type&
! ignore(streamsize __n);
!
! __istream_type&
! ignore(streamsize __n, int_type __delim);
/**
* @brief Looking ahead in the stream