diff options
author | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-03-08 08:16:06 +0000 |
---|---|---|
committer | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-03-08 08:16:06 +0000 |
commit | d224894434122edb0c9de1b7f79ee8e633d515d6 (patch) | |
tree | 9718ebdfec13ed6a37f4d78228aa105a9125271e | |
parent | 45c2938ec41ac5236ecc071bfb6ef147f0a8d5bb (diff) | |
download | gcc-d224894434122edb0c9de1b7f79ee8e633d515d6.tar.gz |
2003-03-08 Paolo Carlini <pcarlini@unitus.it>
Petur Runolfsson <peturr02@ru.is>
PR libstdc++/9424
* include/bits/streambuf.tcc (__copy_streambufs): Use
sgetn-sputn only when sputn cannot fail, otherwise fall back
to safe snextc-sputc.
* testsuite/27_io/streambuf_members.cc (test11, test12): Add.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@63974 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libstdc++-v3/ChangeLog | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/streambuf.tcc | 36 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/streambuf_members.cc | 87 |
3 files changed, 126 insertions, 6 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ffc04bc0100..1ada07bc781 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2003-03-08 Paolo Carlini <pcarlini@unitus.it> + Petur Runolfsson <peturr02@ru.is> + + PR libstdc++/9424 + * include/bits/streambuf.tcc (__copy_streambufs): Use + sgetn-sputn only when sputn cannot fail, otherwise fall back + to safe snextc-sputc. + * testsuite/27_io/streambuf_members.cc (test11, test12): Add. + 2003-03-08 Jerry Quinn <jlquinn@optonline.net> * include/bits/locale_facets.tcc (num_put::do_put(bool)): Use diff --git a/libstdc++-v3/include/bits/streambuf.tcc b/libstdc++-v3/include/bits/streambuf.tcc index c14139988af..6e9d192f345 100644 --- a/libstdc++-v3/include/bits/streambuf.tcc +++ b/libstdc++-v3/include/bits/streambuf.tcc @@ -193,6 +193,9 @@ namespace std streamsize __ret = 0; streamsize __bufsize = __sbin->in_avail(); streamsize __xtrct; + const typename _Traits::off_type __size_opt = + __sbin->_M_buf_size_opt > 0 ? __sbin->_M_buf_size_opt : 1; + try { while (__bufsize != -1) @@ -208,12 +211,33 @@ namespace std } else { - size_t __size = - __sbin->_M_buf_size_opt > 0 ? __sbin->_M_buf_size_opt : 1; - _CharT* __buf = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __size)); - streamsize __charsread = __sbin->sgetn(__buf, __size); - __xtrct = __sbout->sputn(__buf, __charsread); + streamsize __charsread; + const streamsize __size = + std::min(__size_opt, __sbout->_M_out_buf_size()); + if (__size > 1) + { + _CharT* __buf = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __size)); + // Since the next sputn cannot fail sgetn can be + // safely used. + __charsread = __sbin->sgetn(__buf, __size); + __xtrct = __sbout->sputn(__buf, __charsread); + } + else + { + __xtrct = __charsread = 0; + int_type __c = __sbin->sgetc(); + while (!_Traits::eq_int_type(__c, _Traits::eof())) + { + ++__charsread; + if (_Traits::eq_int_type(__sbout->sputc(_Traits::to_char_type(__c)), + _Traits::eof())) + break; + ++__xtrct; + __c = __sbin->snextc(); + } + } __ret += __xtrct; if (__xtrct != __charsread) break; diff --git a/libstdc++-v3/testsuite/27_io/streambuf_members.cc b/libstdc++-v3/testsuite/27_io/streambuf_members.cc index 80f569d8074..d7ae5693d33 100644 --- a/libstdc++-v3/testsuite/27_io/streambuf_members.cc +++ b/libstdc++-v3/testsuite/27_io/streambuf_members.cc @@ -431,6 +431,91 @@ void test10() VERIFY( buf.result() == "Bad Moon Rising" ); } +// libstdc++/9424 +class Outbuf_2 : public std::streambuf +{ + char buf[1]; + +public: + Outbuf_2() + { + setp(buf, buf + 1); + } + + int_type overflow(int_type c) + { + int_type eof = traits_type::eof(); + + if (pptr() < epptr()) + { + if (traits_type::eq_int_type(c, eof)) + return traits_type::not_eof(c); + + *pptr() = traits_type::to_char_type(c); + pbump(1); + return c; + } + + return eof; + } +}; + +class Inbuf_2 : public std::streambuf +{ + static const char buf[]; + const char* current; + int size; + +public: + Inbuf_2() + { + 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_2::buf[] = "Atteivlis"; + +// <1> +void test11() +{ + bool test = true; + + Inbuf_2 inbuf1; + std::istream is(&inbuf1); + Outbuf_2 outbuf1; + is >> &outbuf1; + VERIFY( inbuf1.sgetc() == 't' ); + VERIFY( is.good() ); +} + +// <2> +void test12() +{ + bool test = true; + + Outbuf_2 outbuf2; + std::ostream os (&outbuf2); + Inbuf_2 inbuf2; + os << &inbuf2; + VERIFY( inbuf2.sgetc() == 't' ); + VERIFY( os.good() ); +} + int main() { test01(); @@ -445,5 +530,7 @@ int main() test09(); test10(); + test11(); + test12(); return 0; } |