diff options
-rw-r--r-- | libstdc++-v3/ChangeLog | 14 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/istream.tcc | 123 | ||||
-rw-r--r-- | libstdc++-v3/include/std/std_istream.h | 15 |
3 files changed, 144 insertions, 8 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3b579d73496..7e0b5e7c1bf 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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 diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index c8861b651ef..59a44de10dd 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -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); } diff --git a/libstdc++-v3/include/std/std_istream.h b/libstdc++-v3/include/std/std_istream.h index a3a53ba73f6..65f9e6c3034 100644 --- a/libstdc++-v3/include/std/std_istream.h +++ b/libstdc++-v3/include/std/std_istream.h @@ -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 |