re PR libstdc++/9339 (filebuf::pubsetbuf(0, 0) doesn't turn off buffering)
authorBenjamin Kosnik <bkoz@gcc.gnu.org>
Mon, 26 May 2003 14:54:42 +0000 (14:54 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Mon, 26 May 2003 14:54:42 +0000 (14:54 +0000)
2003-05-26  Benjamin Kosnik  <bkoz@redhat.com>

PR libstdc++/9339
* include/std/std_fstream.h (basic_filebuf::_M_overflow): Remove.
(_M_pback): No array necessary.
* include/bits/fstream.tcc (basic_filebuf::_M_overflow): Add
unbuffered case, coalesec into ...
(basic_filebuf::overflow): ...this.
* testsuite/27_io/basic_filebuf/sputn/char/9339.cc: New.
* testsuite/27_io/basic_filebuf/sputc/char/2.cc: Unbuffered.

From-SVN: r67175

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/bits/streambuf.tcc
libstdc++-v3/include/std/std_fstream.h
libstdc++-v3/testsuite/27_io/basic_filebuf/sputc/char/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/sputn/char/9339.cc [new file with mode: 0644]

index afd5f672699a3d6adef967409d0d3e29e816b500..7165b8e6cc87d201e418ef75b5bef0112d5345cf 100644 (file)
@@ -1,3 +1,14 @@
+2003-05-26  Benjamin Kosnik  <bkoz@redhat.com>
+
+       PR libstdc++/9339
+       * include/std/std_fstream.h (basic_filebuf::_M_overflow): Remove.
+       (_M_pback): No array necessary.
+       * include/bits/fstream.tcc (basic_filebuf::_M_overflow): Add
+       unbuffered case, coalesec into ...
+       (basic_filebuf::overflow): ...this.
+       * testsuite/27_io/basic_filebuf/sputn/char/9339.cc: New.
+       * testsuite/27_io/basic_filebuf/sputc/char/2.cc: Unbuffered.
+       
 2003-05-24  Nathanael Nerode  <neroden@gcc.gnu.org>
 
        * libsupc++/Makefile.am, libsupc++/cxxabi.h, libsupc++/del_op.cc,
@@ -58,6 +69,7 @@
 
 2003-05-22  Brad Spencer  <spencer@infointeractive.com>
 
+       PR libstdc++/10106
        * configure.in: Add Solaris cross bits.
 
 2003-05-21  Danny Smith  <dannysmith@users.sourceforge.net>
index cda0bacd9f9cf7f7f711b1ca9081edfcd17834fb..9bbb5cc1a52927f28322110aff6ccce51bd70ca1 100644 (file)
@@ -73,7 +73,7 @@ namespace std
     basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), 
     _M_state_cur(__state_type()), _M_state_beg(__state_type()), 
     _M_buf(NULL), _M_buf_size(BUFSIZ), _M_buf_allocated(false),
-    _M_last_overflowed(false), _M_pback_cur_save(0),
+    _M_last_overflowed(false), _M_filepos(0), _M_pback_cur_save(0),
     _M_pback_end_save(0), _M_pback_init(false), _M_codecvt(0)
     { 
       this->_M_buf_unified = true;       
@@ -125,7 +125,7 @@ namespace std
              const bool __testput = this->_M_out_beg < this->_M_out_lim;
 
              if (__testput 
-                 && traits_type::eq_int_type(_M_overflow(__eof), __eof))
+                 && traits_type::eq_int_type(this->overflow(), __eof))
                __testfail = true;
 
 #if 0
@@ -133,7 +133,7 @@ namespace std
              if (_M_last_overflowed)
                {
                  _M_output_unshift();
-                 _M_overflow(__eof);
+                 this->overflow();
                }
 #endif
            }
@@ -204,7 +204,7 @@ namespace std
 
          // Sync internal and external buffers.
          if (__testout && this->_M_out_beg < this->_M_out_lim)
-           _M_overflow();
+           this->overflow();
 
          if (_M_buf_size > 1)
            {
@@ -321,67 +321,49 @@ namespace std
       return __ret;
     }
 
