Compress-Zstd
view release on metacpan or search on metacpan
ext/zstd/contrib/linux-kernel/lib/zstd/decompress.c view on Meta::CPAN
ip += headerSize;
remainingSize -= headerSize;
/* Loop on each block */
while (1) {
blockProperties_t blockProperties;
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTD_isError(cBlockSize))
return cBlockSize;
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
return ERROR(srcSize_wrong);
ip += ZSTD_blockHeaderSize + cBlockSize;
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
if (blockProperties.lastBlock)
break;
}
if (fParams.checksumFlag) { /* Frame content checksum */
if (remainingSize < 4)
return ERROR(srcSize_wrong);
ip += 4;
remainingSize -= 4;
}
return ip - ipstart;
}
}
/*! ZSTD_decompressFrame() :
* @dctx must be properly initialized */
static size_t ZSTD_decompressFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void **srcPtr, size_t *srcSizePtr)
{
const BYTE *ip = (const BYTE *)(*srcPtr);
BYTE *const ostart = (BYTE * const)dst;
BYTE *const oend = ostart + dstCapacity;
BYTE *op = ostart;
size_t remainingSize = *srcSizePtr;
/* check */
if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize)
return ERROR(srcSize_wrong);
/* Frame Header */
{
size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
if (ZSTD_isError(frameHeaderSize))
return frameHeaderSize;
if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize)
return ERROR(srcSize_wrong);
CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
ip += frameHeaderSize;
remainingSize -= frameHeaderSize;
}
/* Loop on each block */
while (1) {
size_t decodedSize;
blockProperties_t blockProperties;
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
if (ZSTD_isError(cBlockSize))
return cBlockSize;
ip += ZSTD_blockHeaderSize;
remainingSize -= ZSTD_blockHeaderSize;
if (cBlockSize > remainingSize)
return ERROR(srcSize_wrong);
switch (blockProperties.blockType) {
case bt_compressed: decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend - op, ip, cBlockSize); break;
case bt_raw: decodedSize = ZSTD_copyRawBlock(op, oend - op, ip, cBlockSize); break;
case bt_rle: decodedSize = ZSTD_generateNxBytes(op, oend - op, *ip, blockProperties.origSize); break;
case bt_reserved:
default: return ERROR(corruption_detected);
}
if (ZSTD_isError(decodedSize))
return decodedSize;
if (dctx->fParams.checksumFlag)
xxh64_update(&dctx->xxhState, op, decodedSize);
op += decodedSize;
ip += cBlockSize;
remainingSize -= cBlockSize;
if (blockProperties.lastBlock)
break;
}
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState);
U32 checkRead;
if (remainingSize < 4)
return ERROR(checksum_wrong);
checkRead = ZSTD_readLE32(ip);
if (checkRead != checkCalc)
return ERROR(checksum_wrong);
ip += 4;
remainingSize -= 4;
}
/* Allow caller to get size read */
*srcPtr = ip;
*srcSizePtr = remainingSize;
return op - ostart;
}
static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict);
static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict);
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize,
const ZSTD_DDict *ddict)
{
void *const dststart = dst;
if (ddict) {
if (dict) {
/* programmer error, these two cases should be mutually exclusive */
return ERROR(GENERIC);
}
dict = ZSTD_DDictDictContent(ddict);
dictSize = ZSTD_DDictDictSize(ddict);
}
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
U32 magicNumber;
magicNumber = ZSTD_readLE32(src);
if (magicNumber != ZSTD_MAGICNUMBER) {
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
size_t skippableSize;
if (srcSize < ZSTD_skippableHeaderSize)
return ERROR(srcSize_wrong);
skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize;
if (srcSize < skippableSize) {
return ERROR(srcSize_wrong);
}
src = (const BYTE *)src + skippableSize;
srcSize -= skippableSize;
continue;
} else {
ext/zstd/contrib/linux-kernel/lib/zstd/decompress.c view on Meta::CPAN
{
size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict);
if (ZSTD_isError(errorCode)) {
ZSTD_freeDDict(ddict);
return NULL;
}
}
return ddict;
}
}
/*! ZSTD_initDDict() :
* Create a digested dictionary, to start decompression without startup delay.
* `dict` content is copied inside DDict.
* Consequently, `dict` can be released after `ZSTD_DDict` creation */
ZSTD_DDict *ZSTD_initDDict(const void *dict, size_t dictSize, void *workspace, size_t workspaceSize)
{
ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
return ZSTD_createDDict_advanced(dict, dictSize, 1, stackMem);
}
size_t ZSTD_freeDDict(ZSTD_DDict *ddict)
{
if (ddict == NULL)
return 0; /* support free on NULL */
{
ZSTD_customMem const cMem = ddict->cMem;
ZSTD_free(ddict->dictBuffer, cMem);
ZSTD_free(ddict, cMem);
return 0;
}
}
/*! ZSTD_getDictID_fromDict() :
* Provides the dictID stored within dictionary.
* if @return == 0, the dictionary is not conformant with Zstandard specification.
* It can still be loaded, but as a content-only dictionary. */
unsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize)
{
if (dictSize < 8)
return 0;
if (ZSTD_readLE32(dict) != ZSTD_DICT_MAGIC)
return 0;
return ZSTD_readLE32((const char *)dict + 4);
}
/*! ZSTD_getDictID_fromDDict() :
* Provides the dictID of the dictionary loaded into `ddict`.
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict)
{
if (ddict == NULL)
return 0;
return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
}
/*! ZSTD_getDictID_fromFrame() :
* Provides the dictID required to decompressed the frame stored within `src`.
* If @return == 0, the dictID could not be decoded.
* This could for one of the following reasons :
* - The frame does not require a dictionary to be decoded (most common case).
* - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
* Note : this use case also happens when using a non-conformant dictionary.
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
* - This is not a Zstandard frame.
* When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
unsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize)
{
ZSTD_frameParams zfp = {0, 0, 0, 0};
size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize);
if (ZSTD_isError(hError))
return 0;
return zfp.dictID;
}
/*! ZSTD_decompress_usingDDict() :
* Decompression using a pre-digested Dictionary
* Use dictionary without significant overhead. */
size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const ZSTD_DDict *ddict)
{
/* pass content and size in case legacy frames are encountered */
return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, NULL, 0, ddict);
}
/*=====================================
* Streaming decompression
*====================================*/
typedef enum { zdss_init, zdss_loadHeader, zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
/* *** Resource management *** */
struct ZSTD_DStream_s {
ZSTD_DCtx *dctx;
ZSTD_DDict *ddictLocal;
const ZSTD_DDict *ddict;
ZSTD_frameParams fParams;
ZSTD_dStreamStage stage;
char *inBuff;
size_t inBuffSize;
size_t inPos;
size_t maxWindowSize;
char *outBuff;
size_t outBuffSize;
size_t outStart;
size_t outEnd;
size_t blockSize;
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
size_t lhSize;
ZSTD_customMem customMem;
void *legacyContext;
U32 previousLegacyVersion;
U32 legacyVersion;
U32 hostageByte;
}; /* typedef'd to ZSTD_DStream within "zstd.h" */
size_t ZSTD_DStreamWorkspaceBound(size_t maxWindowSize)
{
size_t const blockSize = MIN(maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
size_t const inBuffSize = blockSize;
size_t const outBuffSize = maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
return ZSTD_DCtxWorkspaceBound() + ZSTD_ALIGN(sizeof(ZSTD_DStream)) + ZSTD_ALIGN(inBuffSize) + ZSTD_ALIGN(outBuffSize);
}
static ZSTD_DStream *ZSTD_createDStream_advanced(ZSTD_customMem customMem)
ext/zstd/contrib/linux-kernel/lib/zstd/decompress.c view on Meta::CPAN
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);
}
if (zds->outBuffSize < neededOutSize) {
return ERROR(GENERIC);
}
zds->blockSize = blockSize;
}
zds->stage = zdss_read;
}
/* pass-through */
case zdss_read: {
size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
if (neededInSize == 0) { /* end of frame */
zds->stage = zdss_init;
someMoreWork = 0;
break;
}
if ((size_t)(iend - ip) >= neededInSize) { /* decode directly from src */
const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart,
(isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), ip, neededInSize);
if (ZSTD_isError(decodedSize))
return decodedSize;
ip += neededInSize;
if (!decodedSize && !isSkipFrame)
break; /* this was just a header */
zds->outEnd = zds->outStart + decodedSize;
zds->stage = zdss_flush;
break;
}
if (ip == iend) {
someMoreWork = 0;
break;
} /* no more input */
zds->stage = zdss_load;
/* pass-through */
}
case zdss_load: {
size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */
size_t loadedSize;
if (toLoad > zds->inBuffSize - zds->inPos)
return ERROR(corruption_detected); /* should never happen */
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend - ip);
ip += loadedSize;
zds->inPos += loadedSize;
if (loadedSize < toLoad) {
someMoreWork = 0;
break;
} /* not enough input, wait for more */
/* decode loaded input */
{
const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
zds->inBuff, neededInSize);
if (ZSTD_isError(decodedSize))
return decodedSize;
zds->inPos = 0; /* input is consumed */
if (!decodedSize && !isSkipFrame) {
zds->stage = zdss_read;
break;
} /* this was just a header */
zds->outEnd = zds->outStart + decodedSize;
zds->stage = zdss_flush;
/* pass-through */
}
}
case zdss_flush: {
size_t const toFlushSize = zds->outEnd - zds->outStart;
size_t const flushedSize = ZSTD_limitCopy(op, oend - op, zds->outBuff + zds->outStart, toFlushSize);
op += flushedSize;
zds->outStart += flushedSize;
if (flushedSize == toFlushSize) { /* flush completed */
zds->stage = zdss_read;
if (zds->outStart + zds->blockSize > zds->outBuffSize)
zds->outStart = zds->outEnd = 0;
break;
}
/* cannot complete flush */
someMoreWork = 0;
break;
}
default:
return ERROR(GENERIC); /* impossible */
}
}
/* result */
input->pos += (size_t)(ip - istart);
output->pos += (size_t)(op - ostart);
{
size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx);
if (!nextSrcSizeHint) { /* frame fully decoded */
if (zds->outEnd == zds->outStart) { /* output fully flushed */
if (zds->hostageByte) {
if (input->pos >= input->size) {
zds->stage = zdss_read;
return 1;
} /* can't release hostage (not present) */
input->pos++; /* release hostage */
}
return 0;
}
if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
zds->hostageByte = 1;
}
return 1;
}
nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */
if (zds->inPos > nextSrcSizeHint)
return ERROR(GENERIC); /* should never happen */
nextSrcSizeHint -= zds->inPos; /* already loaded*/
return nextSrcSizeHint;
}
}
EXPORT_SYMBOL(ZSTD_DCtxWorkspaceBound);
EXPORT_SYMBOL(ZSTD_initDCtx);
EXPORT_SYMBOL(ZSTD_decompressDCtx);
EXPORT_SYMBOL(ZSTD_decompress_usingDict);
EXPORT_SYMBOL(ZSTD_DDictWorkspaceBound);
EXPORT_SYMBOL(ZSTD_initDDict);
EXPORT_SYMBOL(ZSTD_decompress_usingDDict);
EXPORT_SYMBOL(ZSTD_DStreamWorkspaceBound);
EXPORT_SYMBOL(ZSTD_initDStream);
EXPORT_SYMBOL(ZSTD_initDStream_usingDDict);
EXPORT_SYMBOL(ZSTD_resetDStream);
EXPORT_SYMBOL(ZSTD_decompressStream);
EXPORT_SYMBOL(ZSTD_DStreamInSize);
EXPORT_SYMBOL(ZSTD_DStreamOutSize);
EXPORT_SYMBOL(ZSTD_findFrameCompressedSize);
EXPORT_SYMBOL(ZSTD_getFrameContentSize);
EXPORT_SYMBOL(ZSTD_findDecompressedSize);
EXPORT_SYMBOL(ZSTD_isFrame);
EXPORT_SYMBOL(ZSTD_getDictID_fromDict);
EXPORT_SYMBOL(ZSTD_getDictID_fromDDict);
EXPORT_SYMBOL(ZSTD_getDictID_fromFrame);
EXPORT_SYMBOL(ZSTD_getFrameParams);
EXPORT_SYMBOL(ZSTD_decompressBegin);
EXPORT_SYMBOL(ZSTD_decompressBegin_usingDict);
EXPORT_SYMBOL(ZSTD_copyDCtx);
EXPORT_SYMBOL(ZSTD_nextSrcSizeToDecompress);
EXPORT_SYMBOL(ZSTD_decompressContinue);
EXPORT_SYMBOL(ZSTD_nextInputType);
EXPORT_SYMBOL(ZSTD_decompressBlock);
EXPORT_SYMBOL(ZSTD_insertBlock);
( run in 0.810 second using v1.01-cache-2.11-cpan-39bf76dae61 )