From e9fb72e85fc8c0c85e9b98a744d3b908901509ca Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Wed, 17 Nov 2004 09:04:14 +0000 Subject: [PATCH] istream.tcc (getline(basic_istream<>&, basic_string<>&, _CharT)): Remove temporary kludge for libstdc++/15002. 2004-11-17 Paolo Carlini * 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. From-SVN: r90801 --- libstdc++-v3/ChangeLog | 11 ++ libstdc++-v3/include/bits/basic_string.h | 18 ++- libstdc++-v3/include/bits/istream.tcc | 11 +- libstdc++-v3/include/std/std_streambuf.h | 7 +- libstdc++-v3/src/istream.cc | 160 +++++++++++++++++++++++ 5 files changed, 193 insertions(+), 14 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 78884ef026a3..ab9349737de4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2004-11-17 Paolo Carlini + + * 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. + 2004-11-16 Jonathan Wakely * docs/html/19_diagnostics/howto.html: Document change from diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index e242d0fa191a..ecca1f523781 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -2286,7 +2286,7 @@ namespace std 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 @@ namespace std * delim was encountered, it is extracted but not stored into @a str. */ template - 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 @@ namespace std * encountered, it is extracted but not stored into @a str. */ template - 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& + getline(basic_istream& __in, basic_string& __str, + char __delim); + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + basic_istream& + getline(basic_istream& __in, basic_string& __str, + wchar_t __delim); +#endif } // namespace std #endif /* _BASIC_STRING_H */ diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index b467376b7898..1ed3e8d86982 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -1160,10 +1160,7 @@ namespace std { 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 @@ namespace std && !_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 --git a/libstdc++-v3/include/std/std_streambuf.h b/libstdc++-v3/include/std/std_streambuf.h index 23da7b90a69b..eed17767cc0a 100644 --- a/libstdc++-v3/include/std/std_streambuf.h +++ b/libstdc++-v3/include/std/std_streambuf.h @@ -154,7 +154,12 @@ namespace std friend streamsize __copy_streambufs<>(__streambuf_type* __sbin, __streambuf_type* __sbout); - + + template + friend basic_istream<_CharT2, _Traits2>& + getline(basic_istream<_CharT2, _Traits2>&, + basic_string<_CharT2, _Traits2, _Alloc>&, _CharT2); + protected: //@{ /** diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc index 7725ab4c138a..462824dada91 100644 --- a/libstdc++-v3/src/istream.cc +++ b/libstdc++-v3/src/istream.cc @@ -218,6 +218,86 @@ namespace std return *this; } + template<> + basic_istream& + getline(basic_istream& __in, basic_string& __str, + char __delim) + { + typedef basic_istream __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 __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& @@ -401,5 +481,85 @@ namespace std } return *this; } + + template<> + basic_istream& + getline(basic_istream& __in, basic_string& __str, + wchar_t __delim) + { + typedef basic_istream __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 __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