This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3] Fix libstdc++/15002 (continued)


Hi,

tested x86-linux, committed to mainline.

Paolo.

/////////////
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().
diff -prN libstdc++-v3-orig/include/bits/istream.tcc libstdc++-v3/include/bits/istream.tcc
*** libstdc++-v3-orig/include/bits/istream.tcc	Sun Feb  8 05:46:41 2004
--- libstdc++-v3/include/bits/istream.tcc	Fri Apr 23 12:17:58 2004
***************
*** 1,6 ****
  // istream classes -*- C++ -*-
  
! // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
  // Free Software Foundation, Inc.
  //
  // This file is part of the GNU ISO C++ Library.  This library is free
--- 1,6 ----
  // istream classes -*- C++ -*-
  
! // 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
*************** namespace std
*** 592,618 ****
  	      const int_type __eof = traits_type::eof();
  	      __streambuf_type* __sb = this->rdbuf();
  	      int_type __c = __sb->sgetc();
! 
! 	      while (_M_gcount + 1 < __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;
  		}
  	      if (traits_type::eq_int_type(__c, __eof))
  		__err |= ios_base::eofbit;
! 	      else
  		{
! 		  if (traits_type::eq_int_type(__c, __idelim))
! 		    {
! 		      __sb->sbumpc();
! 		      ++_M_gcount;
! 		    }
! 		  else
! 		    __err |= ios_base::failbit;
  		}
  	    }
  	  catch(...)
  	    { this->_M_setstate(ios_base::badbit); }
--- 592,636 ----
  	      const int_type __eof = traits_type::eof();
  	      __streambuf_type* __sb = this->rdbuf();
  	      int_type __c = __sb->sgetc();
! 	      --__n;
! 	      
! 	      while (_M_gcount < __n
  		     && !traits_type::eq_int_type(__c, __eof)
  		     && !traits_type::eq_int_type(__c, __idelim))
  		{
! 		  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 if (traits_type::eq_int_type(__c, __idelim))
  		{
! 		  __sb->sbumpc();
! 		  ++_M_gcount;
  		}
+ 	      else
+ 		__err |= ios_base::failbit;
  	    }
  	  catch(...)
  	    { this->_M_setstate(ios_base::badbit); }
*************** namespace std
*** 1085,1106 ****
  	  try
  	    {
  	      __str.erase();
! 	      __int_type __idelim = _Traits::to_int_type(__delim);
! 	      __streambuf_type* __sb = __in.rdbuf();
! 	      __int_type __c = __sb->sbumpc();
  	      const __int_type __eof = _Traits::eof();
! 	      __testdelim = _Traits::eq_int_type(__c, __idelim);
  
! 	      while (!_Traits::eq_int_type(__c, __eof) && !__testdelim
! 		     && __extracted < __n)
  		{
  		  __str += _Traits::to_char_type(__c);
  		  ++__extracted;
- 		  __c = __sb->sbumpc();
- 		  __testdelim = _Traits::eq_int_type(__c, __idelim);
  		}
  	      if (_Traits::eq_int_type(__c, __eof))
  		__err |= ios_base::eofbit;
  	    }
  	  catch(...)
  	    {
--- 1103,1130 ----
  	  try
  	    {
  	      __str.erase();
! 	      const __int_type __idelim = _Traits::to_int_type(__delim);
  	      const __int_type __eof = _Traits::eof();
! 	      __streambuf_type* __sb = __in.rdbuf();
! 	      __int_type __c = __sb->sgetc();
  
! 	      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;
  		}
  	      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(...)
  	    {
*************** namespace std
*** 1110,1116 ****
  	      __in._M_setstate(ios_base::badbit);
  	    }
  	}
!       if ((!__extracted && !__testdelim) || __extracted == __n)
  	__err |= ios_base::failbit;
        if (__err)
  	__in.setstate(__err);
--- 1134,1140 ----
  	      __in._M_setstate(ios_base::badbit);
  	    }
  	}
!       if (!__extracted)
  	__err |= ios_base::failbit;
        if (__err)
  	__in.setstate(__err);
diff -prN libstdc++-v3-orig/testsuite/27_io/basic_istream/getline/char/4.cc libstdc++-v3/testsuite/27_io/basic_istream/getline/char/4.cc
*** libstdc++-v3-orig/testsuite/27_io/basic_istream/getline/char/4.cc	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/27_io/basic_istream/getline/char/4.cc	Fri Apr 23 23:39:01 2004
***************
*** 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 <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;
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]