Esempio n. 1
0
static void vport_print(ScmObj obj, ScmPort *port, ScmWriteContext *ctx)
{
    Scm_Printf(port, "#<%A%s %A %p>",
               Scm__InternalClassName(Scm_ClassOf(obj)),
               SCM_PORT_CLOSED_P(obj)? "(closed)" : "",
               Scm_PortName(SCM_PORT(obj)),
               obj);
}
Esempio n. 2
0
ScmObj Scm_PortSeekUnsafe(ScmPort *p, ScmObj off, int whence)
#endif
{
    VMDECL;
    SHORTCUT(p, return Scm_PortSeekUnsafe(p, off, whence));
    if (SCM_PORT_CLOSED_P(p)) {
        Scm_PortError(p, SCM_PORT_ERROR_CLOSED,
                      "attempt to seek on closed port: %S", p);
    }

    off_t r = (off_t)-1;
    off_t o = Scm_IntegerToOffset(off);
    int is_telling = (whence == SEEK_CUR && o == 0);

    LOCK(p);

    off_t pending = port_pending_bytes(p);
    if (!is_telling) {
        /* Unless we're telling, we discard pending bytes. */
        p->scrcnt = 0;
        p->ungotten = SCM_CHAR_INVALID;
        /* ... and adjust offset, when it's relative. */
        if (whence == SEEK_CUR) o -= pending;
    }

    switch (SCM_PORT_TYPE(p)) {
    case SCM_PORT_FILE:
        /* NB: we might be able to skip calling seeker if we keep the
           # of bytes read or write so far, but such count may be off
           when the port has been experienced an error condition. */
        /* NB: the following doesn't work if we have bidirectional port.
           In such case we need to keep whether the last call of buffer
           handling routine was input or output. */
        if (!p->src.buf.seeker) break;
        if (is_telling) {
            SAFE_CALL(p, r = p->src.buf.seeker(p, 0, SEEK_CUR));
            if (SCM_PORT_DIR(p)&SCM_PORT_INPUT) {
                r -= (off_t)(p->src.buf.end - p->src.buf.current);
            } else {
                r += (off_t)(p->src.buf.current - p->src.buf.buffer);
            }
        } else {
            /* NB: possible optimization: the specified position is within
               the current buffer, we can avoid calling seeker. */
            if (SCM_PORT_DIR(p)&SCM_PORT_INPUT) {
                char *c = p->src.buf.current; /* save current ptr */
                if (whence == SEEK_CUR) {
                    o -= (off_t)(p->src.buf.end - c);
                }
                p->src.buf.current = p->src.buf.end; /* invalidate buffer */
                SAFE_CALL(p, r = p->src.buf.seeker(p, o, whence));
                if (r == (off_t)-1) {
                    /* This may happend if seeker somehow gave up */
                    p->src.buf.current = c;
                }
            } else {
                SAFE_CALL(p, bufport_flush(p, 0, TRUE));
                SAFE_CALL(p, r = p->src.buf.seeker(p, o, whence));
            }
        }
        break;
    case SCM_PORT_ISTR:
        r = SEEK_ISTR(p, o, whence, is_telling);
        break;
    case SCM_PORT_OSTR:
        if (is_telling) {
            r = (off_t)Scm_DStringSize(&(p->src.ostr));
        } else {
            /* Not supported yet */
            r = (off_t)-1;
        }
        break;
    case SCM_PORT_PROC:
        if (p->src.vt.Seek) {
            SAFE_CALL(p, r = p->src.vt.Seek(p, o, whence));
        }
        break;
    }
    UNLOCK(p);
    if (r == (off_t)-1) return SCM_FALSE;

    if (is_telling) r -= pending;
    
    return Scm_OffsetToInteger(r);
}