/* virtual */ strstreambuf::pos_type strstreambuf::seekpos (pos_type sp, ios::openmode which) { _RWSTD_ASSERT (_C_is_valid ()); // call seekoff() defined by strstreambuf, and // not an overridden() virtual if one exists return strstreambuf::seekoff (sp - pos_type (), ios::beg, which); }
/* virtual */ strstreambuf::~strstreambuf () { _RWSTD_ASSERT (_C_is_valid ()); if ( _C_buffer && _C_state & _C_allocated && !(_C_state & _C_frozen)) { if (_C_pfree) _C_pfree (_C_buffer); else delete[] _C_buffer; } }
/* virtual */ strstreambuf::int_type strstreambuf::pbackfail (int_type c) { _RWSTD_ASSERT (_C_is_valid ()); typedef traits_type Traits; if (eback () < gptr ()) { // putback position is available (see 27.5.1, p3, bullet 3) if (Traits::eq_int_type (c, Traits::eof ())) { // D.7.1.3, p6, bullet 3 gbump (-1); return Traits::not_eof (c); } if (Traits::eq_int_type (Traits::to_int_type (*(gptr () - 1)), c)) { // D.7.1.3, p6, bullet 1 gbump (-1); return c; } if (!(_C_state & _C_constant)) { // D.7.1.3, p6, bullet 2 gbump (-1); Traits::assign (*gptr (), Traits::to_char_type (c)); return c; } } // D.7.1.3, p7 return Traits::eof (); }
/* virtual */ strstreambuf::int_type strstreambuf::overflow (int_type c) { _RWSTD_ASSERT (_C_is_valid ()); if (!_C_is_out () || !(_C_state & _C_dynamic)) return traits_type::eof (); if (_C_is_eof (c)) return traits_type::not_eof (c); // reallocate space if necessary if (!(pptr () < epptr ())) { const streamsize new_size = _C_bufsize ? _C_bufsize * 2 : _C_alsize ? _C_alsize : 128; // take care to avoid calling the overridden setbuf(), if any if (!strstreambuf::setbuf (0, new_size)) return traits_type::eof (); } return sputc (traits_type::to_char_type (c)); }
/* virtual */ streambuf* strstreambuf::setbuf (char_type* buf, streamsize bufsize) { _RWSTD_ASSERT (_C_is_valid ()); if ( !(_C_state & _C_dynamic) || (_C_state & _C_frozen) || (!buf && !bufsize)) { // lwg issue 66 return 0; } // determine the existing (possibly disjoint) sequences // in the (possibly two distinct) buffer(s) and copy // them into the new buffer // [.....] [.....] or [....[.]...] // ^ ^ ^ ^ ^ ^ // | | | | | | // | | | +- xend | +- xend, gap_beg, gap_end // | | +------- gap_end +------------ xbeg // | +---------- gap_beg // +---------------- xbeg const char_type* const xbeg = eback () && eback () < pbase () ? eback () : pbase (); const char_type* const xend = epptr () && epptr () < egptr () ? egptr () : epptr (); const char_type *gap_beg = pptr () < eback () ? pptr () : egptr () < pbase () ? egptr () : pbase (); const char_type *gap_end = pptr () < eback () ? eback () : egptr () < pbase () ? egptr () : pbase (); // if gap_end is before gap_beg, set both so as to make the gap zero size if (gap_end <= gap_beg) gap_beg = gap_end = xend; // compute the cumulative size of both sequences minus the gap const streamsize slen = streamsize ((xend - xbeg) - (gap_end - gap_beg)); if (bufsize < slen || !_C_is_out ()) return 0; // failure const bool free_old_buf = _C_own_buf (); if (!buf) { _TRY { // allocate a new buffer buf = _C_palloc ? _RWSTD_STATIC_CAST (char_type*, _C_palloc (bufsize)) : new char [bufsize]; } _CATCH (...) { // catch all exceptions, indicate failure by returning 0 } if (!buf) return 0; _C_own_buf (true); }
/* virtual */ strstreambuf::pos_type strstreambuf::seekoff (off_type off, ios::seekdir way, ios::openmode which) { _RWSTD_ASSERT (_C_is_valid ()); // should implicitly hold as long as ios::seekdir is an enum _RWSTD_ASSERT (ios::beg == way || ios::cur == way || ios::end == way); _RWSTD_ASSERT (_C_is_valid ()); // determine seekable area - D.7.1, p4 char* const seeklo = eback (); char* const seekhi = epptr () ? epptr () : egptr (); const char* const xnext = which & ios::in ? gptr () : pptr (); const char* const xbeg = which & ios::in ? eback () : pbase (); // D.7.1.3, p13 if (!xnext) return pos_type (off_type (-1)); off_type saved_off = off; // compute new offset - D.7.1.3, p13, table 105 if (ios::cur == way) off += off_type (xnext - xbeg); else if (ios::end == way) off += off_type (seekhi - xbeg); // test conditions in D.7.1.3, p13, table 105, row 4 if (off < seeklo - xbeg || off > seekhi - xbeg) off = -1; // failure else if (which & ios::in) { // position input sequence // fail if `way' is `cur', otherwise position output sequence first if ( which & ios::out && ( way == ios::cur || pos_type (-1) == seekoff (saved_off, way, ios::out))) return pos_type (off_type (-1)); // adjust input sequence as necessary to maintain invariant if (off <= egptr () - eback ()) setg (eback (), eback () + off, egptr ()); else if (off <= pptr () - egptr ()) // advance egptr() setg (eback (), eback () + off, pptr ()); else // advance egptr() even further setg (eback (), eback () + off, epptr ()); } else if (which & ios::out) { // position output sequence if (seeklo + off < pbase ()) { // adjust beginning of output sequence, then increment pptr() setp (seeklo, epptr ()); pbump (off); } else { // reset pptr() first, then increment it by offset setp (pbase (), epptr ()); pbump (off - (pbase () - seeklo)); } } else off = -1; // failure _RWSTD_ASSERT (_C_is_valid ()); return pos_type (off); }