} blockProperties_t;
-/* *******************************************************
+/*_*******************************************************
* Memory operations
**********************************************************/
static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
-/* *************************************
+/*-*************************************
* Error Management
***************************************/
unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; }
const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }
-/* *************************************************************
+/*-*************************************************************
* Context management
***************************************************************/
typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
}
-/* *************************************************************
+/*-*************************************************************
* Decompression section
***************************************************************/
/* Frame format description
Frame Header - [ Block Header - Block ] - Frame End
1) Frame Header
- - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_internal.h)
- - 1 byte - Window Descriptor
+ - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h)
+ - 1 byte - Frame Descriptor
2) Block Header
- 3 bytes, starting with a 2-bits descriptor
Uncompressed, Compressed, Frame End, unused
- 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
Prerequisite : size of (compressed) block, maximum size of regenerated data
TO DO
*/
+static const size_t ZSTD_fcs_fieldSize[4] = { 0, 1, 2, 8 };
-/** ZSTD_decodeFrameHeader_Part1() :
-* decode the 1st part of the Frame Header, which tells Frame Header size.
-* srcSize must be == ZSTD_frameHeaderSize_min.
-* @return : the full size of the Frame Header */
-static size_t ZSTD_decodeFrameHeader_Part1(ZSTD_DCtx* zc, const void* src, size_t srcSize)
+/** ZSTD_frameHeaderSize() :
+* srcSize must be >= ZSTD_frameHeaderSize_min.
+* @return : size of the Frame Header */
+static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
{
- U32 magicNumber;
- if (srcSize != ZSTD_frameHeaderSize_min)
- return ERROR(srcSize_wrong);
- magicNumber = MEM_readLE32(src);
- if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
- zc->headerSize = ZSTD_frameHeaderSize_min;
- return zc->headerSize;
+ U32 fcsId;
+ if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);
+ fcsId = (((const BYTE*)src)[4]) >> 6;
+ return ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
}
+/** 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)
{
- U32 magicNumber;
- if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_max;
+ U32 magicNumber, fcsId;
+ const BYTE* ip = (const BYTE*)src;
+ BYTE frameDesc;
+
+ if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_min;
magicNumber = MEM_readLE32(src);
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));
- fparamsPtr->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
- fparamsPtr->mml = (((const BYTE*)src)[4] & 16) ? MINMATCH-1 : MINMATCH;
- if ((((const BYTE*)src)[4] >> 5) != 0) return ERROR(frameParameter_unsupported); /* reserved 3 bits */
+ frameDesc = ip[4];
+ fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
+ 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;
}
-/** ZSTD_decodeFrameHeader_Part2() :
-* decode the full Frame Header.
+
+/** ZSTD_decodeFrameHeader() :
+* decode Frame Header.
* srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1().
* @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;
- if (srcSize != zc->headerSize)
- return ERROR(srcSize_wrong);
- result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
+ size_t result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
return result;
}
/* Frame Header */
{
- size_t frameHeaderSize;
+ size_t frameHeaderSize, errorCode;
if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
{
return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber);
}
#endif
- frameHeaderSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min);
+ frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
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;
- frameHeaderSize = ZSTD_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);
- if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
}
/* Loop on each block */
{
/* get frame header size */
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;
memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
/* get frame header */
size_t result;
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;
dctx->expected = ZSTD_blockHeaderSize;
dctx->stage = ZSTDds_decodeBlockHeader;