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] Speed-up getline(string)


Hi,

tested x86/x86_64-linux, committed to mainline.

Paolo.

////////////////
2004-11-17  Paolo Carlini  <pcarlini@suse.de>

	* include/bits/istream.tcc (getline(basic_istream<>&, basic_string<>&,
	_CharT)): Remove temporary kludge for libstdc++/15002.
	* include/std/std_streambuf.h (class basic_streambuf): Declare
	getline(basic_istream<>&, basic_string<>&, _CharT) as friend.
	* include/bits/basic_string.h (getline(basic_istream<>&,
	basic_string<>&, _CharT)): Declare optimized specializations for
	char and wchar_t, using protected members of basic_streambuf.
	* src/istream.cc: Define the latter.
diff -urN libstdc++-v3-orig/include/bits/basic_string.h libstdc++-v3/include/bits/basic_string.h
--- libstdc++-v3-orig/include/bits/basic_string.h	2004-10-28 03:04:34.000000000 +0200
+++ libstdc++-v3/include/bits/basic_string.h	2004-11-16 17:21:52.000000000 +0100
@@ -2286,7 +2286,7 @@
     inline bool
     operator<=(const _CharT* __lhs,
 	       const basic_string<_CharT, _Traits, _Alloc>& __rhs)
-  { return __rhs.compare(__lhs) >= 0; }
+    { return __rhs.compare(__lhs) >= 0; }
 
   // operator >=
   /**
@@ -2382,7 +2382,7 @@
    *  delim was encountered, it is extracted but not stored into @a str.
    */
   template<typename _CharT, typename _Traits, typename _Alloc>
-    basic_istream<_CharT,_Traits>&
+    basic_istream<_CharT, _Traits>&
     getline(basic_istream<_CharT, _Traits>& __is,
 	    basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim);
 
@@ -2399,9 +2399,21 @@
    *  encountered, it is extracted but not stored into @a str.
    */
   template<typename _CharT, typename _Traits, typename _Alloc>
-    inline basic_istream<_CharT,_Traits>&
+    inline basic_istream<_CharT, _Traits>&
     getline(basic_istream<_CharT, _Traits>& __is,
 	    basic_string<_CharT, _Traits, _Alloc>& __str);
+    
+  template<>
+    basic_istream<char>&
+    getline(basic_istream<char>& __in, basic_string<char>& __str,
+	    char __delim);
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    basic_istream<wchar_t>&
+    getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
+	    wchar_t __delim);
+#endif  
 } // namespace std
 
 #endif /* _BASIC_STRING_H */
