This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3] libstdc++/9339
- From: Benjamin Kosnik <bkoz at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 26 May 2003 10:54:46 -0400 (EDT)
- Subject: [v3] libstdc++/9339
Removes some of the overflow complexity, adds in unbuffered. Still
related bugs (9024). Also, the unbuffered input bits need to be taken
care of.
tested x86/linux
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.
Index: include/bits/fstream.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/fstream.tcc,v
retrieving revision 1.78
diff -c -p -r1.78 fstream.tcc
*** include/bits/fstream.tcc 22 May 2003 22:16:39 -0000 1.78
--- include/bits/fstream.tcc 26 May 2003 14:51:19 -0000
*************** namespace std
*** 73,79 ****
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_pback_end_save(0), _M_pback_init(false), _M_codecvt(0)
{
this->_M_buf_unified = true;
--- 73,79 ----
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_filepos(0), _M_pback_cur_save(0),
_M_pback_end_save(0), _M_pback_init(false), _M_codecvt(0)
{
this->_M_buf_unified = true;
*************** namespace std
*** 125,131 ****
const bool __testput = this->_M_out_beg < this->_M_out_lim;
if (__testput
! && traits_type::eq_int_type(_M_overflow(__eof), __eof))
__testfail = true;
#if 0
--- 125,131 ----
const bool __testput = this->_M_out_beg < this->_M_out_lim;
if (__testput
! && traits_type::eq_int_type(this->overflow(), __eof))
__testfail = true;
#if 0
*************** namespace std
*** 133,139 ****
if (_M_last_overflowed)
{
_M_output_unshift();
! _M_overflow(__eof);
}
#endif
}
--- 133,139 ----
if (_M_last_overflowed)
{
_M_output_unshift();
! this->overflow();
}
#endif
}
*************** namespace std
*** 204,210 ****
// Sync internal and external buffers.
if (__testout && this->_M_out_beg < this->_M_out_lim)
! _M_overflow();
if (_M_buf_size > 1)
{
--- 204,210 ----
// Sync internal and external buffers.
if (__testout && this->_M_out_beg < this->_M_out_lim)
! this->overflow();
if (_M_buf_size > 1)
{
*************** namespace std
*** 324,387 ****
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 __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)
{
! *this->_M_out_cur = traits_type::to_char_type(__c);
! _M_move_out_cur(1);
! __ret = traits_type::not_eof(__c);
}
- else
- __ret = this->_M_overflow(__c);
}
return __ret;
}
--- 324,369 ----
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 __testeof = traits_type::eq_int_type(__c, __ret);
const bool __testout = this->_M_mode & ios_base::out;
if (__testout)
{
! 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
{
! // Unbuffered.
! char_type __conv = traits_type::to_char_type(__c);
! if (!__testeof && _M_convert_to_external(&__conv, 1))
! __ret = __c;
}
}
+ _M_last_overflowed = true;
return __ret;
}
Index: include/bits/streambuf.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/streambuf.tcc,v
retrieving revision 1.38
diff -c -p -r1.38 streambuf.tcc
*** include/bits/streambuf.tcc 2 May 2003 18:35:24 -0000 1.38
--- include/bits/streambuf.tcc 26 May 2003 14:51:19 -0000
*************** namespace std
*** 115,121 ****
while (__ret < __n)
{
const size_t __buf_len = _M_in_end - _M_in_cur;
! if (__buf_len > 0)
{
const size_t __remaining = __n - __ret;
const size_t __len = std::min(__buf_len, __remaining);
--- 115,121 ----
while (__ret < __n)
{
const size_t __buf_len = _M_in_end - _M_in_cur;
! if (__buf_len)
{
const size_t __remaining = __n - __ret;
const size_t __len = std::min(__buf_len, __remaining);
*************** namespace std
*** 149,155 ****
while (__ret < __n)
{
const size_t __buf_len = _M_out_end - _M_out_cur;
! if (__buf_len > 0)
{
const size_t __remaining = __n - __ret;
const size_t __len = std::min(__buf_len, __remaining);
--- 149,155 ----
while (__ret < __n)
{
const size_t __buf_len = _M_out_end - _M_out_cur;
! if (__buf_len)
{
const size_t __remaining = __n - __ret;
const size_t __len = std::min(__buf_len, __remaining);
*************** namespace std
*** 161,167 ****
if (__ret < __n)
{
! const int_type __c = this->overflow(traits_type::to_int_type(*__s));
if (!traits_type::eq_int_type(__c, traits_type::eof()))
{
++__ret;
--- 161,167 ----
if (__ret < __n)
{
! int_type __c = this->overflow(traits_type::to_int_type(*__s));
if (!traits_type::eq_int_type(__c, traits_type::eof()))
{
++__ret;
Index: include/std/std_fstream.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_fstream.h,v
retrieving revision 1.40
diff -c -p -r1.40 std_fstream.h
*** include/std/std_fstream.h 22 May 2003 22:16:40 -0000 1.40
--- include/std/std_fstream.h 26 May 2003 14:51:19 -0000
*************** namespace std
*** 158,164 ****
* @note pbacks of over one character are not currently supported.
* @endif
*/
! char_type _M_pback[1];
char_type* _M_pback_cur_save;
char_type* _M_pback_end_save;
bool _M_pback_init;
--- 158,164 ----
* @note pbacks of over one character are not currently supported.
* @endif
*/
! char_type _M_pback;
char_type* _M_pback_cur_save;
char_type* _M_pback_end_save;
bool _M_pback_init;
*************** namespace std
*** 177,183 ****
{
_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);
_M_pback_init = true;
}
}
--- 177,183 ----
{
_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);
_M_pback_init = true;
}
}
*************** namespace std
*** 191,198 ****
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,
_M_pback_end_save);
_M_pback_init = false;
}
--- 191,198 ----
if (_M_pback_init)
{
// Length _M_in_cur moved in the pback buffer.
! 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;
}
*************** namespace std
*** 311,329 ****
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
--- 311,316 ----
*************** namespace std
*** 336,343 ****
* @doctodo
* @endif
*/
! int_type
! _M_overflow(int_type __c = _Traits::eof());
// Convert internal byte sequence to external, char-based
// sequence via codecvt.
--- 323,330 ----
* @doctodo
* @endif
*/
! virtual int_type
! overflow(int_type __c = _Traits::eof());
// Convert internal byte sequence to external, char-based
// sequence via codecvt.
*************** namespace std
*** 389,395 ****
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()))
__ret = -1;
else if (__off)
_M_file.seekoff(__off, ios_base::cur);
--- 376,382 ----
off_type __off = this->_M_out_cur - this->_M_out_lim;
// _M_file.sync() will be called within
! if (traits_type::eq_int_type(this->overflow(), traits_type::eof()))
__ret = -1;
else if (__off)
_M_file.seekoff(__off, ios_base::cur);
*************** namespace std
*** 444,450 ****
// 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.
//
// 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
--- 431,437 ----
// 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 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
Index: testsuite/27_io/basic_filebuf/sputc/char/2.cc
===================================================================
RCS file: testsuite/27_io/basic_filebuf/sputc/char/2.cc
diff -N testsuite/27_io/basic_filebuf/sputc/char/2.cc
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/27_io/basic_filebuf/sputc/char/2.cc 26 May 2003 14:51:20 -0000
***************
*** 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;
+ }
Index: testsuite/27_io/basic_filebuf/sputn/char/9339.cc
===================================================================
RCS file: testsuite/27_io/basic_filebuf/sputn/char/9339.cc
diff -N testsuite/27_io/basic_filebuf/sputn/char/9339.cc
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/27_io/basic_filebuf/sputn/char/9339.cc 26 May 2003 14:51:20 -0000
***************
*** 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;
+ }