Decompression can decode frame content size
This commit is contained in:
parent
0e491c01fe
commit
03ea59b17b
@ -94,13 +94,13 @@ typedef struct
|
|||||||
} blockProperties_t;
|
} blockProperties_t;
|
||||||
|
|
||||||
|
|
||||||
/* *******************************************************
|
/*_*******************************************************
|
||||||
* Memory operations
|
* Memory operations
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
|
static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
|
||||||
|
|
||||||
|
|
||||||
/* *************************************
|
/*-*************************************
|
||||||
* Error Management
|
* Error Management
|
||||||
***************************************/
|
***************************************/
|
||||||
unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; }
|
unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; }
|
||||||
@ -118,7 +118,7 @@ ZSTD_ErrorCode ZSTD_getError(size_t code) { return ERR_getError(code); }
|
|||||||
const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }
|
const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }
|
||||||
|
|
||||||
|
|
||||||
/* *************************************************************
|
/*-*************************************************************
|
||||||
* Context management
|
* Context management
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
||||||
@ -185,15 +185,15 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* *************************************************************
|
/*-*************************************************************
|
||||||
* Decompression section
|
* Decompression section
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
/* Frame format description
|
/* Frame format description
|
||||||
Frame Header - [ Block Header - Block ] - Frame End
|
Frame Header - [ Block Header - Block ] - Frame End
|
||||||
1) Frame Header
|
1) Frame Header
|
||||||
- 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_internal.h)
|
- 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h)
|
||||||
- 1 byte - Window Descriptor
|
- 1 byte - Frame Descriptor
|
||||||
2) Block Header
|
2) Block Header
|
||||||
- 3 bytes, starting with a 2-bits descriptor
|
- 3 bytes, starting with a 2-bits descriptor
|
||||||
Uncompressed, Compressed, Frame End, unused
|
Uncompressed, Compressed, Frame End, unused
|
||||||
@ -203,7 +203,18 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|||||||
- 3 bytes, compatible with Block Header
|
- 3 bytes, compatible with Block Header
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Block format description
|
|
||||||
|
/* Frame descriptor
|
||||||
|
|
||||||
|
1 byte, using :
|
||||||
|
bit 0-3 : windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN (see zstd_internal.h)
|
||||||
|
bit 4 : minmatch 4(0) or 3(1)
|
||||||
|
bit 5 : reserved (must be zero)
|
||||||
|
bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Compressed Block, format description
|
||||||
|
|
||||||
Block = Literal Section - Sequences Section
|
Block = Literal Section - Sequences Section
|
||||||
Prerequisite : size of (compressed) block, maximum size of regenerated data
|
Prerequisite : size of (compressed) block, maximum size of regenerated data
|
||||||
@ -269,46 +280,63 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|||||||
TO DO
|
TO DO
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static const size_t ZSTD_fcs_fieldSize[4] = { 0, 1, 2, 8 };
|
||||||
|
|
||||||
/** ZSTD_decodeFrameHeader_Part1() :
|
/** ZSTD_frameHeaderSize() :
|
||||||
* decode the 1st part of the Frame Header, which tells Frame Header size.
|
* srcSize must be >= ZSTD_frameHeaderSize_min.
|
||||||
* srcSize must be == ZSTD_frameHeaderSize_min.
|
* @return : size of the Frame Header */
|
||||||
* @return : the full size of the Frame Header */
|
static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
||||||
static size_t ZSTD_decodeFrameHeader_Part1(ZSTD_DCtx* zc, const void* src, size_t srcSize)
|
|
||||||
{
|
{
|
||||||
U32 magicNumber;
|
U32 fcsId;
|
||||||
if (srcSize != ZSTD_frameHeaderSize_min)
|
if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);
|
||||||
return ERROR(srcSize_wrong);
|
fcsId = (((const BYTE*)src)[4]) >> 6;
|
||||||
magicNumber = MEM_readLE32(src);
|
return ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
|
||||||
if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
|
|
||||||
zc->headerSize = ZSTD_frameHeaderSize_min;
|
|
||||||
return zc->headerSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** ZSTD_getFrameParams() :
|
||||||
|
* decode Frame Header, or provide expected `srcSize`.
|
||||||
|
* @return : 0, `fparamsPtr` is correctly filled,
|
||||||
|
* >0, not enough srcSize, provide expected `srcSize`,
|
||||||
|
* or an error code, which can be tested using ZSTD_isError() */
|
||||||
size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize)
|
size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
U32 magicNumber;
|
U32 magicNumber, fcsId;
|
||||||
if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_max;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
|
BYTE frameDesc;
|
||||||
|
|
||||||
|
if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_min;
|
||||||
magicNumber = MEM_readLE32(src);
|
magicNumber = MEM_readLE32(src);
|
||||||
if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
|
if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
|
||||||
|
|
||||||
|
{ size_t fhsize = ZSTD_frameHeaderSize(src, srcSize);
|
||||||
|
if (srcSize < fhsize) return fhsize; }
|
||||||
|
|
||||||
memset(fparamsPtr, 0, sizeof(*fparamsPtr));
|
memset(fparamsPtr, 0, sizeof(*fparamsPtr));
|
||||||
fparamsPtr->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
frameDesc = ip[4];
|
||||||
fparamsPtr->mml = (((const BYTE*)src)[4] & 16) ? MINMATCH-1 : MINMATCH;
|
fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
||||||
if ((((const BYTE*)src)[4] >> 5) != 0) return ERROR(frameParameter_unsupported); /* reserved 3 bits */
|
fparamsPtr->mml = (frameDesc & 0x10) ? MINMATCH-1 : MINMATCH;
|
||||||
|
if ((frameDesc & 0x20) != 0) return ERROR(frameParameter_unsupported); /* reserved 1 bit */
|
||||||
|
fcsId = frameDesc >> 6;
|
||||||
|
switch(fcsId)
|
||||||
|
{
|
||||||
|
default: /* impossible */
|
||||||
|
case 0 : fparamsPtr->frameContentSize = 0; break;
|
||||||
|
case 1 : fparamsPtr->frameContentSize = ip[5]; break;
|
||||||
|
case 2 : fparamsPtr->frameContentSize = MEM_readLE16(ip+5); break;
|
||||||
|
case 3 : fparamsPtr->frameContentSize = MEM_readLE64(ip+5); break;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ZSTD_decodeFrameHeader_Part2() :
|
|
||||||
* decode the full Frame Header.
|
/** ZSTD_decodeFrameHeader() :
|
||||||
|
* decode Frame Header.
|
||||||
* srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1().
|
* srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1().
|
||||||
* @return : 0, or an error code, which can be tested using ZSTD_isError() */
|
* @return : 0, or an error code, which can be tested using ZSTD_isError() */
|
||||||
static size_t ZSTD_decodeFrameHeader_Part2(ZSTD_DCtx* zc, const void* src, size_t srcSize)
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* zc, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
size_t result;
|
size_t result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
|
||||||
if (srcSize != zc->headerSize)
|
|
||||||
return ERROR(srcSize_wrong);
|
|
||||||
result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
|
|
||||||
if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
|
if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -901,7 +929,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
|
|
||||||
/* Frame Header */
|
/* Frame Header */
|
||||||
{
|
{
|
||||||
size_t frameHeaderSize;
|
size_t frameHeaderSize, errorCode;
|
||||||
if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
|
||||||
{
|
{
|
||||||
@ -910,12 +938,12 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber);
|
return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
frameHeaderSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min);
|
frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
|
||||||
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
||||||
if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||||
|
errorCode = ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize);
|
||||||
|
if (ZSTD_isError(errorCode)) return errorCode;
|
||||||
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
||||||
frameHeaderSize = ZSTD_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);
|
|
||||||
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop on each block */
|
/* Loop on each block */
|
||||||
@ -1024,7 +1052,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co
|
|||||||
{
|
{
|
||||||
/* get frame header size */
|
/* get frame header size */
|
||||||
if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
|
if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
|
||||||
dctx->headerSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min);
|
dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
|
||||||
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
||||||
memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
|
memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
|
||||||
if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
|
if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
|
||||||
@ -1039,7 +1067,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co
|
|||||||
/* get frame header */
|
/* get frame header */
|
||||||
size_t result;
|
size_t result;
|
||||||
memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
|
memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
|
||||||
result = ZSTD_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize);
|
result = ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);
|
||||||
if (ZSTD_isError(result)) return result;
|
if (ZSTD_isError(result)) return result;
|
||||||
dctx->expected = ZSTD_blockHeaderSize;
|
dctx->expected = ZSTD_blockHeaderSize;
|
||||||
dctx->stage = ZSTDds_decodeBlockHeader;
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
||||||
|
@ -165,7 +165,7 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci
|
|||||||
You can then reuse ZSTD_CCtx to compress some new frame.
|
You can then reuse ZSTD_CCtx to compress some new frame.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct { U64 frameSize; U32 windowLog; U32 mml; } ZSTD_frameParams;
|
typedef struct { U64 frameContentSize; U32 windowLog; U32 mml; } ZSTD_frameParams;
|
||||||
|
|
||||||
#define ZSTD_FRAMEHEADERSIZE_MAX 13 /* for static allocation */
|
#define ZSTD_FRAMEHEADERSIZE_MAX 13 /* for static allocation */
|
||||||
static const size_t ZSTD_frameHeaderSize_min = 5;
|
static const size_t ZSTD_frameHeaderSize_min = 5;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user