summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2003-03-08 08:16:06 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2003-03-08 08:16:06 +0000
commitd224894434122edb0c9de1b7f79ee8e633d515d6 (patch)
tree9718ebdfec13ed6a37f4d78228aa105a9125271e
parent45c2938ec41ac5236ecc071bfb6ef147f0a8d5bb (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--libstdc++-v3/include/bits/streambuf.tcc36
-rw-r--r--libstdc++-v3/testsuite/27_io/streambuf_members.cc87
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;
}