+2004-04-24 Paolo Carlini <pcarlini@suse.de>
+ Petur Runolfsson <peturr02@ru.is>
+
+ 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 <pcarlini@suse.de>
+
+ * 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 <doko@debian.org>
Jonathan Wakely <cow@compsoc.man.ac.uk>
// 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
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); }
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(...)
{
__in._M_setstate(ios_base::badbit);
}
}
- if ((!__extracted && !__testdelim) || __extracted == __n)
+ if (!__extracted)
__err |= ios_base::failbit;
if (__err)
__in.setstate(__err);
--- /dev/null
+// 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 <cstring> // for strlen
+#include <istream>
+#include <testsuite_hooks.h>
+
+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<char> 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;
+}