Logo Search packages:      
Sourcecode: virtualbox-ose version File versions

static int krdrBufRead ( PKRDR  pRdr,
void *  pvBuf,
KSIZE  cb,
KFOFF  off 
) [static]

Definition at line 264 of file kRdrBuffered.cpp.

References KRDRBUF::cbBuf, KRDRBUF::cbBufValid, KRDRBUF::cbFile, KRDRBUF::fTainedByLineQ, K_MIN, KERR_OUT_OF_RANGE, krdrBufFillBuffer(), KSIZE, KRDRBUF::offBuf, KRDRBUF::offBufEnd, KRDRBUF::offFile, KRDRBUF::pbBuf, KRDROPS::pfnRead, KRDR::pOps, and KRDRBUF::pRdr.

{
    PKRDRBUF pThis = (PKRDRBUF)pRdr;

    /*
     * We need to validate and update the file offset before
     * we start making partial reads from the buffer and stuff.
     */
    KFOFF offEnd = off + cb;
    if (    off >= pThis->cbFile
        ||  offEnd > pThis->cbFile
        ||  offEnd < off)
        return KERR_OUT_OF_RANGE; /* includes EOF. */
    pThis->offFile = offEnd;
    if (!cb)
        return 0;

    /*
     * Scratch the buffer if kRdrBufLineQ has tained it.
     */
    if (pThis->fTainedByLineQ)
    {
        pThis->offBuf = pThis->offBufEnd = 0;
        pThis->cbBufValid = 0;
    }

    /*
     * Is any part of the request in the buffer?
     *
     * We will currently ignore buffer hits in the middle of the
     * request because it's annoying to implement and it's
     * questionable whether it'll benefit much performance wise.
     */
    if (pThis->cbBufValid > 0)
    {
        if (off >= pThis->offBuf)
        {
            if (off < pThis->offBufEnd)
            {
                /* head (or all) of the request is in the buffer. */
                KSIZE cbMaxChunk = (KSIZE)(pThis->offBufEnd - off);
                KSIZE cbChunk = K_MIN(cb, cbMaxChunk);
                kHlpMemCopy(pvBuf, &pThis->pbBuf[off - pThis->offBuf], cbChunk);
                if (cbChunk == cb)
                    return 0;

                cb -= cbChunk;
                pvBuf = (KU8 *)pvBuf + cbChunk;
                off += cbChunk;
            }
        }
        else if (   offEnd > pThis->offBuf
                 && offEnd <= pThis->offBufEnd)
        {
            /* the end of the request is in the buffer. */
            KSIZE cbChunk = (KSIZE)(pThis->offBufEnd - (offEnd));
            kHlpMemCopy((KU8 *)pvBuf + (pThis->offBuf - off), pThis->pbBuf, cbChunk);
            kRdrAssert(cbChunk < cb);
            cb -= cbChunk;
            offEnd -= cbChunk;
        }
    }

    /*
     * If the buffer is larger than the read request, read a full buffer
     * starting at the requested offset. Otherwise perform an unbuffered
     * read.
     */
    if (pThis->cbBuf > cb)
    {
        int rc = krdrBufFillBuffer(pThis, off);
        if (rc)
            return rc;
        if (pThis->offBuf == off)
            kHlpMemCopy(pvBuf, pThis->pbBuf, cb);
        else
        {
            kRdrAssert(off > pThis->offBuf);
            kRdrAssert(off + cb <= pThis->offBufEnd);
            kHlpMemCopy(pvBuf, pThis->pbBuf + (off - pThis->offBuf), cb);
        }
    }
    else
    {
        int rc = pThis->pRdr->pOps->pfnRead(pThis->pRdr, pvBuf, cb, off);
        if (rc)
            return rc;
    }
    return 0;
}


Generated by  Doxygen 1.6.0   Back to index