static size_t ZSTD_decompressSequencesLong_body()

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);
		}