From 0be6fd342984d375965255bff77f8936bcd85f8a Mon Sep 17 00:00:00 2001
From: Yann Collet Gives the amount of memory allocated for a ZSTD_CCtx given a set of compression parameters.
`frameContentSize` is an optional parameter, provide `0` if unknown
+typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are effectively same object */
+
ZSTD_CStream management functions
ZSTD_CStream* ZSTD_createCStream(void);
size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index c08b315d..d7f90dff 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -79,6 +79,8 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
/*-*************************************
* Context memory management
***************************************/
+typedef enum { zcss_init, zcss_load, zcss_flush, zcss_final } ZSTD_cStreamStage;
+
struct ZSTD_CCtx_s {
const BYTE* nextSrc; /* next block here to continue on current prefix */
const BYTE* base; /* All regular indexes relative to this position */
@@ -115,6 +117,22 @@ struct ZSTD_CCtx_s {
FSE_CTable* matchlengthCTable;
FSE_CTable* litlengthCTable;
unsigned* entropyScratchSpace;
+
+ /* streaming */
+ ZSTD_CDict* cdictLocal;
+ const ZSTD_CDict* cdict;
+ char* inBuff;
+ size_t inBuffSize;
+ size_t inToCompress;
+ size_t inBuffPos;
+ size_t inBuffTarget;
+ char* outBuff;
+ size_t outBuffSize;
+ size_t outBuffContentSize;
+ size_t outBuffFlushedSize;
+ ZSTD_cStreamStage streamStage;
+ U32 frameEnded;
+ U64 pledgedSrcSize;
};
ZSTD_CCtx* ZSTD_createCCtx(void)
@@ -253,8 +271,8 @@ static U32 ZSTD_equivalentParams(ZSTD_parameters param1, ZSTD_parameters param2)
{
return (param1.cParams.hashLog == param2.cParams.hashLog)
& (param1.cParams.chainLog == param2.cParams.chainLog)
- & (param1.cParams.strategy == param2.cParams.strategy)
- & ((param1.cParams.searchLength==3) == (param2.cParams.searchLength==3));
+ & (param1.cParams.strategy == param2.cParams.strategy) /* opt parser space */
+ & ((param1.cParams.searchLength==3) == (param2.cParams.searchLength==3)); /* hashlog3 space */
}
/*! ZSTD_continueCCtx() :
@@ -285,8 +303,11 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
ZSTD_parameters params, U64 frameContentSize,
ZSTD_compResetPolicy_e const crp)
{
+ DEBUGLOG(5, "ZSTD_resetCCtx_internal \n");
+
if (crp == ZSTDcrp_continue)
if (ZSTD_equivalentParams(params, zc->params)) {
+ DEBUGLOG(5, "ZSTD_equivalentParams()==1 \n");
zc->fseCTables_ready = 0;
zc->hufCTable_repeatMode = HUF_repeat_none;
return ZSTD_continueCCtx(zc, params, frameContentSize);
@@ -312,6 +333,8 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
size_t const optSpace = ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) ? optPotentialSpace : 0;
size_t const neededSpace = entropySpace + optSpace + tableSpace + tokenSpace;
if (zc->workSpaceSize < neededSpace) {
+ DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
+ (unsigned)zc->workSpaceSize>>10, (unsigned)neededSpace>>10);
zc->workSpaceSize = 0;
ZSTD_free(zc->workSpace, zc->customMem);
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
@@ -335,6 +358,7 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
/* init params */
zc->params = params;
zc->blockSize = blockSize;
+ DEBUGLOG(5, "blockSize = %uK \n", (U32)blockSize>>10);
zc->frameContentSize = frameContentSize;
zc->consumedSrcSize = 0;
@@ -364,6 +388,7 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
/* opt parser space */
if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) {
+ DEBUGLOG(5, "reserving optimal parser space ");
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
zc->seqStore.litFreq = (U32*)ptr;
zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<Advanced compression functions
-size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams);
+
size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming);
@@ -382,7 +382,7 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); -Gives the amount of memory used by a given ZSTD_CCtx +
amount of used memory is variable, depending primarily on compression level
typedef enum { @@ -507,7 +507,7 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; vAdvanced streaming functions
Advanced Streaming compression functions
ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); -size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);/**< size of CStream is variable, depending primarily on compression level */ +size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); /**< same as ZSTD_sizeof_CCtx */ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d55ea505..1248032b 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -244,7 +244,7 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u } -size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams) +size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming) { size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog); U32 const divider = (cParams.searchLength==3) ? 3 : 4; @@ -260,12 +260,17 @@ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams) + entropyScratchSpace_size; size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); - size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog); /* allocate buffers */ - { size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog; + { size_t const neededInBuffSize = ((size_t)1 << params.cParams.windowLog) + zcs->blockSize; if (zcs->inBuffSize < neededInBuffSize) { zcs->inBuffSize = 0; ZSTD_free(zcs->inBuff, zcs->customMem); - zcs->inBuff = (char*) ZSTD_malloc(neededInBuffSize, zcs->customMem); + zcs->inBuff = (char*)ZSTD_malloc(neededInBuffSize, zcs->customMem); if (zcs->inBuff == NULL) return ERROR(memory_allocation); zcs->inBuffSize = neededInBuffSize; } - zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, neededInBuffSize); } if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize)+1) { size_t const outBuffSize = ZSTD_compressBound(zcs->blockSize)+1; zcs->outBuffSize = 0; ZSTD_free(zcs->outBuff, zcs->customMem); - zcs->outBuff = (char*) ZSTD_malloc(outBuffSize, zcs->customMem); + zcs->outBuff = (char*)ZSTD_malloc(outBuffSize, zcs->customMem); if (zcs->outBuff == NULL) return ERROR(memory_allocation); zcs->outBuffSize = outBuffSize; } diff --git a/lib/zstd.h b/lib/zstd.h index bb447ee1..e8614334 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -460,8 +460,10 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t ***************************************/ /*! ZSTD_estimateCCtxSize() : * Gives the amount of memory allocated for a ZSTD_CCtx given a set of compression parameters. - * `frameContentSize` is an optional parameter, provide `0` if unknown */ -ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); + * Set streaming to 1 if the CCtx will be used for streaming (CStream) + * Note : this function is currently unable to estimate additional memory allocation needed to create an internal CDict + * which can only happen when starting with ZSTD_initCStream_usingDict() */ +ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming); /*! ZSTD_createCCtx_advanced() : * Create a ZSTD compression context using external alloc and free functions */ @@ -599,7 +601,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); /**< same as ZSTD_sizeof_CCtx */ ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ -ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ +ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8. This result in the creation of an internal CDict */ ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */ ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */ diff --git a/tests/paramgrill.c b/tests/paramgrill.c index 1913b54d..3cc916e0 100644 --- a/tests/paramgrill.c +++ b/tests/paramgrill.c @@ -388,8 +388,8 @@ static int BMK_seed(winnerInfo_t* winners, const ZSTD_compressionParameters para double W_DMemUsed_note = W_ratioNote * ( 40 + 9*cLevel) - log((double)W_DMemUsed); double O_DMemUsed_note = O_ratioNote * ( 40 + 9*cLevel) - log((double)O_DMemUsed); - size_t W_CMemUsed = (1 << params.windowLog) + ZSTD_estimateCCtxSize(params); - size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + ZSTD_estimateCCtxSize(winners[cLevel].params); + size_t W_CMemUsed = (1 << params.windowLog) + ZSTD_estimateCCtxSize(params, 0/*streaming*/); + size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + ZSTD_estimateCCtxSize(winners[cLevel].params, 0); double W_CMemUsed_note = W_ratioNote * ( 50 + 13*cLevel) - log((double)W_CMemUsed); double O_CMemUsed_note = O_ratioNote * ( 50 + 13*cLevel) - log((double)O_CMemUsed); From 7855366598f3287974fba8a0ff4d32de56d9efcd Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 May 2017 17:15:00 -0700 Subject: [PATCH 04/15] Updated ZSTD_freeCCtx() which can also contain streaming buffers now. Redirected ZSTD_freeCStream() towards it. --- lib/compress/zstd_compress.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 1248032b..748aff93 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -158,6 +158,13 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) { if (cctx==NULL) return 0; /* support free on NULL */ ZSTD_free(cctx->workSpace, cctx->customMem); + cctx->workSpace = NULL; + ZSTD_freeCDict(cctx->cdictLocal); + cctx->cdictLocal = NULL; + ZSTD_free(cctx->inBuff, cctx->customMem); + cctx->inBuff = NULL; + ZSTD_free(cctx->outBuff, cctx->customMem); + cctx->outBuff = NULL; ZSTD_free(cctx, cctx->customMem); return 0; /* reserved as a potential error code in the future */ } @@ -3140,17 +3147,7 @@ ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem) size_t ZSTD_freeCStream(ZSTD_CStream* zcs) { - if (zcs==NULL) return 0; /* support free on NULL */ - { ZSTD_customMem const cMem = zcs->customMem; - ZSTD_freeCDict(zcs->cdictLocal); - zcs->cdictLocal = NULL; - ZSTD_free(zcs->inBuff, cMem); - zcs->inBuff = NULL; - ZSTD_free(zcs->outBuff, cMem); - zcs->outBuff = NULL; - ZSTD_free(zcs, cMem); - return 0; - } + return ZSTD_freeCCtx(zcs); /* same object */ } From a1d6704d7f63fb9ad177a8364a40385206d21b53 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 May 2017 17:51:49 -0700 Subject: [PATCH 05/15] added ZSTD_estimateCDictSize() and ZSTD_estimateDDictSize() it complements ZSTD_estimateCCtxSize() for the special case of ZSTD_initCStream_usingDict() --- doc/zstd_manual.html | 24 ++++++++++++++++++------ lib/compress/zstd_compress.c | 8 ++++++++ lib/decompress/zstd_decompress.c | 8 ++++++++ lib/zstd.h | 24 +++++++++++++++++------- tests/fuzzer.c | 6 ++++++ 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index d7091545..9cfb6710 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -372,15 +372,17 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v Advanced compression functions
-size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming); -Gives the amount of memory allocated for a ZSTD_CCtx given a set of compression parameters. - `frameContentSize` is an optional parameter, provide `0` if unknown -
-ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);Create a ZSTD compression context using external alloc and free functions
+size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming); +Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters. + Set streaming to 1 if the CCtx will be used for streaming (CStream). + Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. + Use ZSTD_estimateCDictSize() and add this value to estimate total CCtx size +
+size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);amount of used memory is variable, depending primarily on compression level
@@ -406,6 +408,11 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; vCreate a ZSTD_CDict using external alloc and free, and customized compression parameters
size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize); +Estimate amount of memory that will be needed to create a dictionary with following arguments + Note : if dictionary is created "byReference", reduce this amount by dictSize +
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);Gives the amount of memory used by a given ZSTD_sizeof_CDict
Create a ZSTD_DDict using external alloc and free, optionally by reference
size_t ZSTD_estimateDDictSize(size_t dictSize); +Estimate amount of memory that will be needed to create a dictionary for decompression. + Note : if dictionary is created "byReference", reduce this amount by dictSize +
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);Gives the amount of memory used by a given ZSTD_DDict
ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);/**< same as ZSTD_sizeof_CCtx */ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ -size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ +size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8. This result in the creation of an internal CDict */ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */ diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 748aff93..c5687b21 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2984,6 +2984,14 @@ struct ZSTD_CDict_s { ZSTD_CCtx* refContext; }; /* typedef'd tp ZSTD_CDict within "zstd.h" */ +/*! ZSTD_estimateCDictSize() : + * Estimate amount of memory that will be needed to create a dictionary with following arguments */ +size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize) +{ + cParams = ZSTD_adjustCParams(cParams, 0, dictSize); + return sizeof(ZSTD_CDict) + dictSize + ZSTD_estimateCCtxSize(cParams, 0); +} + size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) { if (cdict==NULL) return 0; /* support sizeof on NULL */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 910f9ab7..88488b4b 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1969,6 +1969,14 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict) } } +/*! ZSTD_estimateDDictSize() : + * Estimate amount of memory that will be needed to create a dictionary for decompression. + * Note : if dictionary is created "byReference", reduce this amount by dictSize */ +size_t ZSTD_estimateDDictSize(size_t dictSize) +{ + return dictSize + sizeof(ZSTD_DDict); +} + size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict) { if (ddict==NULL) return 0; /* support sizeof on NULL */ diff --git a/lib/zstd.h b/lib/zstd.h index e8614334..270943b3 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -458,17 +458,17 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t /*************************************** * Advanced compression functions ***************************************/ -/*! ZSTD_estimateCCtxSize() : - * Gives the amount of memory allocated for a ZSTD_CCtx given a set of compression parameters. - * Set streaming to 1 if the CCtx will be used for streaming (CStream) - * Note : this function is currently unable to estimate additional memory allocation needed to create an internal CDict - * which can only happen when starting with ZSTD_initCStream_usingDict() */ -ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming); - /*! ZSTD_createCCtx_advanced() : * Create a ZSTD compression context using external alloc and free functions */ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); +/*! ZSTD_estimateCCtxSize() : + * Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters. + * Set streaming to 1 if the CCtx will be used for streaming (CStream). + * Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. + * Use ZSTD_estimateCDictSize() and add this value to estimate total CCtx size */ +ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming); + /*! ZSTD_sizeofCCtx() : * amount of used memory is variable, depending primarily on compression level */ ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); @@ -493,6 +493,11 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, siz ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_compressionParameters cParams, ZSTD_customMem customMem); +/*! ZSTD_estimateCDictSize() : + * Estimate amount of memory that will be needed to create a dictionary with following arguments + * Note : if dictionary is created "byReference", reduce this amount by dictSize */ +ZSTDLIB_API size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize); + /*! ZSTD_sizeof_CDict() : * Gives the amount of memory used by a given ZSTD_sizeof_CDict */ ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); @@ -564,6 +569,11 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, siz ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem); +/*! ZSTD_estimateDDictSize() : + * Estimate amount of memory that will be needed to create a dictionary for decompression. + * Note : if dictionary is created "byReference", reduce this amount by dictSize */ +ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize); + /*! ZSTD_sizeof_DDict() : * Gives the amount of memory used by a given ZSTD_DDict */ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index a9dcf12e..7ffcff26 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -404,6 +404,12 @@ static int basicUnitTests(U32 seed, double compressibility) if (r != CNBuffSize) goto _output_error); DISPLAYLEVEL(4, "OK \n"); + DISPLAYLEVEL(4, "test%3i : estimate CDict size : ", testNb++); + { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); + size_t const estimatedSize = ZSTD_estimateCDictSize(cParams, dictSize); + DISPLAYLEVEL(4, "OK : %u \n", (U32)estimatedSize); + } + DISPLAYLEVEL(4, "test%3i : compress with preprocessed dictionary : ", testNb++); { ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); ZSTD_customMem customMem = { NULL, NULL, NULL }; From 51652522a21b5897964019fc158dd86db1fafbd5 Mon Sep 17 00:00:00 2001 From: Yann Collet
Create a ZSTD compression context using external alloc and free functions
size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming); -Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters. - Set streaming to 1 if the CCtx will be used for streaming (CStream). - Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. - Use ZSTD_estimateCDictSize() and add this value to estimate total CCtx size +
size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); +Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters.
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); @@ -519,6 +516,11 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; vAdvanced streaming functions
Advanced Streaming compression functions
ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); +/*! ZSTD_estimateCStreamSize() : + * Provides amount of memory needed to allocate ZSTD_CStream with a set of compression parameters. + * Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. + * Use ZSTD_estimateCDictSize() to estimate its size, and add for total CStream size */ +size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); /**< same as ZSTD_sizeof_CCtx */ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8. This result in the creation of an internal CDict */ diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index c5687b21..37590fca 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -251,7 +251,7 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u } -size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming) +size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams) { size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog); U32 const divider = (cParams.searchLength==3) ? 3 : 4; @@ -272,12 +272,7 @@ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned stream size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btopt2)) ? optBudget : 0; size_t const neededSpace = entropySpace + tableSpace + tokenSpace + optSpace; - size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize; - size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; - size_t const streamingBudget = inBuffSize + outBuffSize; - size_t const streamingSize = streaming ? streamingBudget : 0; - - return sizeof(ZSTD_CCtx) + neededSpace + streamingSize; + return sizeof(ZSTD_CCtx) + neededSpace; } @@ -2989,7 +2984,7 @@ struct ZSTD_CDict_s { size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize) { cParams = ZSTD_adjustCParams(cParams, 0, dictSize); - return sizeof(ZSTD_CDict) + dictSize + ZSTD_estimateCCtxSize(cParams, 0); + return sizeof(ZSTD_CDict) + dictSize + ZSTD_estimateCCtxSize(cParams); } size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) @@ -3158,6 +3153,17 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs) return ZSTD_freeCCtx(zcs); /* same object */ } +size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams) +{ + size_t const CCtxSize = ZSTD_estimateCCtxSize(cParams); + size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog); + size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize; + size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; + size_t const streamingSize = inBuffSize + outBuffSize; + + return sizeof(ZSTD_CCtx) + CCtxSize + streamingSize; +} + /*====== Initialization ======*/ diff --git a/lib/zstd.h b/lib/zstd.h index c3a8a52a..86f1c440 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -463,11 +463,8 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); /*! ZSTD_estimateCCtxSize() : - * Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters. - * Set streaming to 1 if the CCtx will be used for streaming (CStream). - * Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. - * Use ZSTD_estimateCDictSize() and add this value to estimate total CCtx size */ -ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned streaming); + * Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters. */ +ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); /*! ZSTD_sizeofCCtx() : * amount of used memory is variable, depending primarily on compression level */ @@ -609,6 +606,11 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); /*===== Advanced Streaming compression functions =====*/ ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); +/*! ZSTD_estimateCStreamSize() : + * Provides amount of memory needed to allocate ZSTD_CStream with a set of compression parameters. + * Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. + * Use ZSTD_estimateCDictSize() to estimate its size, and add for total CStream size */ +ZSTDLIB_API size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); /**< same as ZSTD_sizeof_CCtx */ ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8. This result in the creation of an internal CDict */ diff --git a/tests/paramgrill.c b/tests/paramgrill.c index 3cc916e0..1913b54d 100644 --- a/tests/paramgrill.c +++ b/tests/paramgrill.c @@ -388,8 +388,8 @@ static int BMK_seed(winnerInfo_t* winners, const ZSTD_compressionParameters para double W_DMemUsed_note = W_ratioNote * ( 40 + 9*cLevel) - log((double)W_DMemUsed); double O_DMemUsed_note = O_ratioNote * ( 40 + 9*cLevel) - log((double)O_DMemUsed); - size_t W_CMemUsed = (1 << params.windowLog) + ZSTD_estimateCCtxSize(params, 0/*streaming*/); - size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + ZSTD_estimateCCtxSize(winners[cLevel].params, 0); + size_t W_CMemUsed = (1 << params.windowLog) + ZSTD_estimateCCtxSize(params); + size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + ZSTD_estimateCCtxSize(winners[cLevel].params); double W_CMemUsed_note = W_ratioNote * ( 50 + 13*cLevel) - log((double)W_CMemUsed); double O_CMemUsed_note = O_ratioNote * ( 50 + 13*cLevel) - log((double)O_CMemUsed); From 5a36c069e73d7c2297e44201c5eb7d758435208e Mon Sep 17 00:00:00 2001 From: Yann ColletDate: Tue, 9 May 2017 15:11:30 -0700 Subject: [PATCH 08/15] regroup memory usage function declarations in a single paragraph in zstd.h, for clarity --- doc/zstd_manual.html | 143 ++++++++++++++++++++--------------------- lib/zstd.h | 148 ++++++++++++++++++++----------------------- 2 files changed, 136 insertions(+), 155 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index a5612c92..c934da04 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -19,8 +19,8 @@ Streaming decompression - HowTo START OF ADVANCED AND EXPERIMENTAL FUNCTIONS Advanced types -Compressed size functions -Decompressed size functions +Frame size functions +Context memory usage Advanced compression functions Advanced decompression functions Advanced streaming functions @@ -325,49 +325,81 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB typedef void (*ZSTD_freeFunction) (void* opaque, void* address); typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
-Compressed size functions
+Frame size functions
size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);`src` should point to the start of a ZSTD encoded frame or skippable frame `srcSize` must be at least as large as the frame - @return : the compressed size of the frame pointed to by `src`, suitable to pass to - `ZSTD_decompress` or similar, or an error code if given invalid input. + @return : the compressed size of the frame pointed to by `src`, + suitable to pass to `ZSTD_decompress` or similar, + or an error code if given invalid input.
-Decompressed size functions
- -unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); -`src` should point to the start of a ZSTD encoded frame - `srcSize` must be at least as large as the frame header. A value greater than or equal - to `ZSTD_frameHeaderSize_max` is guaranteed to be large enough in all cases. - @return : decompressed size of the frame pointed to be `src` if known, otherwise - - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined - - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) +
#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) +unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); +`src` should point to the start of a ZSTD encoded frame. + `srcSize` must be at least as large as the frame header. + A value >= `ZSTD_frameHeaderSize_max` is guaranteed to be large enough. + @return : - decompressed size of the frame pointed to be `src` if known + - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); -`src` should point the start of a series of ZSTD encoded and/or skippable frames - `srcSize` must be the _exact_ size of this series +
`src` should point the start of a series of ZSTD encoded and/or skippable frames + `srcSize` must be the _exact_ size of this series (i.e. there should be a frame boundary exactly `srcSize` bytes after `src`) - @return : the decompressed size of all data in the contained frames, as a 64-bit value _if known_ - - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN - - if an error occurred: ZSTD_CONTENTSIZE_ERROR + @return : - decompressed size of all data in all successive frames + - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN + - if an error occurred: ZSTD_CONTENTSIZE_ERROR - note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. - When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - In which case, it's necessary to use streaming mode to decompress data. - Optionally, application can still use ZSTD_decompress() while relying on implied limits. - (For example, data may be necessarily cut into blocks <= 16 KB). - note 2 : decompressed size is always present when compression is done with ZSTD_compress() - note 3 : decompressed size can be very large (64-bits value), - potentially larger than what local system can handle as a single memory segment. - In which case, it's necessary to use streaming mode to decompress data. - note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. - Always ensure result fits within application's authorized limits. - Each application can set its own limits. - note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to - read each contained frame header. This is efficient as most of the data is skipped, - however it does mean that all frame data must be present and valid. + note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. + When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + In which case, it's necessary to use streaming mode to decompress data. + Optionally, application can still use ZSTD_decompress() while relying on implied limits. + (For example, data may be necessarily cut into blocks <= 16 KB). + note 2 : decompressed size is always present when compression is done with ZSTD_compress() + note 3 : decompressed size can be very large (64-bits value), + potentially larger than what local system can handle as a single memory segment. + In which case, it's necessary to use streaming mode to decompress data. + note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. + Always ensure result fits within application's authorized limits. + Each application can set its own limits. + note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to + read each contained frame header. This is efficient as most of the data is skipped, + however it does mean that all frame data must be present and valid. +
+ +Context memory usage
+ +size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); +size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); +size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); +size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); +size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); +size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); +These functions give the current memory usage of selected object. + Object memory usage can evolve if it's re-used multiple times. +
+ +size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); +size_t ZSTD_estimateDCtxSize(void); +These functions make it possible to estimate memory usage + of a future target object, before its allocation, + given a set of parameters, which vary depending on target object. + The objective is to guide decision before allocation. +
+ +size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); +Note : if streaming is init with function ZSTD_init?Stream_usingDict(), + an internal ?Dict will be created, which size is not estimated. + In this case, get additional size by using ZSTD_estimate?DictSize +
+ +size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize); +size_t ZSTD_estimateDDictSize(size_t dictSize); +Note : if dictionary is created "byReference", reduce estimation by dictSize
Advanced compression functions
@@ -376,14 +408,6 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; vCreate a ZSTD compression context using external alloc and free functions
-size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); -Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters. -
- -size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); -amount of used memory is variable, depending primarily on compression level -
-typedef enum { ZSTD_p_forceWindow, /* Force back-references to remain < windowSize, even when referencing Dictionary content (default:0) */ ZSTD_p_forceRawDict /* Force loading dictionary in "content-only" mode (no header analysis) */ @@ -405,15 +429,6 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; vCreate a ZSTD_CDict using external alloc and free, and customized compression parameters
-size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize); -Estimate amount of memory that will be needed to create a dictionary with following arguments - Note : if dictionary is created "byReference", reduce this amount by dictSize -
- -size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); -Gives the amount of memory used by a given ZSTD_sizeof_CDict -
-ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);@return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. `estimatedSrcSize` value is optional, select 0 if not known @@ -457,18 +472,10 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v Note 3 : Skippable Frame Identifiers are considered valid.
-size_t ZSTD_estimateDCtxSize(void); -Gives the potential amount of memory allocated to create a ZSTD_DCtx -
-ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);Create a ZSTD decompression context using external alloc and free functions
-size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); -Gives the amount of memory used by a given ZSTD_DCtx -
-ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);Create a digested dictionary, ready to start decompression operation without startup delay. Dictionary content is simply referenced, and therefore stays in dictBuffer. @@ -480,15 +487,6 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v
Create a ZSTD_DDict using external alloc and free, optionally by reference
-size_t ZSTD_estimateDDictSize(size_t dictSize); -Estimate amount of memory that will be needed to create a dictionary for decompression. - Note : if dictionary is created "byReference", reduce this amount by dictSize -
- -size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); -Gives the amount of memory used by a given ZSTD_DDict -
-unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);Provides the dictID stored within dictionary. if @return == 0, the dictionary is not conformant with Zstandard specification. @@ -516,12 +514,6 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v
Advanced streaming functions
Advanced Streaming compression functions
ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); -/*! ZSTD_estimateCStreamSize() : - * Provides amount of memory needed to allocate ZSTD_CStream with a set of compression parameters. - * Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. - * Use ZSTD_estimateCDictSize() to estimate its size, and add for total CStream size */ -size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); -size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); /**< same as ZSTD_sizeof_CCtx */ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8. This result in the creation of an internal CDict */ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, @@ -540,11 +532,10 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict*Advanced Streaming decompression functions
typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e; ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); -size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);/**< note: a dict will not be used if dict == NULL or dictSize < 8 */ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue); +size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict will just be referenced, and must outlive decompression session */ size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */ -size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
Buffer-less and synchronous inner streaming functions
This is an advanced API, giving full control over buffer management, for users which need direct control over memory. diff --git a/lib/zstd.h b/lib/zstd.h index 86f1c440..690c851f 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -350,9 +350,6 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output #define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */ #define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U -#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) -#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) - #define ZSTD_WINDOWLOG_MAX_32 27 #define ZSTD_WINDOWLOG_MAX_64 27 #define ZSTD_WINDOWLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) @@ -407,54 +404,88 @@ typedef void (*ZSTD_freeFunction) (void* opaque, void* address); typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; /*************************************** -* Compressed size functions +* Frame size functions ***************************************/ /*! ZSTD_findFrameCompressedSize() : * `src` should point to the start of a ZSTD encoded frame or skippable frame * `srcSize` must be at least as large as the frame - * @return : the compressed size of the frame pointed to by `src`, suitable to pass to - * `ZSTD_decompress` or similar, or an error code if given invalid input. */ + * @return : the compressed size of the frame pointed to by `src`, + * suitable to pass to `ZSTD_decompress` or similar, + * or an error code if given invalid input. */ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); -/*************************************** -* Decompressed size functions -***************************************/ /*! ZSTD_getFrameContentSize() : -* `src` should point to the start of a ZSTD encoded frame -* `srcSize` must be at least as large as the frame header. A value greater than or equal -* to `ZSTD_frameHeaderSize_max` is guaranteed to be large enough in all cases. -* @return : decompressed size of the frame pointed to be `src` if known, otherwise -* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined -* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */ + * `src` should point to the start of a ZSTD encoded frame. + * `srcSize` must be at least as large as the frame header. + * A value >= `ZSTD_frameHeaderSize_max` is guaranteed to be large enough. + * @return : - decompressed size of the frame pointed to be `src` if known + * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); /*! ZSTD_findDecompressedSize() : -* `src` should point the start of a series of ZSTD encoded and/or skippable frames -* `srcSize` must be the _exact_ size of this series -* (i.e. there should be a frame boundary exactly `srcSize` bytes after `src`) -* @return : the decompressed size of all data in the contained frames, as a 64-bit value _if known_ -* - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN -* - if an error occurred: ZSTD_CONTENTSIZE_ERROR -* -* note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. -* When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. -* In which case, it's necessary to use streaming mode to decompress data. -* Optionally, application can still use ZSTD_decompress() while relying on implied limits. -* (For example, data may be necessarily cut into blocks <= 16 KB). -* note 2 : decompressed size is always present when compression is done with ZSTD_compress() -* note 3 : decompressed size can be very large (64-bits value), -* potentially larger than what local system can handle as a single memory segment. -* In which case, it's necessary to use streaming mode to decompress data. -* note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. -* Always ensure result fits within application's authorized limits. -* Each application can set its own limits. -* note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to -* read each contained frame header. This is efficient as most of the data is skipped, -* however it does mean that all frame data must be present and valid. */ + * `src` should point the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary exactly `srcSize` bytes after `src`) + * @return : - decompressed size of all data in all successive frames + * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * Optionally, application can still use ZSTD_decompress() while relying on implied limits. + * (For example, data may be necessarily cut into blocks <= 16 KB). + * note 2 : decompressed size is always present when compression is done with ZSTD_compress() + * note 3 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure result fits within application's authorized limits. + * Each application can set its own limits. + * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to + * read each contained frame header. This is efficient as most of the data is skipped, + * however it does mean that all frame data must be present and valid. */ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); +/*************************************** +* Context memory usage +***************************************/ + +/*! ZSTD_sizeof_*() : + * These functions give the current memory usage of selected object. + * Object memory usage can evolve if it's re-used multiple times. */ +ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); +ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); +ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); +ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); + +/*! ZSTD_estimate*() : + * These functions make it possible to estimate memory usage + * of a future target object, before its allocation, + * given a set of parameters, which vary depending on target object. + * The objective is to guide decision before allocation. */ +ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); +ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); + +/*! ZSTD_estimate?StreamSize() : + * Note : if streaming is init with function ZSTD_init?Stream_usingDict(), + * an internal ?Dict will be created, which size is not estimated. + * In this case, get additional size by using ZSTD_estimate?DictSize */ +ZSTDLIB_API size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); + +/*! ZSTD_estimate?DictSize() : + * Note : if dictionary is created "byReference", reduce estimation by dictSize */ +ZSTDLIB_API size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize); +ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize); + + /*************************************** * Advanced compression functions ***************************************/ @@ -462,14 +493,6 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t * Create a ZSTD compression context using external alloc and free functions */ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); -/*! ZSTD_estimateCCtxSize() : - * Provides amount of memory needed to allocate ZSTD_CCtx with a set of compression parameters. */ -ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); - -/*! ZSTD_sizeofCCtx() : - * amount of used memory is variable, depending primarily on compression level */ -ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); - typedef enum { ZSTD_p_forceWindow, /* Force back-references to remain < windowSize, even when referencing Dictionary content (default:0) */ ZSTD_p_forceRawDict /* Force loading dictionary in "content-only" mode (no header analysis) */ @@ -490,15 +513,6 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, siz ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_compressionParameters cParams, ZSTD_customMem customMem); -/*! ZSTD_estimateCDictSize() : - * Estimate amount of memory that will be needed to create a dictionary with following arguments - * Note : if dictionary is created "byReference", reduce this amount by dictSize */ -ZSTDLIB_API size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize); - -/*! ZSTD_sizeof_CDict() : - * Gives the amount of memory used by a given ZSTD_sizeof_CDict */ -ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); - /*! ZSTD_getCParams() : * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. * `estimatedSrcSize` value is optional, select 0 if not known */ @@ -543,18 +557,10 @@ ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, * Note 3 : Skippable Frame Identifiers are considered valid. */ ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size); -/*! ZSTD_estimateDCtxSize() : - * Gives the potential amount of memory allocated to create a ZSTD_DCtx */ -ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); - /*! ZSTD_createDCtx_advanced() : * Create a ZSTD decompression context using external alloc and free functions */ ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); -/*! ZSTD_sizeof_DCtx() : - * Gives the amount of memory used by a given ZSTD_DCtx */ -ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); - /*! ZSTD_createDDict_byReference() : * Create a digested dictionary, ready to start decompression operation without startup delay. * Dictionary content is simply referenced, and therefore stays in dictBuffer. @@ -566,15 +572,6 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, siz ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem); -/*! ZSTD_estimateDDictSize() : - * Estimate amount of memory that will be needed to create a dictionary for decompression. - * Note : if dictionary is created "byReference", reduce this amount by dictSize */ -ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize); - -/*! ZSTD_sizeof_DDict() : - * Gives the amount of memory used by a given ZSTD_DDict */ -ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); - /*! ZSTD_getDictID_fromDict() : * Provides the dictID stored within dictionary. * if @return == 0, the dictionary is not conformant with Zstandard specification. @@ -606,12 +603,6 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); /*===== Advanced Streaming compression functions =====*/ ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); -/*! ZSTD_estimateCStreamSize() : - * Provides amount of memory needed to allocate ZSTD_CStream with a set of compression parameters. - * Special case : when using ZSTD_initCStream_usingDict(), init will transparently create an internal CDict. - * Use ZSTD_estimateCDictSize() to estimate its size, and add for total CStream size */ -ZSTDLIB_API size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); -ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); /**< same as ZSTD_sizeof_CCtx */ ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8. This result in the creation of an internal CDict */ ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, @@ -632,11 +623,10 @@ ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledg /*===== Advanced Streaming decompression functions =====*/ typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e; ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); -ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue); +ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict will just be referenced, and must outlive decompression session */ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */ -ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); /********************************************************************* From 542c9dfcf8002fc6b5fe338abbb3316770833e40 Mon Sep 17 00:00:00 2001 From: Yann ColletDate: Tue, 9 May 2017 15:46:07 -0700 Subject: [PATCH 09/15] changed name frameParams into frameHeader ZSTD_frameParams => ZSTD_frameHeader ZSTD_getFrameParams() -> ZSTD_getFrameHeader() The new naming is more distinctive from ZSTD_frameParameters, which is used during compression. ZSTD_frameHeader is clearer in its intention to described frame header content. It also implies we are decoding a ZSTD frame, hence we are at decoding stage. --- doc/zstd_manual.html | 4 ++-- lib/decompress/zstd_decompress.c | 27 +++++++++++++-------------- lib/zstd.h | 4 ++-- tests/fullbench.c | 8 ++++---- tests/fuzzer.c | 8 ++++---- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index c934da04..d24a6b89 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -643,9 +643,9 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned lo unsigned windowSize; unsigned dictID; unsigned checksumFlag; -} ZSTD_frameParams; +} ZSTD_frameHeader;
-Buffer-less streaming decompression functions
size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize);/**< doesn't consume input, see details below */ +Buffer-less streaming decompression functions
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize);/**< doesn't consume input, see details below */ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 88488b4b..3c231a94 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -105,7 +105,7 @@ struct ZSTD_DCtx_s const void* vBase; /* virtual start of previous segment if it was just before current one */ const void* dictEnd; /* end of previous segment */ size_t expected; - ZSTD_frameParams fParams; + ZSTD_frameHeader fParams; blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */ ZSTD_dStage stage; U32 litEntropy; @@ -219,12 +219,12 @@ static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) } -/** ZSTD_getFrameParams() : +/** ZSTD_getFrameHeader() : * decode Frame Header, or require larger `srcSize`. * @return : 0, `fparamsPtr` is correctly filled, * >0, `srcSize` is too small, result is 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_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize) { const BYTE* ip = (const BYTE*)src; @@ -302,9 +302,8 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize) return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret; } #endif - { - ZSTD_frameParams fParams; - if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0) return ZSTD_CONTENTSIZE_ERROR; + { ZSTD_frameHeader fParams; + if (ZSTD_getFrameHeader(&fParams, src, srcSize) != 0) return ZSTD_CONTENTSIZE_ERROR; if (fParams.windowSize == 0) { /* Either skippable or empty frame, size == 0 either way */ return 0; @@ -389,7 +388,7 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize) * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize) { - size_t const result = ZSTD_getFrameParams(&(dctx->fParams), src, headerSize); + size_t const result = ZSTD_getFrameHeader(&(dctx->fParams), src, headerSize); if (ZSTD_isError(result)) return result; /* invalid header */ if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */ if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong); @@ -1364,13 +1363,13 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) const BYTE* ip = (const BYTE*)src; const BYTE* const ipstart = ip; size_t remainingSize = srcSize; - ZSTD_frameParams fParams; + ZSTD_frameHeader fParams; size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize); if (ZSTD_isError(headerSize)) return headerSize; /* Frame Header */ - { size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize); + { size_t const ret = ZSTD_getFrameHeader(&fParams, ip, remainingSize); if (ZSTD_isError(ret)) return ret; if (ret > 0) return ERROR(srcSize_wrong); } @@ -2016,11 +2015,11 @@ unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict) * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`. * - This is not a Zstandard frame. * When identifying the exact failure cause, it's possible to use - * ZSTD_getFrameParams(), which will provide a more precise error code. */ + * ZSTD_getFrameHeader(), 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); + ZSTD_frameHeader zfp = { 0 , 0 , 0 , 0 }; + size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize); if (ZSTD_isError(hError)) return 0; return zfp.dictID; } @@ -2053,7 +2052,7 @@ struct ZSTD_DStream_s { ZSTD_DCtx* dctx; ZSTD_DDict* ddictLocal; const ZSTD_DDict* ddict; - ZSTD_frameParams fParams; + ZSTD_frameHeader fParams; ZSTD_dStreamStage stage; char* inBuff; size_t inBuffSize; @@ -2217,7 +2216,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB /* fall-through */ case zdss_loadHeader : - { size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize); + { size_t const hSize = ZSTD_getFrameHeader(&zds->fParams, zds->headerBuffer, zds->lhSize); if (ZSTD_isError(hSize)) #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) { U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart); diff --git a/lib/zstd.h b/lib/zstd.h index 690c851f..ddcaaf8b 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -746,10 +746,10 @@ typedef struct { unsigned windowSize; unsigned dictID; unsigned checksumFlag; -} ZSTD_frameParams; +} ZSTD_frameHeader; /*===== Buffer-less streaming decompression functions =====*/ -ZSTDLIB_API size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input, see details below */ +ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input, see details below */ ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); diff --git a/tests/fullbench.c b/tests/fullbench.c index 38cf22fa..13323aec 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -297,10 +297,10 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb) case 31: /* ZSTD_decodeLiteralsBlock */ if (g_zdc==NULL) g_zdc = ZSTD_createDCtx(); { blockProperties_t bp; - ZSTD_frameParams zfp; + ZSTD_frameHeader zfp; size_t frameHeaderSize, skippedSize; g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, 1); - frameHeaderSize = ZSTD_getFrameParams(&zfp, dstBuff, ZSTD_frameHeaderSize_min); + frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_frameHeaderSize_min); if (frameHeaderSize==0) frameHeaderSize = ZSTD_frameHeaderSize_min; ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { @@ -315,13 +315,13 @@ static size_t benchMem(const void* src, size_t srcSize, U32 benchNb) case 32: /* ZSTD_decodeSeqHeaders */ if (g_zdc==NULL) g_zdc = ZSTD_createDCtx(); { blockProperties_t bp; - ZSTD_frameParams zfp; + ZSTD_frameHeader zfp; const BYTE* ip = dstBuff; const BYTE* iend; size_t frameHeaderSize, cBlockSize; ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, 1); /* it would be better to use direct block compression here */ g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, 1); - frameHeaderSize = ZSTD_getFrameParams(&zfp, dstBuff, ZSTD_frameHeaderSize_min); + frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_frameHeaderSize_min); if (frameHeaderSize==0) frameHeaderSize = ZSTD_frameHeaderSize_min; ip += frameHeaderSize; /* Skip frame Header */ cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */ diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 7ffcff26..4b9cd97a 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -339,8 +339,8 @@ static int basicUnitTests(U32 seed, double compressibility) CHECKPLUS(r, ZSTD_compressEnd(ctxDuplicated, compressedBuffer, ZSTD_compressBound(testSize), (const char*)CNBuffer + dictSize, testSize), cSize = r); - { ZSTD_frameParams fp; - if (ZSTD_getFrameParams(&fp, compressedBuffer, cSize)) goto _output_error; + { ZSTD_frameHeader fp; + if (ZSTD_getFrameHeader(&fp, compressedBuffer, cSize)) goto _output_error; if ((fp.frameContentSize != testSize) && (fp.frameContentSize != 0)) goto _output_error; } } DISPLAYLEVEL(4, "OK \n"); @@ -862,8 +862,8 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 const maxD } /* frame header decompression test */ - { ZSTD_frameParams dParams; - size_t const check = ZSTD_getFrameParams(&dParams, cBuffer, cSize); + { ZSTD_frameHeader dParams; + size_t const check = ZSTD_getFrameHeader(&dParams, cBuffer, cSize); CHECK(ZSTD_isError(check), "Frame Parameters extraction failed"); CHECK(dParams.frameContentSize != sampleSize, "Frame content size incorrect"); } From f16f4497ca121f8a0ec82e2af35a4a00d82acf13 Mon Sep 17 00:00:00 2001 From: Yann ColletDate: Tue, 9 May 2017 16:18:17 -0700 Subject: [PATCH 10/15] added ZSTD_estimateDStreamSize() --- doc/zstd_manual.html | 15 ++++++++------- lib/decompress/zstd_decompress.c | 30 ++++++++++++++++++++---------- lib/zstd.h | 15 ++++++++------- tests/zstreamtest.c | 15 ++++++++++++++- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index d24a6b89..9cfb1b68 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -321,6 +321,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB ZSTD_frameParameters fParams; } ZSTD_parameters;
typedef struct { + unsigned long long frameContentSize; + unsigned windowSize; + unsigned dictID; + unsigned checksumFlag; +} ZSTD_frameHeader; +
typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); typedef void (*ZSTD_freeFunction) (void* opaque, void* address); typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; @@ -392,6 +399,7 @@ size_t ZSTD_estimateDCtxSize(void);
size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); +size_t ZSTD_estimateDStreamSize(ZSTD_frameHeader fHeader);-Note : if streaming is init with function ZSTD_init?Stream_usingDict(), an internal ?Dict will be created, which size is not estimated. In this case, get additional size by using ZSTD_estimate?DictSize @@ -638,13 +646,6 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned lo It also returns Frame Size as fparamsPtr->frameContentSize.
typedef struct { - unsigned long long frameContentSize; - unsigned windowSize; - unsigned dictID; - unsigned checksumFlag; -} ZSTD_frameHeader; -
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize);/**< doesn't consume input, see details below */ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 3c231a94..267aa94d 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -221,20 +221,21 @@ static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) /** ZSTD_getFrameHeader() : * decode Frame Header, or require larger `srcSize`. -* @return : 0, `fparamsPtr` is correctly filled, +* @return : 0, `fhiPtr` is correctly filled, * >0, `srcSize` is too small, result is expected `srcSize`, * or an error code, which can be tested using ZSTD_isError() */ -size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize) +size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fhiPtr, const void* src, size_t srcSize) { const BYTE* ip = (const BYTE*)src; - if (srcSize < ZSTD_frameHeaderSize_prefix) return ZSTD_frameHeaderSize_prefix; + if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) { if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + /* skippable frame */ if (srcSize < ZSTD_skippableHeaderSize) return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */ - memset(fparamsPtr, 0, sizeof(*fparamsPtr)); - fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4); - fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */ + memset(fhiPtr, 0, sizeof(*fhiPtr)); + fhiPtr->frameContentSize = MEM_readLE32((const char *)src + 4); + fhiPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */ return 0; } return ERROR(prefix_unknown); @@ -281,10 +282,10 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t } if (!windowSize) windowSize = (U32)frameContentSize; if (windowSize > windowSizeMax) return ERROR(frameParameter_windowTooLarge); - fparamsPtr->frameContentSize = frameContentSize; - fparamsPtr->windowSize = windowSize; - fparamsPtr->dictID = dictID; - fparamsPtr->checksumFlag = checksumFlag; + fhiPtr->frameContentSize = frameContentSize; + fhiPtr->windowSize = windowSize; + fhiPtr->dictID = dictID; + fhiPtr->checksumFlag = checksumFlag; } return 0; } @@ -2182,6 +2183,15 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds) + zds->inBuffSize + zds->outBuffSize; } +size_t ZSTD_estimateDStreamSize(ZSTD_frameHeader fHeader) +{ + size_t const windowSize = fHeader.windowSize; + size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); + size_t const inBuffSize = blockSize; /* no block can be larger */ + size_t const outBuffSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2); + return sizeof(ZSTD_DStream) + ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize; +} + /* ***** Decompression ***** */ diff --git a/lib/zstd.h b/lib/zstd.h index ddcaaf8b..08754cb2 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -398,6 +398,13 @@ typedef struct { ZSTD_frameParameters fParams; } ZSTD_parameters; +typedef struct { + unsigned long long frameContentSize; + unsigned windowSize; + unsigned dictID; + unsigned checksumFlag; +} ZSTD_frameHeader; + /*= Custom memory allocation functions */ typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); typedef void (*ZSTD_freeFunction) (void* opaque, void* address); @@ -479,6 +486,7 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); * an internal ?Dict will be created, which size is not estimated. * In this case, get additional size by using ZSTD_estimate?DictSize */ ZSTDLIB_API size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams); +ZSTDLIB_API size_t ZSTD_estimateDStreamSize(ZSTD_frameHeader fHeader); /*! ZSTD_estimate?DictSize() : * Note : if dictionary is created "byReference", reduce estimation by dictSize */ @@ -741,13 +749,6 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci It also returns Frame Size as fparamsPtr->frameContentSize. */ -typedef struct { - unsigned long long frameContentSize; - unsigned windowSize; - unsigned dictID; - unsigned checksumFlag; -} ZSTD_frameHeader; - /*===== Buffer-less streaming decompression functions =====*/ ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input, see details below */ ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 6c210f2f..6ce309c5 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -262,7 +262,20 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo } } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : check DStream size : ", testNb++); + /* context size functions */ + DISPLAYLEVEL(3, "test%3i : estimate DStream size : ", testNb++); + { ZSTD_frameHeader fhi; + const void* cStart = (char*)compressedBuffer + (skippableFrameSize + 8); + size_t const gfhError = ZSTD_getFrameHeader(&fhi, cStart, cSize); + if (gfhError!=0) goto _output_error; + DISPLAYLEVEL(5, " (windowSize : %u) ", fhi.windowSize); + { size_t const s = ZSTD_estimateDStreamSize(fhi) + + ZSTD_estimateDDictSize(128 KB); /* uses ZSTD_initDStream_usingDict() */ + if (ZSTD_isError(s)) goto _output_error; + DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s); + } } + + DISPLAYLEVEL(3, "test%3i : check actual DStream size : ", testNb++); { size_t const s = ZSTD_sizeof_DStream(zd); if (ZSTD_isError(s)) goto _output_error; DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s); From 461a9cc7c62f9d6fc5bcb2725601e2e073a0f392 Mon Sep 17 00:00:00 2001 From: Yann Collet
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize);/**< doesn't consume input, see details below */ +
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize);/**< doesn't consume input, see details below */ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 267aa94d..379842b5 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -221,10 +221,10 @@ static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) /** ZSTD_getFrameHeader() : * decode Frame Header, or require larger `srcSize`. -* @return : 0, `fhiPtr` is correctly filled, +* @return : 0, `zfhPtr` is correctly filled, * >0, `srcSize` is too small, result is expected `srcSize`, * or an error code, which can be tested using ZSTD_isError() */ -size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fhiPtr, const void* src, size_t srcSize) +size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize) { const BYTE* ip = (const BYTE*)src; if (srcSize < ZSTD_frameHeaderSize_prefix) return ZSTD_frameHeaderSize_prefix; @@ -233,9 +233,9 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fhiPtr, const void* src, size_t src if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ if (srcSize < ZSTD_skippableHeaderSize) return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */ - memset(fhiPtr, 0, sizeof(*fhiPtr)); - fhiPtr->frameContentSize = MEM_readLE32((const char *)src + 4); - fhiPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */ + memset(zfhPtr, 0, sizeof(*zfhPtr)); + zfhPtr->frameContentSize = MEM_readLE32((const char *)src + 4); + zfhPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */ return 0; } return ERROR(prefix_unknown); @@ -282,10 +282,10 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fhiPtr, const void* src, size_t src } if (!windowSize) windowSize = (U32)frameContentSize; if (windowSize > windowSizeMax) return ERROR(frameParameter_windowTooLarge); - fhiPtr->frameContentSize = frameContentSize; - fhiPtr->windowSize = windowSize; - fhiPtr->dictID = dictID; - fhiPtr->checksumFlag = checksumFlag; + zfhPtr->frameContentSize = frameContentSize; + zfhPtr->windowSize = windowSize; + zfhPtr->dictID = dictID; + zfhPtr->checksumFlag = checksumFlag; } return 0; } diff --git a/lib/zstd.h b/lib/zstd.h index 08754cb2..c956860a 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -750,7 +750,7 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci */ /*===== Buffer-less streaming decompression functions =====*/ -ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input, see details below */ +ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input, see details below */ ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); From 30ab64e21d09f8b493c2ae7968c7139b5d197e23 Mon Sep 17 00:00:00 2001 From: Yann Collet