Пример #1
0
/* 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);
}
Пример #2
0
/* 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;
    }
}
Пример #3
0
/* 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 ();
}
Пример #4
0
/* 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));
}
Пример #5
0
/* 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);
    }
Пример #6
0
/* 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);
}