void SplittableBzip2ReadBuffer::getAndMoveToFrontDecode()

in cpp-ch/local-engine/IO/SplittableBzip2ReadBuffer.cpp [623:790]


void SplittableBzip2ReadBuffer::getAndMoveToFrontDecode()
{
    origPtr = static_cast<Int32>(bsR(24));
    recvDecodingTables();

    ReadBuffer * inShadow = in.get();
    Data * dataShadow = data.get();
    auto & ll8 = dataShadow->ll8;
    Int32 * unzftab = dataShadow->unzftab;
    char * selector = dataShadow->selector;
    auto * seqToUnseq = dataShadow->seqToUnseq;
    auto * yy = dataShadow->getAndMoveToFrontDecode_yy;
    Int32 * minLens = dataShadow->minLens;
    auto * limit = dataShadow->limit;
    auto * base = dataShadow->base;
    auto * perm = dataShadow->perm;
    Int32 limitLast = blockSize100k * 100000;

    for (Int32 i = 256; --i >= 0;)
    {
        yy[i] = i;
        unzftab[i] = 0;
    }

    Int32 groupNo = 0;
    Int32 groupPos = BZip2Constants::G_SIZE - 1;
    Int32 eob = nInUse + 1;
    Int32 nextSym = getAndMoveToFrontDecode0(0);
    Int32 bsBuffShadow = static_cast<Int32>(bsBuff);
    Int32 bsLiveShadow = static_cast<Int32>(bsLive);
    Int32 lastShadow = -1;
    Int32 zt = selector[groupNo] & 0xff;
    Int32 * base_zt = base[zt];
    Int32 * limit_zt = limit[zt];
    Int32 * perm_zt = perm[zt];
    Int32 minLens_zt = minLens[zt];

    while (nextSym != eob)
    {
        if ((nextSym == BZip2Constants::RUNA) || (nextSym == BZip2Constants::RUNB))
        {
            Int32 s = -1;
            for (Int32 n = 1; true; n <<= 1)
            {
                if (nextSym == BZip2Constants::RUNA)
                    s += n;
                else if (nextSym == BZip2Constants::RUNB)
                    s += n << 1;
                else
                    break;

                if (groupPos == 0)
                {
                    groupPos = BZip2Constants::G_SIZE - 1;
                    zt = selector[++groupNo] & 0xff;
                    base_zt = base[zt];
                    limit_zt = limit[zt];
                    perm_zt = perm[zt];
                    minLens_zt = minLens[zt];
                }
                else
                {
                    groupPos--;
                }

                Int32 zn = minLens_zt;
                while (bsLiveShadow < zn)
                {
                    Int32 thech = readAByte(*inShadow);
                    if (thech < 0)
                        DB::throwReadAfterEOF();

                    bsBuffShadow = (bsBuffShadow << 8) | thech;
                    bsLiveShadow += 8;
                }

                Int64 zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1);
                bsLiveShadow -= zn;
                while (zvec > limit_zt[zn])
                {
                    zn++;
                    while (bsLiveShadow < 1)
                    {
                        Int32 thech = readAByte(*inShadow);
                        if (thech < 0)
                            DB::throwReadAfterEOF();

                        bsBuffShadow = (bsBuffShadow << 8) | thech;
                        bsLiveShadow += 8;
                    }
                    bsLiveShadow--;
                    zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1);
                }
                nextSym = perm_zt[static_cast<Int32>(zvec - base_zt[zn])];
            }

            char ch = seqToUnseq[yy[0]];
            unzftab[ch & 0xff] += s + 1;
            while (s-- >= 0)
                ll8[++lastShadow] = ch;
            if (lastShadow >= limitLast)
                throw Exception(ErrorCodes::LOGICAL_ERROR, "Block overrun");
        }
        else
        {
            if (++lastShadow >= limitLast)
                throw Exception(ErrorCodes::LOGICAL_ERROR, "Block overrun");
            auto tmp = yy[nextSym - 1];
            unzftab[seqToUnseq[tmp] & 0xff]++;
            ll8[lastShadow] = seqToUnseq[tmp];

            if (nextSym <= 16)
                for (Int32 j = nextSym - 1; j > 0; --j)
                    yy[j] = yy[j - 1];
            else
                memmove(&yy[1], &yy[0], (nextSym - 1) * sizeof(yy[0]));
            yy[0] = tmp;

            if (groupPos == 0)
            {
                groupPos = BZip2Constants::G_SIZE - 1;
                zt = selector[++groupNo] & 0xff;
                base_zt = base[zt];
                limit_zt = limit[zt];
                perm_zt = perm[zt];
                minLens_zt = minLens[zt];
            }
            else
            {
                groupPos--;
            }

            Int32 zn = minLens_zt;
            while (bsLiveShadow < zn)
            {
                Int32 thech = readAByte(*inShadow);
                if (thech < 0)
                    DB::throwReadAfterEOF();

                bsBuffShadow = (bsBuffShadow << 8) | thech;
                bsLiveShadow += 8;
            }

            Int32 zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1);
            bsLiveShadow -= zn;
            while (zvec > limit_zt[zn])
            {
                zn++;
                while (bsLiveShadow < 1)
                {
                    Int32 thech = readAByte(*inShadow);
                    if (thech < 0)
                        DB::throwReadAfterEOF();

                    bsBuffShadow = (bsBuffShadow << 8) | thech;
                    bsLiveShadow += 8;
                }
                bsLiveShadow--;
                zvec = ((zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1));
            }
            nextSym = perm_zt[zvec - base_zt[zn]];
        }
    }

    last = lastShadow;
    bsLive = bsLiveShadow;
    bsBuff = bsBuffShadow;
}