This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3] Speed-up getline(string)
- From: Paolo Carlini <pcarlini at suse dot de>
- To: "'gcc-patches at gcc dot gnu dot org'" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 17 Nov 2004 10:06:56 +0100
- Subject: [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