+2003-06-22 Paolo Carlini <pcarlini@unitus.it>
+ Nathan C. Myers <ncm-nospam@cantrip.org>
+
+ * 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 <dgregor@apple.com>
- * 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 <dgregor@apple.com>
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.
__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;
}
}
// 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();
// 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<char_type*>(_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 <class _CharT, class _Traits, class _Alloc>
+ 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 <class _CharT, class _Traits, class _Alloc>
typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
basic_stringbuf<_CharT, _Traits, _Alloc>::
seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
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);
}
}
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));
}
}
__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;
}
/**
_M_sync(const_cast<char_type*>(_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
{
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());
+ }
};
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;
+ }
}
}