std_istream.h (ignore(streamsize __n = 1, int_type __delim = traits_type::eof())...
authorPaolo Carlini <pcarlini@suse.de>
Tue, 22 Jun 2004 10:06:39 +0000 (10:06 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 22 Jun 2004 10:06:39 +0000 (10:06 +0000)
2004-06-22  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.

From-SVN: r83486

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/istream.tcc
libstdc++-v3/include/std/std_istream.h

index 3b579d73496503bd2d1700852a752e0a1bfa26a5..7e0b5e7c1bf37a71e30033c13b55463b8c40bf4c 100644 (file)
@@ -1,3 +1,17 @@
+2004-06-22  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.
+
 2004-06-21  Loren J. Rittle  <ljrittle@acm.org>
 
        * config/linker-map.gnu: Use wildcards for
index c8861b651ef7627ddfce15d6a5f150df67f15fd2..59a44de10ddc226e75934cd3fdca2d0e5e07ceed 100644 (file)
@@ -641,11 +641,97 @@ namespace std
       return *this;
     }
 
+  // We provide three overloads, since the first two are much simpler
+  // than the general case. Also, the latter two can thus adopt the
+  // same "batchy" strategy used by getline above.
+  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, streamsize(__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)
@@ -653,21 +739,46 @@ namespace std
          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 = __eof;
+             int_type __c = __sb->sgetc();
 
-             if (__n != numeric_limits<streamsize>::max())
+             const bool __bound = __n != numeric_limits<streamsize>::max();
+             if (__bound)
                --__n;
              while (_M_gcount <= __n
-                    && !traits_type::eq_int_type(__c = __sb->sbumpc(), __eof))
+                    && !traits_type::eq_int_type(__c, __eof)
+                    && !traits_type::eq_int_type(__c, __delim))
                {
-                 ++_M_gcount;
-                 if (traits_type::eq_int_type(__c, __delim))
-                   break;
+                 streamsize __size = __sb->egptr() - __sb->gptr();
+                 if (__bound)
+                   __size = std::min(__size, streamsize(__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); }
index a3a53ba73f6e28d3bc31351b04292dddc56b06c7..65f9e6c30345466f51083456e02e892f3952344b 100644 (file)
@@ -1,6 +1,6 @@
 // Input streams -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003
+// Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003, 2004
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -412,9 +412,20 @@ namespace std
        *  - 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: Provide three overloads, instead of the single function
+       *  (with defaults) mandated by the Standard: this leads to a
+       *  better performing implementation, while still conforming to
+       *  the Standard.
       */
       __istream_type& 
-      ignore(streamsize __n = 1, int_type __delim = traits_type::eof());
+      ignore();
+
+      __istream_type& 
+      ignore(streamsize __n);
+
+      __istream_type& 
+      ignore(streamsize __n, int_type __delim);
       
       /**
        *  @brief  Looking ahead in the stream