This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[RFC/Patch] Change _M_overflow to call _M_convert_to_external onlyonce
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: libstdc++ at gcc dot gnu dot org
- Cc: Nathan Myers <ncm at cantrip dot org>
- Date: Sun, 11 May 2003 18:57:12 +0200
- Subject: [RFC/Patch] Change _M_overflow to call _M_convert_to_external onlyonce
Hi again,
this is the interesting part, based on an idea developed
with Nathan.
Basically, the put area is still _M_buf_size sized, but there
is one more allocated char at _M_out_end, which can host
the overflow char of a full buffer.
Everything is quite straightforward, apart from a corner case,
about which I particularly need feedback: what happens for
a setbuf(*, n), n = 1?
In the proposal below, I simply ignore the request: only n = 0
(with the stream closed) and n > 1 have an effect: seems not
a real limitation, considering the actual uses of setbuf
buffers.
Alternately, we could change n = 1 to n = 0 and deal with this
case as I tentatively did for the not-a-bug 9423:
http://gcc.gnu.org/ml/libstdc++/2003-04/msg00088.html
The below is missing comments but passed make check (and a few
other sanity checks).
Thanks,
Paolo.
///////
diff -prN libstdc++-v3-1/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
*** libstdc++-v3-1/include/bits/fstream.tcc Sun May 11 17:22:17 2003
--- libstdc++-v3/include/bits/fstream.tcc Sun May 11 18:47:38 2003
*************** namespace std
*** 51,57 ****
if (!this->_M_buf && this->_M_buf_size)
{
// Allocate internal buffer.
! this->_M_buf = new char_type[this->_M_buf_size];
_M_buf_allocated = true;
}
}
--- 51,57 ----
if (!this->_M_buf && this->_M_buf_size)
{
// Allocate internal buffer.
! this->_M_buf = new char_type[this->_M_buf_size + 1];
_M_buf_allocated = true;
}
}
*************** namespace std
*** 76,82 ****
basic_filebuf<_CharT, _Traits>::
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)
{ this->_M_buf_unified = true; }
--- 76,82 ----
basic_filebuf<_CharT, _Traits>::
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-1), _M_buf_allocated(false),
_M_last_overflowed(false), _M_pback_cur_save(0),
_M_pback_end_save(0), _M_pback_init(false)
{ this->_M_buf_unified = true; }
*************** namespace std
*** 433,478 ****
_M_overflow(int_type __c)
{
int_type __ret = traits_type::eof();
! const bool __testput = this->_M_out_beg < this->_M_out_lim;
const bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size;
! if (__testput || __testunbuffered)
{
// 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 && _M_filepos != this->_M_out_beg)
! {
! off_type __off = this->_M_out_beg - _M_filepos;
! _M_file.seekoff(__off, ios_base::cur);
! }
! // Convert internal buffer to external representation, output.
! // NB: In the unbuffered case, no internal buffer exists.
! if (__testunbuffered || _M_convert_to_external(this->_M_out_beg,
! this->_M_out_lim
! - this->_M_out_beg))
! {
! // Convert pending sequence to external representation, output.
! // If eof, then just attempt sync.
! if (!traits_type::eq_int_type(__c, traits_type::eof()))
! {
! char_type __pending = traits_type::to_char_type(__c);
! // User code must flush when switching modes (thus
! // don't sync).
! if (_M_convert_to_external(&__pending, 1))
! {
! _M_set_indeterminate();
! __ret = traits_type::not_eof(__c);
! }
! }
! else if (!_M_file.sync())
! {
! _M_set_indeterminate();
! __ret = traits_type::not_eof(__c);
! }
! }
}
_M_last_overflowed = true;
return __ret;
}
--- 433,469 ----
_M_overflow(int_type __c)
{
int_type __ret = traits_type::eof();
! const bool __testeof = traits_type::eq_int_type(__c, __ret);
const bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size;
+ bool __convok = false;
! 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 (!__testeof)
! *this->_M_out_lim++ = traits_type::to_char_type(__c);
! __convok = _M_convert_to_external(this->_M_out_beg,
! this->_M_out_lim
! - this->_M_out_beg);
! }
! else if (__testunbuffered && !__testeof)
! {
! char_type __pending = traits_type::to_char_type(__c);
! __convok = _M_convert_to_external(&__pending, 1);
! }
! else if (__testunbuffered && __testeof && !_M_file.sync())
! __convok = true;
! if (__convok)
! {
! _M_set_indeterminate();
! __ret = traits_type::not_eof(__c);
}
+
_M_last_overflowed = true;
return __ret;
}
*************** namespace std
*** 484,490 ****
{
if (!this->is_open() && __s == 0 && __n == 0)
this->_M_buf_size = 0;
! else if (__s && __n)
{
// This is implementation-defined behavior, and assumes
// that an external char_type array of length (__s + __n)
--- 475,481 ----
{
if (!this->is_open() && __s == 0 && __n == 0)
this->_M_buf_size = 0;
! else if (__s && __n > 1)
{
// This is implementation-defined behavior, and assumes
// that an external char_type array of length (__s + __n)
*************** namespace std
*** 496,502 ****
// Step 2: Use the external array.
this->_M_buf = __s;
! this->_M_buf_size = __n;
_M_set_indeterminate();
}
_M_last_overflowed = false;
--- 487,493 ----
// Step 2: Use the external array.
this->_M_buf = __s;
! this->_M_buf_size = __n - 1;
_M_set_indeterminate();
}
_M_last_overflowed = false;
diff -prN libstdc++-v3-1/include/ext/stdio_filebuf.h libstdc++-v3/include/ext/stdio_filebuf.h
*** libstdc++-v3-1/include/ext/stdio_filebuf.h Sun May 11 06:20:55 2003
--- libstdc++-v3/include/ext/stdio_filebuf.h Sun May 11 18:09:44 2003
*************** namespace __gnu_cxx
*** 121,127 ****
if (this->is_open())
{
this->_M_mode = __mode;
! this->_M_buf_size = __size;
_M_allocate_internal_buffer();
_M_set_indeterminate();
}
--- 121,127 ----
if (this->is_open())
{
this->_M_mode = __mode;
! this->_M_buf_size = __size > 1 ? __size - 1 : 0;
_M_allocate_internal_buffer();
_M_set_indeterminate();
}
*************** namespace __gnu_cxx
*** 136,142 ****
if (this->is_open())
{
this->_M_mode = __mode;
! this->_M_buf_size = __size;
_M_allocate_internal_buffer();
_M_set_indeterminate();
}
--- 136,142 ----
if (this->is_open())
{
this->_M_mode = __mode;
! this->_M_buf_size = __size > 1 ? __size - 1 : 0;
_M_allocate_internal_buffer();
_M_set_indeterminate();
}