static size_t ExecSequenceLong()

in csharp/src/ZStdDecompress.cs [1355:1441]


		static size_t ExecSequenceLong(BYTE* op,
									 BYTE* oend, seq_t sequence,
									 BYTE** litPtr, BYTE* litLimit,
									 BYTE* prefixStart, BYTE* dictStart, BYTE* dictEnd)
		{
			BYTE* oLitEnd = op + sequence.litLength;
			size_t sequenceLength = sequence.litLength + sequence.matchLength;
			BYTE* oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */
			BYTE* oend_w = oend - WILDCOPY_OVERLENGTH;
			BYTE* iLitEnd = *litPtr + sequence.litLength;
			BYTE* match = sequence.match;

			/* check */
			if (oMatchEnd > oend) return ERROR(Error.dstSize_tooSmall); /* last match must start at a minimum distance of  WILDCOPY_OVERLENGTH from oend */
			if (iLitEnd > litLimit) return ERROR(Error.corruption_detected);   /* over-read beyond lit buffer */
			if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);

			/* copy Literals */
			ZSTD_copy8(op, *litPtr);  /* note : op <= oLitEnd <= oend_w == oend - 8 */
			if (sequence.litLength > 8)
				Wildcopy(op + 8, (*litPtr) + 8, (int)(sequence.litLength - 8));   /* note : since oLitEnd <= oend- WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
			op = oLitEnd;
			*litPtr = iLitEnd;   /* update for next sequence */

			/* copy Match */
			if (sequence.offset > (size_t)(oLitEnd - prefixStart))
			{
				/* offset beyond prefix */
				if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(Error.corruption_detected);
				if (match + sequence.matchLength <= dictEnd)
				{
					memmove(oLitEnd, match, sequence.matchLength);
					return sequenceLength;
				}
				/* span extDict & currentPrefixSegment */
				{
					size_t length1 = (size_t)(dictEnd - match);
					memmove(oLitEnd, match, length1);
					op = oLitEnd + length1;
					sequence.matchLength -= length1;
					match = prefixStart;
					if (op > oend_w || sequence.matchLength < MINMATCH)
					{
						U32 i;
						for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
						return sequenceLength;
					}
				}
			}
			Debug.Assert(op <= oend_w);
			Debug.Assert(sequence.matchLength >= MINMATCH);

			/* match within prefix */
			if (sequence.offset < 8)
			{
				/* close range match, overlap */
				int sub2 = dec64table[sequence.offset];
				op[0] = match[0];
				op[1] = match[1];
				op[2] = match[2];
				op[3] = match[3];
				match += dec32table[sequence.offset];
				ZSTD_copy4(op + 4, match);
				match -= sub2;
			}
			else
			{
				ZSTD_copy8(op, match);
			}
			op += 8; match += 8;

			if (oMatchEnd > oend - (16 - MINMATCH))
			{
				if (op < oend_w)
				{
					Wildcopy(op, match, (int)(oend_w - op));
					match += oend_w - op;
					op = oend_w;
				}
				while (op < oMatchEnd) *op++ = *match++;
			}
			else
			{
				Wildcopy(op, match, (int)(sequence.matchLength - 8));   /* works even if matchLength < 8 */
			}
			return sequenceLength;
		}