]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libstdc++/12875 (Weird behaviour in basic_filebuf::setbuf())
authorPaolo Carlini <pcarlini@suse.de>
Wed, 12 Nov 2003 01:14:34 +0000 (01:14 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Wed, 12 Nov 2003 01:14:34 +0000 (01:14 +0000)
2003-11-11  Paolo Carlini  <pcarlini@suse.de>

PR libstdc++/12875
* include/bits/fstream.tcc (setbuf): Don't do anything
after open(), in particular don't discard data.
(_M_allocate_internal_buffer): Tweak to not allocate memory
in case the buffer is provided by the user via setbuf.
* include/ext/stdio_filebuf.h: Tweak comment.
* testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc: New.
* testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc: Likewise.
* testsuite/27_io/basic_filebuf/setbuf/char/2.cc: Tweak, now
setbuf does nothing after open().
* testsuite/27_io/basic_filebuf/setbuf/char/3.cc: Likewise.

From-SVN: r73477

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/ext/stdio_filebuf.h
libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/2.cc
libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/3.cc

index 1df66abe038bf51f3145d949aea226e85d85fa3b..791cee3e85fc8931e731c610a3d5baf35cedaf53 100644 (file)
@@ -1,3 +1,17 @@
+2003-11-11  Paolo Carlini  <pcarlini@suse.de>
+
+       PR libstdc++/12875
+       * include/bits/fstream.tcc (setbuf): Don't do anything
+       after open(), in particular don't discard data.
+       (_M_allocate_internal_buffer): Tweak to not allocate memory
+       in case the buffer is provided by the user via setbuf.
+       * include/ext/stdio_filebuf.h: Tweak comment.
+       * testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc: New.
+       * testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc: Likewise.
+       * testsuite/27_io/basic_filebuf/setbuf/char/2.cc: Tweak, now
+       setbuf does nothing after open().
+       * testsuite/27_io/basic_filebuf/setbuf/char/3.cc: Likewise.
+
 2003-11-11  Doug Gregor  <gregod@cs.rpi.edu>
 
        * docs/html/debug.html: Document libstdc++ debug mode.
index 56497412fce56575d0da2ef172788b295397781d..a2daab5476123b5af3075b0dfe0856c829bc4401 100644 (file)
@@ -44,15 +44,15 @@ namespace std
     basic_filebuf<_CharT, _Traits>::
     _M_allocate_internal_buffer()
     {
-      if (!_M_buf_allocated && this->_M_buf_size)
+      // Allocate internal buffer only if one doesn't already exist
+      // (either allocated or provided by the user via setbuf).
+      if (!_M_buf_allocated && !this->_M_buf)
        {
-         // Allocate internal buffer.
          this->_M_buf = new char_type[this->_M_buf_size];
          _M_buf_allocated = true;
        }
     }
 
-  // Both close and setbuf need to deallocate internal buffers, if it exists.
   template<typename _CharT, typename _Traits>
     void
     basic_filebuf<_CharT, _Traits>::
@@ -213,8 +213,8 @@ namespace std
          else
            {
               // Worst-case number of external bytes.
-              // XXX Not done encoding() == -1.
-              const int __enc = _M_codecvt->encoding();
+             // XXX Not done encoding() == -1.
+             const int __enc = _M_codecvt->encoding();
              streamsize __blen; // Minimum buffer size.
              streamsize __rlen; // Number of chars to read.
              if (__enc > 0)
@@ -539,29 +539,22 @@ namespace std
     basic_filebuf<_CharT, _Traits>::
     setbuf(char_type* __s, streamsize __n)
     {
-      if (!this->is_open() && __s == 0 && __n == 0)
-       this->_M_buf_size = 1;
-      else if (__s && __n > 0)
-       {
-         // This is implementation-defined behavior, and assumes that
-         // an external char_type array of length __n exists and has
-         // been pre-allocated. If this is not the case, things will
-         // quickly blow up. When __n > 1, __n - 1 positions will be
-         // used for the get area, __n - 1 for the put area and 1
-         // position to host the overflow char of a full put area.
-         // When __n == 1, 1 position will be used for the get area
-         // and 0 for the put area, as in the unbuffered case above.
-
-         // Step 1: Destroy the current internal array.
-         _M_destroy_internal_buffer();
-         
-         // Step 2: Use the external array.
-         this->_M_buf = __s;
-         this->_M_buf_size = __n;
-         _M_reading = false;
-         _M_writing = false;
-         _M_set_buffer(-1);
-       }
+      if (!this->is_open())
+       if (__s == 0 && __n == 0)
+         this->_M_buf_size = 1;
+       else if (__s && __n > 0)
+         {
+           // This is implementation-defined behavior, and assumes that
+           // an external char_type array of length __n exists and has
+           // been pre-allocated. If this is not the case, things will
+           // quickly blow up. When __n > 1, __n - 1 positions will be
+           // used for the get area, __n - 1 for the put area and 1
+           // position to host the overflow char of a full put area.
+           // When __n == 1, 1 position will be used for the get area
+           // and 0 for the put area, as in the unbuffered case above.
+           this->_M_buf = __s;
+           this->_M_buf_size = __n;
+         }
       return this; 
     }
   
index 8750f5801e3662153faae4a546d900bbe1956f1e..9e04807b33e0709f7e0c159bd93d852b54f25914 100644 (file)
@@ -66,9 +66,7 @@ namespace __gnu_cxx
        *  @param  fd  An open file descriptor.
        *  @param  mode  Same meaning as in a standard filebuf.
        *  @param  del  Whether to close the file on destruction.
-       *  @param  size  Optimal or preferred size of internal buffer, in bytes.
-       *                Note that it includes a position for the overflow char,
-       *                therefore, can't be smaller than 2.
+       *  @param  size  Optimal or preferred size of internal buffer, in chars.
        *
        *  This constructor associates a file stream buffer with an open
        *  POSIX file descriptor.  Iff @a del is true, then the associated
@@ -80,10 +78,8 @@ namespace __gnu_cxx
       /**
        *  @param  f  An open @c FILE*.
        *  @param  mode  Same meaning as in a standard filebuf.
-       *  @param  size  Optimal or preferred size of internal buffer, in bytes.
-       *                Defaults to system's @c BUFSIZ. Note that it includes
-       *                a position for the overflow char, therefore, can't be
-       *                smaller than 2.
+       *  @param  size  Optimal or preferred size of internal buffer, in chars.
+       *                Defaults to system's @c BUFSIZ. 
        *
        *  This constructor associates a file stream buffer with an open
        *  C @c FILE*.  The @c FILE* will not be automatically closed when the
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc
new file mode 100644 (file)
index 0000000..5013b87
--- /dev/null
@@ -0,0 +1,57 @@
+// 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 <cstdio>
+#include <cstring>
+#include <testsuite_hooks.h>
+
+// libstdc++/12875
+void test01()
+{
+  using namespace std;
+  bool test __attribute__((unused)) = true;
+
+  const char* name = "tmp_setbuf4";
+  static char buf[1024];
+  
+  FILE* out = fopen(name, "w");
+  fputs("Hello, world", out);
+  fclose(out);
+  
+  filebuf in;
+  in.open(name, ios_base::in);
+  char str[256];
+  streamsize r = in.sgetn(str, 6);
+  VERIFY( r == 6 );
+  VERIFY( !memcmp(str, "Hello,", 6) );
+  in.pubsetbuf(buf, 1024);
+  r = in.sgetn(str, 6);
+  VERIFY( r == 6 );
+  VERIFY( !memcmp(str, " world", 6) );
+  in.close();
+}
+
+// libstdc++/12875
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc
new file mode 100644 (file)
index 0000000..c50a5ed
--- /dev/null
@@ -0,0 +1,55 @@
+// 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 <cstdio>
+#include <cstring>
+#include <testsuite_hooks.h>
+
+// libstdc++/12875
+void test02()
+{
+  using namespace std;
+  bool test __attribute__((unused)) = true;
+
+  const char* name = "tmp_setbuf5";
+  static char buf[1024];
+  
+  filebuf out;
+  out.open(name, ios_base::out);
+  streamsize r = out.sputn("Hello,", 6);
+  VERIFY( r == 6 );
+  out.pubsetbuf(buf, 1024);
+  r = out.sputn(" world", 6);
+  VERIFY( r == 6 );
+  VERIFY( out.close() );
+  
+  FILE* in = fopen(name, "r");
+  char str[256];
+  fgets(str, 256, in);
+  VERIFY( !strcmp(str, "Hello, world") );
+  fclose(in);
+}
+
+int main()
+{
+  test02();
+  return 0;
+}
index 7cca957e17f76d687393b519f9cc7d093016bf3e..524935a1c84077d16eb5b81ddad3fc27aaab8f1c 100644 (file)
@@ -32,8 +32,8 @@ void test01()
   const char* strlit = "how to tell a story and other essays: mark twain";
   const size_t strlitsize = std::strlen(strlit);
   filebuf fbuf;
-  fbuf.open("tmp_setbuf2", ios_base::out);
   fbuf.pubsetbuf(buf, 512);
+  fbuf.open("tmp_setbuf2", ios_base::out);
   fbuf.sputn(strlit, strlitsize);
   VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
 }
index b5512d765347ecd79783f362b72a4432bd095de0..11702dc03365e5e3eb4d7356b05f51e17343775b 100644 (file)
@@ -23,7 +23,7 @@
 #include <fstream>
 #include <testsuite_hooks.h>
 
-void test02()
+void test03()
 {
   using namespace std;
 
@@ -32,17 +32,17 @@ void test02()
   const char* strlit = "how to tell a story and other essays: mark twain";
   const size_t strlitsize = std::strlen(strlit);
   filebuf fbuf01;
-  fbuf01.open("tmp", ios_base::out);
-
   // NB: +2 otherwise sputn is optimized to a direct write,
   // bypassing the buffer.
   fbuf01.pubsetbuf(buf, strlitsize + 2);
+  fbuf01.open("tmp_setbuf3", ios_base::out);
+
   fbuf01.sputn(strlit, strlitsize);
   VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
 }
 
 int main() 
 {
-  test02();
+  test03();
   return 0;
 }