-  template<typename _CharT, typename _Traits>
-    typename basic_filebuf<_CharT, _Traits>::int_type 
-    basic_filebuf<_CharT, _Traits>::
-    _M_overflow(int_type __c)
-    {
-      int_type __ret = traits_type::eof();
-      const bool __testeof = traits_type::eq_int_type(__c, __ret);
-      const bool __testput = this->_M_out_beg < this->_M_out_lim;
-
-      if (__testput)
-       {
-         // Need to restore current position. The position of the
-         // external byte sequence (_M_file) corresponds to
-         // _M_filepos, and we need to move it to _M_out_beg for the
-         // write.
-         if (_M_filepos != this->_M_out_beg)
-           _M_file.seekoff(this->_M_out_beg - _M_filepos, ios_base::cur);
-
-         // If appropriate, append the overflow char.
-         if (!__testeof)
-           *this->_M_out_lim++ = traits_type::to_char_type(__c);
-
-         // Convert pending sequence to external representation,
-         // output. 
-         if (_M_convert_to_external(this->_M_out_beg,
-                                    this->_M_out_lim - this->_M_out_beg)
-             && (!__testeof || (__testeof && !_M_file.sync())))
-           {
-             _M_set_buffer(0);
-             __ret = traits_type::not_eof(__c);
-           }
-       }
-      _M_last_overflowed = true;       
-      return __ret;
-    }
-
   template<typename _CharT, typename _Traits>
     typename basic_filebuf<_CharT, _Traits>::int_type 
     basic_filebuf<_CharT, _Traits>::
     overflow(int_type __c)
     {
       int_type __ret = traits_type::eof();
-      const bool __testput = this->_M_out_cur < this->_M_out_end;
+      const bool __testeof = traits_type::eq_int_type(__c, __ret);
       const bool __testout = this->_M_mode & ios_base::out;
       
-      // Perhaps set below in _M_overflow.
-      _M_last_overflowed = false;
-
       if (__testout)
        {
-         if (traits_type::eq_int_type(__c, traits_type::eof()))
-           __ret = traits_type::not_eof(__c);
-         else if (__testput)
+         if (this->_M_out_beg < this->_M_out_lim)
+           {
+             // Need to restore current position. The position of the
+             // external byte sequence (_M_file) corresponds to
+             // _M_filepos, and we need to move it to _M_out_beg for
+             // the write.
+             if (_M_filepos != this->_M_out_beg)
+               _M_file.seekoff(this->_M_out_beg - _M_filepos, ios_base::cur);
+
+             // If appropriate, append the overflow char.
+             if (!__testeof)
+               *this->_M_out_lim++ = traits_type::to_char_type(__c);
+             
+             // Convert pending sequence to external representation,
+             // output.
+             if (_M_convert_to_external(this->_M_out_beg,
+                                        this->_M_out_lim - this->_M_out_beg)
+                 && (!__testeof || (__testeof && !_M_file.sync())))
+               {
+                 _M_set_buffer(0);
+                 __ret = traits_type::not_eof(__c);
+               }
+           }
+         else
            {
-             *this->_M_out_cur = traits_type::to_char_type(__c);
-             _M_move_out_cur(1);
-             __ret = traits_type::not_eof(__c);
+             // Unbuffered.
+             char_type __conv = traits_type::to_char_type(__c);
+             if (!__testeof && _M_convert_to_external(&__conv, 1))
+               __ret = __c;
            }
-         else 
-           __ret = this->_M_overflow(__c);
        }
+      _M_last_overflowed = true;       
       return __ret;
     }
   
