in csharp/src/ZStdDecompress.cs [1709:1787]
static size_t ZSTD_decompressSequencesLong_body(
ZSTD_DCtx dctx,
void* dst, size_t maxDstSize,
void* seqStart, size_t seqSize, int nbSeq,
ZSTD_longOffset_e isLongOffset)
{
BYTE* ip = (BYTE*)seqStart;
BYTE* iend = ip + seqSize;
BYTE* ostart = (BYTE*)dst;
BYTE* oend = ostart + maxDstSize;
BYTE* op = ostart;
BYTE* litPtr = dctx.litPtr;
BYTE* litEnd = litPtr + dctx.litSize;
BYTE* prefixStart = (BYTE*)(dctx.baseField);
BYTE* dictStart = (BYTE*)(dctx.vBase);
BYTE* dictEnd = (BYTE*)(dctx.dictEnd);
/* Regen sequences */
if (nbSeq != 0)
{
const int STORED_SEQS = 4;
const int STOSEQ_MASK = (STORED_SEQS - 1);
const int ADVANCED_SEQS = 4;
seq_t[] sequences = new seq_t[STORED_SEQS];
int seqAdvance = Math.Min(nbSeq, ADVANCED_SEQS);
seqState_t seqState = new seqState_t();
int seqNb;
dctx.fseEntropy = 1;
{ U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx.entropy.rep[i]; }
seqState.prefixStart = prefixStart;
seqState.pos = (size_t)(op - prefixStart);
seqState.dictEnd = dictEnd;
{ size_t errcod = InitDStream(seqState.DStream, ip, (size_t)(iend - ip)); if (IsError(errcod)) return ERROR(Error.corruption_detected); }
InitFseState(ref seqState.stateLL, seqState.DStream, dctx.LLTptr);
InitFseState(ref seqState.stateOffb, seqState.DStream, dctx.OFTptr);
InitFseState(ref seqState.stateML, seqState.DStream, dctx.MLTptr);
/* prepare in advance */
for (seqNb = 0; (ReloadDStream(seqState.DStream) <= BIT_DStream_status.BIT_DStream_completed) && (seqNb < seqAdvance); seqNb++)
{
sequences[seqNb] = DecodeSequenceLong(seqState, isLongOffset);
}
if (seqNb < seqAdvance) return ERROR(Error.corruption_detected);
/* decode and decompress */
for (; (ReloadDStream(seqState.DStream) <= BIT_DStream_status.BIT_DStream_completed) && (seqNb < nbSeq); seqNb++)
{
seq_t sequence = DecodeSequenceLong(seqState, isLongOffset);
size_t oneSeqSize = ExecSequenceLong(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
if (IsError(oneSeqSize)) return oneSeqSize;
//PREFETCH(sequence.match); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
sequences[seqNb & STOSEQ_MASK] = sequence;
op += oneSeqSize;
}
if (seqNb < nbSeq) return ERROR(Error.corruption_detected);
/* finish queue */
seqNb -= seqAdvance;
for (; seqNb < nbSeq; seqNb++)
{
size_t oneSeqSize = ExecSequenceLong(op, oend, sequences[seqNb & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
if (IsError(oneSeqSize)) return oneSeqSize;
op += oneSeqSize;
}
/* save reps for next block */
{ U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) dctx.entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
}
/* last literal segment */
{
size_t lastLLSize = (size_t)(litEnd - litPtr);
if (lastLLSize > (size_t)(oend - op)) return ERROR(Error.dstSize_tooSmall);
memcpy(op, litPtr, lastLLSize);
op += lastLLSize;
}
return (size_t)(op - ostart);
}