static size_t DecompressFrame()

in csharp/src/ZStdDecompress.cs [2008:2091]


		static size_t DecompressFrame(ZSTD_DCtx dctx,
										   void* dst, size_t dstCapacity,
									 void** srcPtr, size_t* srcSizePtr)
		{
			BYTE* ip = (BYTE*)(*srcPtr);
			BYTE* ostart = (BYTE*)dst;
			BYTE* oend = ostart + dstCapacity;
			BYTE* op = ostart;
			size_t remainingSize = *srcSizePtr;

			/* check */
			if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize)
				return ERROR(Error.srcSize_wrong);

			/* Frame Header */
			{
				size_t frameHeaderSize = FrameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
				if (IsError(frameHeaderSize)) return frameHeaderSize;
				if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize)
					return ERROR(Error.srcSize_wrong);
				{ size_t errcod = DecodeFrameHeader(dctx, ip, frameHeaderSize); if (IsError(errcod)) return errcod; }
				ip += frameHeaderSize; remainingSize -= frameHeaderSize;
			}

			/* Loop on each block */
			while (true)
			{
				size_t decodedSize;
				blockProperties_t blockProperties;
				size_t cBlockSize = GetcBlockSize(ip, remainingSize, &blockProperties);
				if (IsError(cBlockSize)) return cBlockSize;

				ip += ZSTD_blockHeaderSize;
				remainingSize -= ZSTD_blockHeaderSize;
				if (cBlockSize > remainingSize) return ERROR(Error.srcSize_wrong);

				switch (blockProperties.blockType)
				{
					case blockType_e.bt_compressed:
						decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend - op), ip, cBlockSize, /* frame */ 1);
						break;
					case blockType_e.bt_raw:
						decodedSize = CopyRawBlock(op, (size_t)(oend - op), ip, cBlockSize);
						break;
					case blockType_e.bt_rle:
						decodedSize = GenerateNxBytes(op, (size_t)(oend - op), *ip, blockProperties.origSize);
						break;
					case blockType_e.bt_reserved:
					default:
						return ERROR(Error.corruption_detected);
				}

				if (IsError(decodedSize)) return decodedSize;
				if (dctx.fParams.checksumFlag != 0)
					XXH64_update(dctx.xxhState, op, decodedSize);
				op += decodedSize;
				ip += cBlockSize;
				remainingSize -= cBlockSize;
				if (blockProperties.lastBlock != 0) break;
			}

			if (dctx.fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
			{
				if ((U64)(op - ostart) != dctx.fParams.frameContentSize)
				{
					return ERROR(Error.corruption_detected);
				}
			}
			if (dctx.fParams.checksumFlag != 0)
			{ /* Frame content checksum verification */
				U32 checkCalc = (U32)XXH64_digest(dctx.xxhState);
				U32 checkRead;
				if (remainingSize < 4) return ERROR(Error.checksum_wrong);
				checkRead = MEM_readLE32(ip);
				if (checkRead != checkCalc) return ERROR(Error.checksum_wrong);
				ip += 4;
				remainingSize -= 4;
			}

			/* Allow caller to get size read */
			*srcPtr = ip;
			*srcSizePtr = remainingSize;
			return (size_t)(op - ostart);
		}