diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c9383a5eb9e..d2993e4af26 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,21 +1,47 @@ +2003-06-22 Paolo Carlini + Nathan C. Myers + + * include/std/std_streambuf.h (_M_move_out_cur): _M_out_lim + is now used only for filebuf, when _M_buf_unified is true. + epgtr() plays the role of _M_out_lim but it's only updated + upon overflow, underflow, uflow, seekoff/pos. + * include/bits/sstream.tcc (_M_underflow): New, implements + stringbuf::underflow and uflow. + (seekoff, seekpos): Tweak, use _M_update_egptr. + * include/std/std_sstream.h (str): Rewrote, deal correctly + with the new logic, in particular, when pptr() > egptr(). + (_M_sync): When __testout && !__testin set all the get area + pointers to the current string end. + (_M_update_egptr): New, internal function updating egptr() + to the actual string end. + (_M_underflow): New, declare. + (underflow): Dispatch to _M_underflow(false). + (uflow): Dispatch to _M_underflow(true). + + * include/bits/sstream.tcc (pbackfail, overflow, seekoff, + seekpos): Use only the documented derivation interface to + basic_streambuf (gptr(), setg(), etc.) to work right with + user specializations. + * include/std/std_sstream.h (str, _M_sync): Likewise. + 2003-06-20 Doug Gregor - * testsuite/20_util/auto_ptr.cc: don't dereference NULL auto_ptr - * testsuite/21_strings/basic_string/replace/char/4.cc: don't - dereference end iterator. - * testsuite/21_strings/basic_string/replace/wchar_t/4.cc: same. - * testsuite/22_locale/ctype/narrow/char/1.cc: don't subscript with - index equal to the length of a string. - * testsuite/22_locale/ctype/narrow/char/2.cc: same. - * testsuite/22_locale/ctype/narrow/wchar_t/1.cc: same. - * testsuite/22_locale/ctype/narrow/wchar_t/2.cc: same. - * testsuite/22_locale/ctype/widen/char/1.cc: same. - * testsuite/22_locale/ctype/widen/wchar_t/1.cc: same. - * testsuite/23_containers/list_modifiers.cc: don't dereference - singular reverse iterator. - * testsuite/23_containers/vector_bool.cc: don't increment singular - iterator. - * testsuite/24_iterators/rel_ops.cc: don't compare singular iterator. + * testsuite/20_util/auto_ptr.cc: Don't dereference NULL auto_ptr + * testsuite/21_strings/basic_string/replace/char/4.cc: Don't + dereference end iterator. + * testsuite/21_strings/basic_string/replace/wchar_t/4.cc: Same. + * testsuite/22_locale/ctype/narrow/char/1.cc: Don't subscript with + index equal to the length of a string. + * testsuite/22_locale/ctype/narrow/char/2.cc: Same. + * testsuite/22_locale/ctype/narrow/wchar_t/1.cc: Same. + * testsuite/22_locale/ctype/narrow/wchar_t/2.cc: Same. + * testsuite/22_locale/ctype/widen/char/1.cc: Same. + * testsuite/22_locale/ctype/widen/wchar_t/1.cc: Same. + * testsuite/23_containers/list_modifiers.cc: Don't dereference + singular reverse iterator. + * testsuite/23_containers/vector_bool.cc: Don't increment singular + iterator. + * testsuite/24_iterators/rel_ops.cc: Don't compare singular iterator. 2003-06-20 Doug Gregor diff --git a/libstdc++-v3/include/bits/sstream.tcc b/libstdc++-v3/include/bits/sstream.tcc index 764e2801d19..f5b4c578071 100644 --- a/libstdc++-v3/include/bits/sstream.tcc +++ b/libstdc++-v3/include/bits/sstream.tcc @@ -49,11 +49,11 @@ namespace std int_type __ret = traits_type::eof(); const bool __testeof = traits_type::eq_int_type(__c, __ret); - if (this->_M_in_beg < this->_M_in_cur) + if (this->eback() < this->gptr()) { const bool __testeq = traits_type::eq(traits_type::to_char_type(__c), - this->_M_in_cur[-1]); - --this->_M_in_cur; + this->gptr()[-1]); + this->gbump(-1); // Try to put back __c into input sequence in one of three ways. // Order these tests done in is unspecified by the standard. @@ -63,7 +63,7 @@ namespace std __ret = traits_type::not_eof(__c); else { - *this->_M_in_cur = traits_type::to_char_type(__c); + *this->gptr() = traits_type::to_char_type(__c); __ret = __c; } } @@ -88,9 +88,9 @@ namespace std // experimental value (pronounced "arbitrary" in some of the // hipper english-speaking countries), and can be changed to // suit particular needs. - __size_type __len = std::max(__size_type(_M_string.capacity() + 1), - __size_type(512)); - const bool __testput = this->_M_out_cur < this->_M_out_end; + const __size_type __len = std::max(__size_type(_M_string.capacity() + 1), + __size_type(512)); + const bool __testput = this->pptr() < this->epptr(); if (__builtin_expect(!__testput && __len > _M_string.max_size(), false)) return traits_type::eof(); @@ -103,18 +103,37 @@ namespace std // growth policy builtin into basic_string. __string_type __tmp; __tmp.reserve(__len); - __tmp.assign(_M_string.data(), - this->_M_out_end - this->_M_out_beg); + __tmp.assign(_M_string.data(), this->epptr() - this->pbase()); _M_string.swap(__tmp); - // Just to be sure... - _M_string.reserve(__len); _M_sync(const_cast(_M_string.data()), - this->_M_in_cur - this->_M_in_beg, - this->_M_out_cur - this->_M_out_beg); + this->gptr() - this->eback(), + this->pptr() - this->pbase()); } return this->sputc(traits_type::to_char_type(__c)); } + template + typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type + basic_stringbuf<_CharT, _Traits, _Alloc>:: + _M_underflow(bool __bump) + { + int_type __ret = traits_type::eof(); + const bool __testin = this->_M_mode & ios_base::in; + if (__testin) + { + // Update egptr() to match the actual string end. + _M_update_egptr(); + + if (this->gptr() < this->egptr()) + { + __ret = traits_type::to_int_type(*this->gptr()); + if (__bump) + this->gbump(1); + } + } + return __ret; + } + template typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type basic_stringbuf<_CharT, _Traits, _Alloc>:: @@ -129,35 +148,32 @@ namespace std if (_M_string.capacity() && (__testin || __testout || __testboth)) { - char_type* __beg = __testin ? this->_M_in_beg : this->_M_out_beg; + char_type* __beg = __testin ? this->eback() : this->pbase(); + + _M_update_egptr(); off_type __newoffi = 0; off_type __newoffo = 0; if (__way == ios_base::cur) { - __newoffi = this->_M_in_cur - __beg; - __newoffo = this->_M_out_cur - __beg; + __newoffi = this->gptr() - __beg; + __newoffo = this->pptr() - __beg; } else if (__way == ios_base::end) - { - __newoffi = this->_M_in_end - __beg; - // Due to the resolution of DR169, ios_base::end - // is this->_M_out_lim, not _M_out_end. - __newoffo = this->_M_out_lim - __beg; - } + __newoffo = __newoffi = this->egptr() - __beg; if ((__testin || __testboth) && __newoffi + __off >= 0 - && this->_M_in_end - __beg >= __newoffi + __off) + && this->egptr() - __beg >= __newoffi + __off) { - this->_M_in_cur = __beg + __newoffi + __off; + this->gbump((__beg + __newoffi + __off) - this->gptr()); __ret = pos_type(__newoffi); } if ((__testout || __testboth) && __newoffo + __off >= 0 - && this->_M_out_lim - __beg >= __newoffo + __off) + && this->egptr() - __beg >= __newoffo + __off) { - this->_M_out_cur = __beg + __newoffo + __off; + this->pbump((__beg + __newoffo + __off) - this->pptr()); __ret = pos_type(__newoffo); } } @@ -176,23 +192,18 @@ namespace std off_type __pos = __sp; // Use streamoff operator to do conversion. const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0; const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; - char_type* __beg = __testin ? this->_M_in_beg : this->_M_out_beg; + char_type* __beg = __testin ? this->eback() : this->pbase(); - // NB: Ordered. - bool __testposi = false; - bool __testposo = false; - if (__testin && 0 <= __pos - && __pos <= this->_M_in_end - __beg) - __testposi = true; - if (__testout && 0 <= __pos - && __pos <= this->_M_out_lim - __beg) - __testposo = true; - if (__testposi || __testposo) + _M_update_egptr(); + + const bool __testpos = 0 <= __pos + && __pos <= this->egptr() - __beg; + if ((__testin || __testout) && __testpos) { - if (__testposi) - this->_M_in_cur = __beg + __pos; - if (__testposo) - this->_M_out_cur = __beg + __pos; + if (__testin) + this->gbump((__beg + __pos) - this->gptr()); + if (__testout) + this->pbump((__beg + __pos) - this->pptr()); __ret = pos_type(off_type(__pos)); } } diff --git a/libstdc++-v3/include/std/std_sstream.h b/libstdc++-v3/include/std/std_sstream.h index 7f3fc6440cc..687e26ad07e 100644 --- a/libstdc++-v3/include/std/std_sstream.h +++ b/libstdc++-v3/include/std/std_sstream.h @@ -133,11 +133,17 @@ namespace std __string_type str() const { - __string_type __ret = _M_string; const bool __testout = this->_M_mode & ios_base::out; - if (__testout && this->_M_out_beg < this->_M_out_lim) - __ret = __string_type(this->_M_out_beg, this->_M_out_lim); - return __ret; + if (__testout) + { + // The current egptr() may not be the actual string end. + if (this->pptr() > this->egptr()) + return __string_type(this->pbase(), this->pptr()); + else + return __string_type(this->pbase(), this->egptr()); + } + else + return _M_string; } /** @@ -173,18 +179,18 @@ namespace std _M_sync(const_cast(_M_string.data()), 0, __len); } - // Overridden virtual functions: + int_type + _M_underflow(bool __bump); + // [documentation is inherited] virtual int_type underflow() - { - int_type __ret; - if (this->_M_in_cur < this->_M_in_end) - __ret = traits_type::to_int_type(*this->_M_in_cur); - else - __ret = traits_type::eof(); - return __ret; - } + { return _M_underflow(false); } + + // [documentation is inherited] + virtual int_type + uflow() + { return _M_underflow(true); } // [documentation is inherited] virtual int_type @@ -250,18 +256,37 @@ namespace std { const bool __testin = this->_M_mode & ios_base::in; const bool __testout = this->_M_mode & ios_base::out; - __size_type __len = _M_string.size(); + const __size_type __len = _M_string.size(); if (__testin) this->setg(__base, __base + __i, __base + __len); if (__testout) { this->setp(__base, __base + _M_string.capacity()); - // _M_out_lim points to the string end. - this->_M_out_lim += __len; - this->_M_out_cur += __o; + this->pbump(__o); + // We need a pointer to the string end anyway, even when + // !__testin: in that case, however, for the correct + // functioning of the streambuf inlines all the get area + // pointers must be identical. + if (!__testin) + this->setg(__base + __len, __base + __len, __base + __len); } } + + // Internal function for correctly updating egptr() to the actual + // string end. + void + _M_update_egptr() + { + const bool __testin = this->_M_mode & ios_base::in; + const bool __testout = this->_M_mode & ios_base::out; + + if (__testout && this->pptr() > this->egptr()) + if (__testin) + this->setg(this->eback(), this->gptr(), this->pptr()); + else + this->setg(this->pptr(), this->pptr(), this->pptr()); + } }; diff --git a/libstdc++-v3/include/std/std_streambuf.h b/libstdc++-v3/include/std/std_streambuf.h index 20928078d9d..fa85bf4641e 100644 --- a/libstdc++-v3/include/std/std_streambuf.h +++ b/libstdc++-v3/include/std/std_streambuf.h @@ -238,17 +238,19 @@ namespace std void _M_move_out_cur(off_type __n) // argument needs to be +- { - const bool __testin = _M_in_cur; - _M_out_cur += __n; - if (__testin && _M_buf_unified) - _M_in_cur += __n; - if (_M_out_cur > _M_out_lim) + if (__builtin_expect(_M_buf_unified, false)) { - _M_out_lim = _M_out_cur; - // NB: in | out buffers drag the _M_in_end pointer along... + const bool __testin = _M_in_cur; if (__testin) - _M_in_end += __n; + _M_in_cur += __n; + if (_M_out_cur > _M_out_lim) + { + _M_out_lim = _M_out_cur; + // NB: in | out buffers drag the _M_in_end pointer along... + if (__testin) + _M_in_end += __n; + } } }