mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-02 16:23:56 +08:00
re PR libstdc++/12875 (Weird behaviour in basic_filebuf::setbuf())
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
This commit is contained in:
parent
a5966c9ef9
commit
dfad48c6e8
@ -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>
|
2003-11-11 Doug Gregor <gregod@cs.rpi.edu>
|
||||||
|
|
||||||
* docs/html/debug.html: Document libstdc++ debug mode.
|
* docs/html/debug.html: Document libstdc++ debug mode.
|
||||||
|
@ -44,15 +44,15 @@ namespace std
|
|||||||
basic_filebuf<_CharT, _Traits>::
|
basic_filebuf<_CharT, _Traits>::
|
||||||
_M_allocate_internal_buffer()
|
_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];
|
this->_M_buf = new char_type[this->_M_buf_size];
|
||||||
_M_buf_allocated = true;
|
_M_buf_allocated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both close and setbuf need to deallocate internal buffers, if it exists.
|
|
||||||
template<typename _CharT, typename _Traits>
|
template<typename _CharT, typename _Traits>
|
||||||
void
|
void
|
||||||
basic_filebuf<_CharT, _Traits>::
|
basic_filebuf<_CharT, _Traits>::
|
||||||
@ -213,8 +213,8 @@ namespace std
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Worst-case number of external bytes.
|
// Worst-case number of external bytes.
|
||||||
// XXX Not done encoding() == -1.
|
// XXX Not done encoding() == -1.
|
||||||
const int __enc = _M_codecvt->encoding();
|
const int __enc = _M_codecvt->encoding();
|
||||||
streamsize __blen; // Minimum buffer size.
|
streamsize __blen; // Minimum buffer size.
|
||||||
streamsize __rlen; // Number of chars to read.
|
streamsize __rlen; // Number of chars to read.
|
||||||
if (__enc > 0)
|
if (__enc > 0)
|
||||||
@ -539,29 +539,22 @@ namespace std
|
|||||||
basic_filebuf<_CharT, _Traits>::
|
basic_filebuf<_CharT, _Traits>::
|
||||||
setbuf(char_type* __s, streamsize __n)
|
setbuf(char_type* __s, streamsize __n)
|
||||||
{
|
{
|
||||||
if (!this->is_open() && __s == 0 && __n == 0)
|
if (!this->is_open())
|
||||||
this->_M_buf_size = 1;
|
if (__s == 0 && __n == 0)
|
||||||
else if (__s && __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
|
// This is implementation-defined behavior, and assumes that
|
||||||
// been pre-allocated. If this is not the case, things will
|
// an external char_type array of length __n exists and has
|
||||||
// quickly blow up. When __n > 1, __n - 1 positions will be
|
// been pre-allocated. If this is not the case, things will
|
||||||
// used for the get area, __n - 1 for the put area and 1
|
// quickly blow up. When __n > 1, __n - 1 positions will be
|
||||||
// position to host the overflow char of a full put area.
|
// used for the get area, __n - 1 for the put area and 1
|
||||||
// When __n == 1, 1 position will be used for the get area
|
// position to host the overflow char of a full put area.
|
||||||
// and 0 for the put area, as in the unbuffered case above.
|
// 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.
|
this->_M_buf = __s;
|
||||||
_M_destroy_internal_buffer();
|
this->_M_buf_size = __n;
|
||||||
|
}
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,9 +66,7 @@ namespace __gnu_cxx
|
|||||||
* @param fd An open file descriptor.
|
* @param fd An open file descriptor.
|
||||||
* @param mode Same meaning as in a standard filebuf.
|
* @param mode Same meaning as in a standard filebuf.
|
||||||
* @param del Whether to close the file on destruction.
|
* @param del Whether to close the file on destruction.
|
||||||
* @param size Optimal or preferred size of internal buffer, in bytes.
|
* @param size Optimal or preferred size of internal buffer, in chars.
|
||||||
* Note that it includes a position for the overflow char,
|
|
||||||
* therefore, can't be smaller than 2.
|
|
||||||
*
|
*
|
||||||
* This constructor associates a file stream buffer with an open
|
* This constructor associates a file stream buffer with an open
|
||||||
* POSIX file descriptor. Iff @a del is true, then the associated
|
* 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 f An open @c FILE*.
|
||||||
* @param mode Same meaning as in a standard filebuf.
|
* @param mode Same meaning as in a standard filebuf.
|
||||||
* @param size Optimal or preferred size of internal buffer, in bytes.
|
* @param size Optimal or preferred size of internal buffer, in chars.
|
||||||
* Defaults to system's @c BUFSIZ. Note that it includes
|
* Defaults to system's @c BUFSIZ.
|
||||||
* a position for the overflow char, therefore, can't be
|
|
||||||
* smaller than 2.
|
|
||||||
*
|
*
|
||||||
* This constructor associates a file stream buffer with an open
|
* This constructor associates a file stream buffer with an open
|
||||||
* C @c FILE*. The @c FILE* will not be automatically closed when the
|
* C @c FILE*. The @c FILE* will not be automatically closed when the
|
||||||
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -32,8 +32,8 @@ void test01()
|
|||||||
const char* strlit = "how to tell a story and other essays: mark twain";
|
const char* strlit = "how to tell a story and other essays: mark twain";
|
||||||
const size_t strlitsize = std::strlen(strlit);
|
const size_t strlitsize = std::strlen(strlit);
|
||||||
filebuf fbuf;
|
filebuf fbuf;
|
||||||
fbuf.open("tmp_setbuf2", ios_base::out);
|
|
||||||
fbuf.pubsetbuf(buf, 512);
|
fbuf.pubsetbuf(buf, 512);
|
||||||
|
fbuf.open("tmp_setbuf2", ios_base::out);
|
||||||
fbuf.sputn(strlit, strlitsize);
|
fbuf.sputn(strlit, strlitsize);
|
||||||
VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
|
VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
void test02()
|
void test03()
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -32,17 +32,17 @@ void test02()
|
|||||||
const char* strlit = "how to tell a story and other essays: mark twain";
|
const char* strlit = "how to tell a story and other essays: mark twain";
|
||||||
const size_t strlitsize = std::strlen(strlit);
|
const size_t strlitsize = std::strlen(strlit);
|
||||||
filebuf fbuf01;
|
filebuf fbuf01;
|
||||||
fbuf01.open("tmp", ios_base::out);
|
|
||||||
|
|
||||||
// NB: +2 otherwise sputn is optimized to a direct write,
|
// NB: +2 otherwise sputn is optimized to a direct write,
|
||||||
// bypassing the buffer.
|
// bypassing the buffer.
|
||||||
fbuf01.pubsetbuf(buf, strlitsize + 2);
|
fbuf01.pubsetbuf(buf, strlitsize + 2);
|
||||||
|
fbuf01.open("tmp_setbuf3", ios_base::out);
|
||||||
|
|
||||||
fbuf01.sputn(strlit, strlitsize);
|
fbuf01.sputn(strlit, strlitsize);
|
||||||
VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
|
VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
test02();
|
test03();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user