diff -urN libstdc++-v3-orig/include/bits/istream.tcc libstdc++-v3/include/bits/istream.tcc
--- libstdc++-v3-orig/include/bits/istream.tcc	2004-11-08 16:46:27.000000000 +0100
+++ libstdc++-v3/include/bits/istream.tcc	2004-11-16 17:24:17.000000000 +0100
@@ -1160,10 +1160,7 @@
 	{
 	  try
 	    {
-	      // Avoid reallocation for common case.
 	      __str.erase();
-	      _CharT __buf[128];
-	      __size_type __len = 0;
 	      const __int_type __idelim = _Traits::to_int_type(__delim);
 	      const __int_type __eof = _Traits::eof();
 	      __streambuf_type* __sb = __in.rdbuf();
@@ -1173,16 +1170,10 @@
 		     && !_Traits::eq_int_type(__c, __eof)
 		     && !_Traits::eq_int_type(__c, __idelim))
 		{
-		  if (__len == sizeof(__buf) / sizeof(_CharT))
-		    {
-		      __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
-		      __len = 0;
-		    }
-		  __buf[__len++] = _Traits::to_char_type(__c);
+		  __str += _Traits::to_char_type(__c);
 		  ++__extracted;
 		  __c = __sb->snextc();
 		}
-	      __str.append(__buf, __len);
 
 	      if (_Traits::eq_int_type(__c, __eof))
 		__err |= ios_base::eofbit;
diff -urN libstdc++-v3-orig/include/std/std_streambuf.h libstdc++-v3/include/std/std_streambuf.h
--- libstdc++-v3-orig/include/std/std_streambuf.h	2004-11-16 00:33:05.000000000 +0100
+++ libstdc++-v3/include/std/std_streambuf.h	2004-11-16 17:52:19.000000000 +0100
@@ -154,7 +154,12 @@
       friend streamsize
       __copy_streambufs<>(__streambuf_type* __sbin,
 			  __streambuf_type* __sbout);
-      
+
+      template<typename _CharT2, typename _Traits2, typename _Alloc>
+        friend basic_istream<_CharT2, _Traits2>&
+        getline(basic_istream<_CharT2, _Traits2>&,
+		basic_string<_CharT2, _Traits2, _Alloc>&, _CharT2);
+
     protected:
       //@{
       /**
diff -urN libstdc++-v3-orig/src/istream.cc libstdc++-v3/src/istream.cc
--- libstdc++-v3-orig/src/istream.cc	2004-11-08 16:46:28.000000000 +0100
+++ libstdc++-v3/src/istream.cc	2004-11-16 17:44:41.000000000 +0100
@@ -218,6 +218,86 @@
       return *this;
     }
 
+  template<>
+    basic_istream<char>&
+    getline(basic_istream<char>& __in, basic_string<char>& __str,
+	    char __delim)
+    {
+      typedef basic_istream<char>       	__istream_type;
+      typedef __istream_type::int_type		__int_type;
+      typedef __istream_type::char_type		__char_type;
+      typedef __istream_type::traits_type	__traits_type;
+      typedef __istream_type::__streambuf_type  __streambuf_type;
+      typedef __istream_type::__ctype_type	__ctype_type;
+      typedef basic_string<char>        	__string_type;
+      typedef __string_type::size_type		__size_type;
+
+      __size_type __extracted = 0;
+      const __size_type __n = __str.max_size();
+      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+      __istream_type::sentry __cerb(__in, true);
+      if (__cerb)
+	{
+	  try
+	    {
+	      __str.erase();
+	      const __int_type __idelim = __traits_type::to_int_type(__delim);
+	      const __int_type __eof = __traits_type::eof();
+	      __streambuf_type* __sb = __in.rdbuf();
+	      __int_type __c = __sb->sgetc();
+
+	      while (__extracted < __n
+		     && !__traits_type::eq_int_type(__c, __eof)
+		     && !__traits_type::eq_int_type(__c, __idelim))
+		{
+		  streamsize __size = std::min(streamsize(__sb->egptr()
+							  - __sb->gptr()),
+					       streamsize(__n - __extracted));
+		  if (__size > 1)
+		    {
+		      const __char_type* __p = __traits_type::find(__sb->gptr(),
+								   __size,
+								   __delim);
+		      if (__p)
+			__size = __p - __sb->gptr();
+		      __str.append(__sb->gptr(), __size);
+		      __sb->gbump(__size);
+		      __extracted += __size;
+		      __c = __sb->sgetc();
+		    }
+		  else
+		    {
+		      __str += __traits_type::to_char_type(__c);
+		      ++__extracted;
+		      __c = __sb->snextc();
+		    }		  
+		}
+
+	      if (__traits_type::eq_int_type(__c, __eof))
+		__err |= ios_base::eofbit;
+	      else if (__traits_type::eq_int_type(__c, __idelim))
+		{
+		  ++__extracted;
+		  __sb->sbumpc();
+		}
+	      else
+		__err |= ios_base::failbit;
+	    }
+	  catch(...)
+	    {
+	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	      // 91. Description of operator>> and getline() for string<>
+	      // might cause endless loop
+	      __in._M_setstate(ios_base::badbit);
+	    }
+	}
+      if (!__extracted)
+	__err |= ios_base::failbit;
+      if (__err)
+	__in.setstate(__err);
+      return __in;
+    }
+
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<>
     basic_istream<wchar_t>&
@@ -401,5 +481,85 @@
 	}
       return *this;
     }
+
+  template<>
+    basic_istream<wchar_t>&
+    getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
+	    wchar_t __delim)
+    {
+      typedef basic_istream<wchar_t>       	__istream_type;
+      typedef __istream_type::int_type		__int_type;
+      typedef __istream_type::char_type		__char_type;
+      typedef __istream_type::traits_type	__traits_type;
+      typedef __istream_type::__streambuf_type  __streambuf_type;
+      typedef __istream_type::__ctype_type	__ctype_type;
+      typedef basic_string<wchar_t>        	__string_type;
+      typedef __string_type::size_type		__size_type;
+
+      __size_type __extracted = 0;
+      const __size_type __n = __str.max_size();
+      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+      __istream_type::sentry __cerb(__in, true);
+      if (__cerb)
+	{
+	  try
+	    {
+	      __str.erase();
+	      const __int_type __idelim = __traits_type::to_int_type(__delim);
+	      const __int_type __eof = __traits_type::eof();
+	      __streambuf_type* __sb = __in.rdbuf();
+	      __int_type __c = __sb->sgetc();
+
+	      while (__extracted < __n
+		     && !__traits_type::eq_int_type(__c, __eof)
+		     && !__traits_type::eq_int_type(__c, __idelim))
+		{
+		  streamsize __size = std::min(streamsize(__sb->egptr()
+							  - __sb->gptr()),
+					       streamsize(__n - __extracted));
+		  if (__size > 1)
+		    {
+		      const __char_type* __p = __traits_type::find(__sb->gptr(),
+								   __size,
+								   __delim);
+		      if (__p)
+			__size = __p - __sb->gptr();
+		      __str.append(__sb->gptr(), __size);
+		      __sb->gbump(__size);
+		      __extracted += __size;
+		      __c = __sb->sgetc();
+		    }
+		  else
+		    {
+		      __str += __traits_type::to_char_type(__c);
+		      ++__extracted;
+		      __c = __sb->snextc();
+		    }		  
+		}
+
+	      if (__traits_type::eq_int_type(__c, __eof))
+		__err |= ios_base::eofbit;
+	      else if (__traits_type::eq_int_type(__c, __idelim))
+		{
+		  ++__extracted;
+		  __sb->sbumpc();
+		}
+	      else
+		__err |= ios_base::failbit;
+	    }
+	  catch(...)
+	    {
+	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	      // 91. Description of operator>> and getline() for string<>
+	      // might cause endless loop
+	      __in._M_setstate(ios_base::badbit);
+	    }
+	}
+      if (!__extracted)
+	__err |= ios_base::failbit;
+      if (__err)
+	__in.setstate(__err);
+      return __in;
+    }
 #endif
 } // namespace std

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