index f80a815aa42723293798026e4faea9a84c52290c..5b76c40f9288c85d77f47eb8aa028d6ca27cef2d 100644 (file)
@@ -115,7 +115,7 @@ namespace std
       while (__ret < __n)
        {
          const size_t __buf_len = _M_in_end - _M_in_cur;
-         if (__buf_len > 0)
+         if (__buf_len)
            {
              const size_t __remaining = __n - __ret;
              const size_t __len = std::min(__buf_len, __remaining);
@@ -149,7 +149,7 @@ namespace std
       while (__ret < __n)
        {
          const size_t __buf_len = _M_out_end - _M_out_cur;
-         if (__buf_len > 0)
+         if (__buf_len)
            {
              const size_t __remaining = __n - __ret;
              const size_t __len = std::min(__buf_len, __remaining);
@@ -161,7 +161,7 @@ namespace std
 
          if (__ret < __n)
            {
-             const int_type __c = this->overflow(traits_type::to_int_type(*__s));
+             int_type __c = this->overflow(traits_type::to_int_type(*__s));
              if (!traits_type::eq_int_type(__c, traits_type::eof()))
                {
                  ++__ret;
index 27794881c75d5e1e7b491df70b6dabdfa3a3c86c..9faf73730062947996d42b69e3ff53ec0e20f832 100644 (file)
@@ -158,7 +158,7 @@ namespace std
        *  @note pbacks of over one character are not currently supported.
        *  @endif
       */
-      char_type                        _M_pback[1]
+      char_type                        _M_pback; 
       char_type*               _M_pback_cur_save;
       char_type*               _M_pback_end_save;
       bool                     _M_pback_init; 
@@ -177,7 +177,7 @@ namespace std
          {
            _M_pback_cur_save = this->_M_in_cur;
            _M_pback_end_save = this->_M_in_end;
-           this->setg(_M_pback, _M_pback, _M_pback + 1);
+           this->setg(&_M_pback, &_M_pback, &_M_pback + 1);
            _M_pback_init = true;
          }
       }
@@ -191,8 +191,8 @@ namespace std
        if (_M_pback_init)
          {
            // Length _M_in_cur moved in the pback buffer.
-           const size_t __off_cur = this->_M_in_cur - _M_pback;
-           this->setg(this->_M_buf, _M_pback_cur_save + __off_cur
+           const size_t __off = this->_M_in_cur == &_M_pback ? 0 : 1;
+           this->setg(this->_M_buf, _M_pback_cur_save + __off, 
                       _M_pback_end_save);
            _M_pback_init = false;
          }
@@ -311,19 +311,6 @@ namespace std
       virtual int_type
       pbackfail(int_type __c = _Traits::eof());
 
-      // NB: For what the standard expects of the overflow function,
-      // see _M_overflow(), below. Because basic_streambuf's
-      // sputc/sputn call overflow directly, and the complications of
-      // this implementation's setting of the initial pointers all
-      // equal to _M_buf when initializing, it seems essential to have
-      // this in actuality be a helper function that checks for the
-      // eccentricities of this implementation, and then call
-      // overflow() if indeed the buffer is full.
-
-      // [documentation is inherited]
-      virtual int_type
-      overflow(int_type __c = _Traits::eof());
-
       // Stroustrup, 1998, p 648
       // The overflow() function is called to transfer characters to the
       // real output destination when the buffer is full. A call to
@@ -336,8 +323,8 @@ namespace std
        *  @doctodo
        *  @endif
       */
-      int_type
-      _M_overflow(int_type __c = _Traits::eof());
+      virtual int_type
+      overflow(int_type __c = _Traits::eof());
 
       // Convert internal byte sequence to external, char-based
       // sequence via codecvt.
@@ -389,7 +376,7 @@ namespace std
            off_type __off = this->_M_out_cur - this->_M_out_lim;
 
            // _M_file.sync() will be called within
-           if (traits_type::eq_int_type(_M_overflow(), traits_type::eof()))
+           if (traits_type::eq_int_type(this->overflow(), traits_type::eof()))
              __ret = -1;
            else if (__off)
              _M_file.seekoff(__off, ios_base::cur);
@@ -444,7 +431,7 @@ namespace std
 
       // This function sets the pointers of the internal buffer, both get
       // and put areas. Typically, __off == _M_in_end - _M_in_beg upon
-      // _M_underflow; __off == 0 upon _M_overflow, seekoff, open, setbuf.
+      // _M_underflow; __off == 0 upon overflow, seekoff, open, setbuf.
       // 
       // NB: _M_out_end - _M_out_beg == _M_buf_size - 1, since _M_buf_size
       // reflects the actual allocated memory and the last cell is reserved
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputc/char/2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputc/char/2.cc
new file mode 100644 (file)
index 0000000..f6a4ae8
--- /dev/null
@@ -0,0 +1,129 @@
+// 2003-05-21 Benjamin Kosnik  <bkoz@redhat.com>
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+// @require@ %-*.tst %-*.txt
+// @diff@ %-*.tst %*.txt
+
+// NB: This test assumes that _M_buf_size == 40, and not the usual
+// buffer_size length of BUFSIZ (8192), so that overflow/underflow can be
+// simulated a bit more readily.
+// NRB (Nota Really Bene): setting it to 40 breaks the test, as intended.
+const int buffer_size = 8192;
+//const int buffer_size = 40;
+
+const char name_01[] = "filebuf_virtuals-1.txt"; // file with data in it
+const char name_02[] = "filebuf_virtuals-2.txt"; // empty file, need to create
+const char name_03[] = "filebuf_virtuals-3.txt"; // empty file, need to create
+
+class derived_filebuf: public std::filebuf
+{
+ public:
+  void
+  set_size(int_type __size) { _M_buf_size = __size; }
+};
+
+derived_filebuf fb_01; // in 
+derived_filebuf fb_02; // out
+derived_filebuf fb_03; // in | out
+
+// Initialize filebufs to be the same size regardless of platform.
+void test03()
+{
+  fb_01.set_size(buffer_size);
+  fb_02.set_size(buffer_size);
+  fb_03.set_size(buffer_size);
+}
+
+// Test overloaded virtual functions.
+void test05() 
+{
+  typedef std::filebuf::int_type       int_type;
+  typedef std::filebuf::traits_type    traits_type;
+  typedef std::filebuf::pos_type       pos_type;
+  typedef std::filebuf::off_type       off_type;
+  typedef size_t                       size_type;
+
+  bool                                         test = true;
+  std::filebuf                                 f_tmp;
+  std::streamsize                      strmsz_1, strmsz_2;
+  std::streamoff                       strmof_1, strmof_2;
+  int                                  i = 0, j = 0, k = 0;
+
+  // Unbuffered
+  fb_01.pubsetbuf(0, 0);
+  fb_02.pubsetbuf(0, 0);
+  fb_03.pubsetbuf(0, 0);
+
+  fb_01.open(name_01, std::ios_base::in);
+  fb_02.open(name_02, std::ios_base::out | std::ios_base::trunc);
+  fb_03.open(name_03, std::ios_base::out | std::ios_base::in | std::ios_base::trunc);
+
+  int_type c1 = fb_01.sbumpc();
+  int_type c2 = fb_02.sbumpc();
+  int_type c3 = fb_01.sbumpc();
+  int_type c4 = fb_02.sbumpc();
+  int_type c5 = fb_03.sbumpc();
+  int_type c6 = fb_01.sgetc();
+  int_type c7 = fb_02.sgetc();
+  int_type c8 = fb_01.sgetc();
+  int_type c9 = fb_02.sgetc();
+
+  // PUT
+  // int_type sputc(char_type c)
+  // if out_cur not avail, return overflow(traits_type::to_int_type(c)) 
+  // else, stores c at out_cur,
+  // increments out_cur, and returns c as int_type
+  // strmsz_1 = fb_03.in_avail();  // XXX valid for in|out??
+  c1 = fb_02.sputc('a'); 
+  c2 = fb_03.sputc('b'); 
+  VERIFY( c1 != c2 );
+  c1 = fb_02.sputc('c'); 
+  c2 = fb_03.sputc('d'); 
+  VERIFY( c1 != c2 );
+  // strmsz_2 = fb_03.in_avail();
+  // VERIFY( strmsz_1 != strmsz_2 );
+  for (int i = 50; i <= 90; ++i) 
+    c2 = fb_02.sputc(char(i));
+  // 27filebuf-2.txt == ac23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+  // fb_02._M_out_cur = '2'
+  strmsz_1 = fb_03.in_avail();
+  for (int i = 50; i <= 90; ++i) 
+    c2 = fb_03.sputc(char(i));
+  strmsz_2 = fb_03.in_avail();
+  // VERIFY( strmsz_1 != strmsz_2 );
+  // VERIFY( strmsz_1 > 0 );
+  // VERIFY( strmsz_2 > 0 );
+  // 27filebuf-2.txt == bd23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+  // fb_02._M_out_cur = '2'
+  c3 = fb_01.sputc('a'); // should be EOF because this is read-only
+  VERIFY( c3 == traits_type::eof() );
+}
+
+main() 
+{
+  test03();
+  test05();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputn/char/9339.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputn/char/9339.cc
new file mode 100644 (file)
index 0000000..37a4145
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+// libstdc++/9339
+void test01()
+{
+  using namespace std;
+  bool test = true;
+
+  filebuf fbuf01;
+  int len = 35;
+  fbuf01.pubsetbuf(0, 0);
+  fbuf01.open("tmp_9339", ios_base::out | ios_base::trunc);
+  streamsize s1 = fbuf01.sputn("Pete Goldlust @ Carl Hammer Gallery", len);
+  VERIFY( s1 == len );
+
+  filebuf fbuf02;
+  char buf[256];
+  fbuf02.open("tmp_9339", ios_base::in);
+  streamsize s2 = fbuf02.sgetn(buf, 256);
+  VERIFY( s2 == len );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}