re PR libstdc++/9424 (i/ostream::operator>>/<<(streambuf*) drops characters)
authorPaolo Carlini <pcarlini@unitus.it>
Sat, 8 Mar 2003 08:16:06 +0000 (09:16 +0100)
committerPaolo Carlini <paolo@gcc.gnu.org>
Sat, 8 Mar 2003 08:16:06 +0000 (08:16 +0000)
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.

Co-Authored-By: Petur Runolfsson <peturr02@ru.is>
From-SVN: r63974

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/streambuf.tcc
libstdc++-v3/testsuite/27_io/streambuf_members.cc

index ffc04bc..1ada07b 100644 (file)
@@ -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
index c141399..6e9d192 100644 (file)
@@ -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;
index 80f569d..d7ae569 100644 (file)
@@ -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;
 }