Compress-Zstd

 view release on metacpan or  search on metacpan

ext/zstd/contrib/linux-kernel/lib/zstd/decompress.c  view on Meta::CPAN

		zds->ddict = ddict;
	}
	return zds;
}

size_t ZSTD_freeDStream(ZSTD_DStream *zds)
{
	if (zds == NULL)
		return 0; /* support free on null */
	{
		ZSTD_customMem const cMem = zds->customMem;
		ZSTD_freeDCtx(zds->dctx);
		zds->dctx = NULL;
		ZSTD_freeDDict(zds->ddictLocal);
		zds->ddictLocal = NULL;
		ZSTD_free(zds->inBuff, cMem);
		zds->inBuff = NULL;
		ZSTD_free(zds->outBuff, cMem);
		zds->outBuff = NULL;
		ZSTD_free(zds, cMem);
		return 0;
	}
}

/* *** Initialization *** */

size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; }
size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }

size_t ZSTD_resetDStream(ZSTD_DStream *zds)
{
	zds->stage = zdss_loadHeader;
	zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
	zds->legacyVersion = 0;
	zds->hostageByte = 0;
	return ZSTD_frameHeaderSize_prefix;
}

/* *****   Decompression   ***** */

ZSTD_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
{
	size_t const length = MIN(dstCapacity, srcSize);
	memcpy(dst, src, length);
	return length;
}

size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
{
	const char *const istart = (const char *)(input->src) + input->pos;
	const char *const iend = (const char *)(input->src) + input->size;
	const char *ip = istart;
	char *const ostart = (char *)(output->dst) + output->pos;
	char *const oend = (char *)(output->dst) + output->size;
	char *op = ostart;
	U32 someMoreWork = 1;

	while (someMoreWork) {
		switch (zds->stage) {
		case zdss_init:
			ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
						/* fall-through */

		case zdss_loadHeader: {
			size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize);
			if (ZSTD_isError(hSize))
				return hSize;
			if (hSize != 0) {				   /* need more input */
				size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
				if (toLoad > (size_t)(iend - ip)) {	/* not enough input to load full header */
					memcpy(zds->headerBuffer + zds->lhSize, ip, iend - ip);
					zds->lhSize += iend - ip;
					input->pos = input->size;
					return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) +
					       ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
				}
				memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad);
				zds->lhSize = hSize;
				ip += toLoad;
				break;
			}

			/* check for single-pass mode opportunity */
			if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
			    && (U64)(size_t)(oend - op) >= zds->fParams.frameContentSize) {
				size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend - istart);
				if (cSize <= (size_t)(iend - istart)) {
					size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend - op, istart, cSize, zds->ddict);
					if (ZSTD_isError(decompressedSize))
						return decompressedSize;
					ip = istart + cSize;
					op += decompressedSize;
					zds->dctx->expected = 0;
					zds->stage = zdss_init;
					someMoreWork = 0;
					break;
				}
			}

			/* Consume header */
			ZSTD_refDDict(zds->dctx, zds->ddict);
			{
				size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
				CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
				{
					size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
					CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer + h1Size, h2Size));
				}
			}

			zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
			if (zds->fParams.windowSize > zds->maxWindowSize)
				return ERROR(frameParameter_windowTooLarge);

			/* Buffers are preallocated, but double check */
			{
				size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
				size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
				if (zds->inBuffSize < blockSize) {
					return ERROR(GENERIC);
				}



( run in 1.317 second using v1.01-cache-2.11-cpan-39bf76dae61 )