This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3] Fix libstdc++/12875


Hi,

tested x86-linux, reviewed by Benjamin.

Paolo.

//////////
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.
diff -urN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
--- libstdc++-v3-orig/include/bits/fstream.tcc	2003-11-04 06:27:37.000000000 +0100
+++ libstdc++-v3/include/bits/fstream.tcc	2003-11-11 17:01:37.000000000 +0100
@@ -44,15 +44,15 @@
     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 @@
 	  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 @@
     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; 
     }
   
diff -urN libstdc++-v3-orig/include/ext/stdio_filebuf.h libstdc++-v3/include/ext/stdio_filebuf.h
--- libstdc++-v3-orig/include/ext/stdio_filebuf.h	2003-07-14 04:52:05.000000000 +0200
+++ libstdc++-v3/include/ext/stdio_filebuf.h	2003-11-11 17:01:37.000000000 +0100
@@ -66,9 +66,7 @@
        *  @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 @@
       /**
        *  @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 -urN libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc
--- libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-1.cc	2003-11-11 17:02:49.000000000 +0100
@@ -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 -urN libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc
--- libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/12875-2.cc	2003-11-11 17:03:14.000000000 +0100
@@ -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;
+}
diff -urN libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/2.cc libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/2.cc
--- libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/2.cc	2003-09-23 22:02:59.000000000 +0200
+++ libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/2.cc	2003-11-11 17:01:37.000000000 +0100
@@ -32,8 +32,8 @@
   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 );
 }
diff -urN libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/3.cc libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/3.cc
--- libstdc++-v3-orig/testsuite/27_io/basic_filebuf/setbuf/char/3.cc	2003-09-23 22:02:59.000000000 +0200
+++ libstdc++-v3/testsuite/27_io/basic_filebuf/setbuf/char/3.cc	2003-11-11 17:01:37.000000000 +0100
@@ -23,7 +23,7 @@
 #include <fstream>
 #include <testsuite_hooks.h>
 
-void test02()
+void test03()
 {
   using namespace std;
 
@@ -32,17 +32,17 @@
   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;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]