FORCE_INLINE size_t FSEv05_decompress_usingDTable_generic()

in lib/legacy/zstd_v05.c [1424:1489]


FORCE_INLINE size_t FSEv05_decompress_usingDTable_generic(
          void* dst, size_t maxDstSize,
    const void* cSrc, size_t cSrcSize,
    const FSEv05_DTable* dt, const unsigned fast)
{
    BYTE* const ostart = (BYTE*) dst;
    BYTE* op = ostart;
    BYTE* const omax = op + maxDstSize;
    BYTE* const olimit = omax-3;

    BITv05_DStream_t bitD;
    FSEv05_DState_t state1;
    FSEv05_DState_t state2;
    size_t errorCode;

    /* Init */
    errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */
    if (FSEv05_isError(errorCode)) return errorCode;

    FSEv05_initDState(&state1, &bitD, dt);
    FSEv05_initDState(&state2, &bitD, dt);

#define FSEv05_GETSYMBOL(statePtr) fast ? FSEv05_decodeSymbolFast(statePtr, &bitD) : FSEv05_decodeSymbol(statePtr, &bitD)

    /* 4 symbols per loop */
    for ( ; (BITv05_reloadDStream(&bitD)==BITv05_DStream_unfinished) && (op<olimit) ; op+=4) {
        op[0] = FSEv05_GETSYMBOL(&state1);

        if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
            BITv05_reloadDStream(&bitD);

        op[1] = FSEv05_GETSYMBOL(&state2);

        if (FSEv05_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
            { if (BITv05_reloadDStream(&bitD) > BITv05_DStream_unfinished) { op+=2; break; } }

        op[2] = FSEv05_GETSYMBOL(&state1);

        if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
            BITv05_reloadDStream(&bitD);

        op[3] = FSEv05_GETSYMBOL(&state2);
    }

    /* tail */
    /* note : BITv05_reloadDStream(&bitD) >= FSEv05_DStream_partiallyFilled; Ends at exactly BITv05_DStream_completed */
    while (1) {
        if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state1))) )
            break;

        *op++ = FSEv05_GETSYMBOL(&state1);

        if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state2))) )
            break;

        *op++ = FSEv05_GETSYMBOL(&state2);
    }

    /* end ? */
    if (BITv05_endOfDStream(&bitD) && FSEv05_endOfDState(&state1) && FSEv05_endOfDState(&state2))
        return op-ostart;

    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */

    return ERROR(corruption_detected);
}