From: Paolo Carlini Date: Sat, 24 Apr 2004 22:20:31 +0000 (+0000) Subject: PR libstdc++/15002 (continued) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=062bf895938ee3130690ac20a8b571f6d61e7dc1;p=platform%2Fupstream%2Fgcc.git PR libstdc++/15002 (continued) 2004-04-24 Paolo Carlini Petur Runolfsson PR libstdc++/15002 (continued) * include/bits/istream.tcc (basic_istream<>::getline(char_type*, streamsize, char_type)): Use traits::find/copy in a loop to speed up greatly the function in the common case (I/O buffer size >> 1). 2004-04-24 Paolo Carlini * testsuite/27_io/basic_istream/getline/char/4.cc: New. * include/bits/istream.tcc (getline(basic_istream<>&, basic_string<>&, _CharT)): Change to use sgetc()/snextc() instead of sbumpc(), consistently with the other functions, thus also dealing correctly with the case of exceeded string::max_size(). Co-Authored-By: Petur Runolfsson From-SVN: r81146 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 886d06c..0f1838e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2004-04-24 Paolo Carlini + Petur Runolfsson + + PR libstdc++/15002 (continued) + * include/bits/istream.tcc (basic_istream<>::getline(char_type*, + streamsize, char_type)): Use traits::find/copy in a loop to speed + up greatly the function in the common case (I/O buffer size >> 1). + +2004-04-24 Paolo Carlini + + * testsuite/27_io/basic_istream/getline/char/4.cc: New. + + * include/bits/istream.tcc (getline(basic_istream<>&, + basic_string<>&, _CharT)): Change to use sgetc()/snextc() instead + of sbumpc(), consistently with the other functions, thus also + dealing correctly with the case of exceeded string::max_size(). + 2004-04-24 Matthias Klose Jonathan Wakely diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index 3edb8cd..a7cf61e 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -1,6 +1,6 @@ // istream classes -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -592,27 +592,45 @@ namespace std const int_type __eof = traits_type::eof(); __streambuf_type* __sb = this->rdbuf(); int_type __c = __sb->sgetc(); - - while (_M_gcount + 1 < __n + --__n; + + while (_M_gcount < __n && !traits_type::eq_int_type(__c, __eof) && !traits_type::eq_int_type(__c, __idelim)) { - *__s++ = traits_type::to_char_type(__c); - __c = __sb->snextc(); - ++_M_gcount; + streamsize __size = std::min(streamsize(__sb->egptr() + - __sb->gptr()), + __n - _M_gcount); + if (__size > 1) + { + const char_type* __p = traits_type::find(__sb->gptr(), + __size, + __delim); + if (__p) + __size = __p - __sb->gptr(); + traits_type::copy(__s, __sb->gptr(), __size); + __s += __size; + __sb->gbump(__size); + _M_gcount += __size; + __c = __sb->sgetc(); + } + else + { + *__s++ = traits_type::to_char_type(__c); + __c = __sb->snextc(); + ++_M_gcount; + } } + if (traits_type::eq_int_type(__c, __eof)) __err |= ios_base::eofbit; - else + else if (traits_type::eq_int_type(__c, __idelim)) { - if (traits_type::eq_int_type(__c, __idelim)) - { - __sb->sbumpc(); - ++_M_gcount; - } - else - __err |= ios_base::failbit; + __sb->sbumpc(); + ++_M_gcount; } + else + __err |= ios_base::failbit; } catch(...) { this->_M_setstate(ios_base::badbit); } @@ -1085,22 +1103,28 @@ namespace std try { __str.erase(); - __int_type __idelim = _Traits::to_int_type(__delim); - __streambuf_type* __sb = __in.rdbuf(); - __int_type __c = __sb->sbumpc(); + const __int_type __idelim = _Traits::to_int_type(__delim); const __int_type __eof = _Traits::eof(); - __testdelim = _Traits::eq_int_type(__c, __idelim); + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); - while (!_Traits::eq_int_type(__c, __eof) && !__testdelim - && __extracted < __n) + while (__extracted < __n + && !_Traits::eq_int_type(__c, __eof) + && !_Traits::eq_int_type(__c, __idelim)) { __str += _Traits::to_char_type(__c); + __c = __sb->snextc(); ++__extracted; - __c = __sb->sbumpc(); - __testdelim = _Traits::eq_int_type(__c, __idelim); } if (_Traits::eq_int_type(__c, __eof)) __err |= ios_base::eofbit; + else if (_Traits::eq_int_type(__c, __idelim)) + { + __sb->sbumpc(); + ++__extracted; + } + else + __err |= ios_base::failbit; } catch(...) { @@ -1110,7 +1134,7 @@ namespace std __in._M_setstate(ios_base::badbit); } } - if ((!__extracted && !__testdelim) || __extracted == __n) + if (!__extracted) __err |= ios_base::failbit; if (__err) __in.setstate(__err); diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/getline/char/4.cc b/libstdc++-v3/testsuite/27_io/basic_istream/getline/char/4.cc new file mode 100644 index 0000000..0c53187 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_istream/getline/char/4.cc @@ -0,0 +1,106 @@ +// Copyright (C) 2004 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include // for strlen +#include +#include + +class Inbuf : public std::streambuf +{ + static const char buf[]; + const char* current; + int size; + +public: + Inbuf() + { + current = buf; + size = std::strlen(buf); + } + + int_type underflow() + { + if (current < buf + size) + return traits_type::to_int_type(*current); + return traits_type::eof(); + } + + int_type uflow() + { + if (current < buf + size) + return traits_type::to_int_type(*current++); + return traits_type::eof(); + } +}; + +const char Inbuf::buf[] = "1234567890abcdefghij"; + +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + typedef char_traits traits_type; + + Inbuf inbuf1; + istream is(&inbuf1); + + char buffer[10]; + traits_type::assign(buffer, sizeof(buffer), 'X'); + + is.getline(buffer, sizeof(buffer), '0'); + VERIFY( is.rdstate() == ios_base::goodbit ); + VERIFY( !traits_type::compare(buffer, "123456789\0", sizeof(buffer)) ); + VERIFY( is.gcount() == 10 ); + + is.clear(); + traits_type::assign(buffer, sizeof(buffer), 'X'); + is.getline(buffer, sizeof(buffer)); + VERIFY( is.rdstate() == ios_base::failbit ); + VERIFY( !traits_type::compare(buffer, "abcdefghi\0", sizeof(buffer)) ); + VERIFY( is.gcount() == 9 ); + + is.clear(); + traits_type::assign(buffer, sizeof(buffer), 'X'); + is.getline(buffer, sizeof(buffer)); + VERIFY( is.rdstate() == ios_base::eofbit ); + VERIFY( !traits_type::compare(buffer, "j\0XXXXXXXX", sizeof(buffer)) ); + VERIFY( is.gcount() == 1 ); + + is.clear(); + traits_type::assign(buffer, sizeof(buffer), 'X'); + is.getline(buffer, sizeof(buffer)); + VERIFY( is.rdstate() == (ios_base::eofbit | ios_base::failbit) ); + VERIFY( !traits_type::compare(buffer, "\0XXXXXXXXX", sizeof(buffer)) ); + VERIFY( is.gcount() == 0 ); +} + +int main() +{ + test01(); + return 0; +}