From 0be6fd342984d375965255bff77f8936bcd85f8a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 May 2017 16:08:01 -0700 Subject: [PATCH 01/15] merged CCtx and CStream as a single same object To be changed : ZSTD_sizeof_CCtx(), ZSTD_estimateCCtxSize() --- doc/zstd_manual.html | 2 + lib/compress/zstd_compress.c | 124 +++++++++++++++++++---------------- lib/zstd.h | 3 +- tests/zstreamtest.c | 18 +++-- 4 files changed, 84 insertions(+), 63 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 2e77e774..8cac4294 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -244,6 +244,8 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
+
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<stage!=ZSTDcs_init) return ERROR(stage_wrong); memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); @@ -2528,9 +2554,8 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, size_t pos; if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall); - DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u \n", !params.fParams.noDictIDFlag); - DEBUGLOG(5, "ZSTD_writeFrameHeader : dictID : %u \n", dictID); - DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDSizeCode : %u \n", dictIDSizeCode); + DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u \n", + !params.fParams.noDictIDFlag, dictID, dictIDSizeCode); MEM_writeLE32(dst, ZSTD_MAGICNUMBER); op[4] = frameHeaderDecriptionByte; pos=5; @@ -2840,6 +2865,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) BYTE* op = ostart; size_t fhSize = 0; + DEBUGLOG(5, "ZSTD_writeEpilogue \n"); if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */ /* special case : empty frame */ @@ -2877,12 +2903,14 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx, const void* src, size_t srcSize) { size_t endResult; - size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 1 /* last chunk */); + size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, + 1 /* frame mode */, 1 /* last chunk */); if (ZSTD_isError(cSize)) return cSize; endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); if (ZSTD_isError(endResult)) return endResult; if (cctx->params.fParams.contentSizeFlag) { /* control src size */ - if (cctx->frameContentSize != cctx->consumedSrcSize) return ERROR(srcSize_wrong); + if (cctx->frameContentSize != cctx->consumedSrcSize) + return ERROR(srcSize_wrong); } return cSize + endResult; } @@ -3084,30 +3112,6 @@ size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, * Streaming ********************************************************************/ -typedef enum { zcss_init, zcss_load, zcss_flush, zcss_final } ZSTD_cStreamStage; - -struct ZSTD_CStream_s { - ZSTD_CCtx* cctx; - ZSTD_CDict* cdictLocal; - const ZSTD_CDict* cdict; - char* inBuff; - size_t inBuffSize; - size_t inToCompress; - size_t inBuffPos; - size_t inBuffTarget; - size_t blockSize; - char* outBuff; - size_t outBuffSize; - size_t outBuffContentSize; - size_t outBuffFlushedSize; - ZSTD_cStreamStage stage; - U32 checksum; - U32 frameEnded; - U64 pledgedSrcSize; - ZSTD_parameters params; - ZSTD_customMem customMem; -}; /* typedef'd to ZSTD_CStream within "zstd.h" */ - ZSTD_CStream* ZSTD_createCStream(void) { return ZSTD_createCStream_advanced(defaultCustomMem); @@ -3124,8 +3128,6 @@ ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem) if (zcs==NULL) return NULL; memset(zcs, 0, sizeof(ZSTD_CStream)); memcpy(&zcs->customMem, &customMem, sizeof(ZSTD_customMem)); - zcs->cctx = ZSTD_createCCtx_advanced(customMem); - if (zcs->cctx == NULL) { ZSTD_freeCStream(zcs); return NULL; } return zcs; } @@ -3133,8 +3135,6 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs) { if (zcs==NULL) return 0; /* support free on NULL */ { ZSTD_customMem const cMem = zcs->customMem; - ZSTD_freeCCtx(zcs->cctx); - zcs->cctx = NULL; ZSTD_freeCDict(zcs->cdictLocal); zcs->cdictLocal = NULL; ZSTD_free(zcs->inBuff, cMem); @@ -3156,20 +3156,20 @@ size_t ZSTD_CStreamOutSize(void) return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; } -static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize) +static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, ZSTD_parameters params, unsigned long long pledgedSrcSize) { if (zcs->inBuffSize==0) return ERROR(stage_wrong); /* zcs has not been init at least once => can't reset */ DEBUGLOG(5, "ZSTD_resetCStream_internal : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag); - if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict_advanced(zcs->cctx, zcs->cdict, zcs->params.fParams, pledgedSrcSize)) - else CHECK_F(ZSTD_compressBegin_internal(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize)); + if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict_advanced(zcs, zcs->cdict, params.fParams, pledgedSrcSize)) + else CHECK_F(ZSTD_compressBegin_internal(zcs, NULL, 0, params, pledgedSrcSize)); zcs->inToCompress = 0; zcs->inBuffPos = 0; zcs->inBuffTarget = zcs->blockSize; zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; - zcs->stage = zcss_load; + zcs->streamStage = zcss_load; zcs->frameEnded = 0; zcs->pledgedSrcSize = pledgedSrcSize; return 0; /* ready to go */ @@ -3178,9 +3178,10 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, unsigned long long p size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize) { - zcs->params.fParams.contentSizeFlag = (pledgedSrcSize > 0); + ZSTD_parameters params = zcs->params; + params.fParams.contentSizeFlag = (pledgedSrcSize > 0); DEBUGLOG(5, "ZSTD_resetCStream : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag); - return ZSTD_resetCStream_internal(zcs, pledgedSrcSize); + return ZSTD_resetCStream_internal(zcs, params, pledgedSrcSize); } /* ZSTD_initCStream_internal() : @@ -3212,11 +3213,8 @@ static size_t ZSTD_initCStream_stage2(ZSTD_CStream* zcs, zcs->outBuffSize = outBuffSize; } - zcs->checksum = params.fParams.checksumFlag > 0; - zcs->params = params; - DEBUGLOG(5, "ZSTD_initCStream_stage2 : dictIDFlag == %u \n", !params.fParams.noDictIDFlag); - return ZSTD_resetCStream_internal(zcs, pledgedSrcSize); + return ZSTD_resetCStream_internal(zcs, params, pledgedSrcSize); } /* ZSTD_initCStream_usingCDict_advanced() : @@ -3261,7 +3259,8 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, ZSTD_parameters params, unsigned long long pledgedSrcSize) { CHECK_F( ZSTD_checkCParams(params.cParams) ); - DEBUGLOG(5, "ZSTD_initCStream_advanced : dictIDFlag == %u \n", !params.fParams.noDictIDFlag); + DEBUGLOG(5, "ZSTD_initCStream_advanced : pledgedSrcSize == %u \n", (U32)pledgedSrcSize); + DEBUGLOG(5, "wlog %u \n", params.cParams.windowLog); return ZSTD_initCStream_internal(zcs, dict, dictSize, params, pledgedSrcSize); } @@ -3287,7 +3286,7 @@ size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) { if (zcs==NULL) return 0; /* support sizeof on NULL */ - return sizeof(*zcs) + ZSTD_sizeof_CCtx(zcs->cctx) + ZSTD_sizeof_CDict(zcs->cdictLocal) + zcs->outBuffSize + zcs->inBuffSize; + return sizeof(*zcs) + ZSTD_sizeof_CDict(zcs->cdictLocal) + zcs->outBuffSize + zcs->inBuffSize; } /*====== Compression ======*/ @@ -3314,8 +3313,9 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, char* const oend = ostart + *dstCapacityPtr; char* op = ostart; + DEBUGLOG(5, "ZSTD_compressStream_generic \n"); while (someMoreWork) { - switch(zcs->stage) + switch(zcs->streamStage) { case zcss_init: return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */ @@ -3323,12 +3323,14 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, /* complete inBuffer */ { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; size_t const loaded = ZSTD_limitCopy(zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend-ip); + DEBUGLOG(5, "loading %u/%u \n", (U32)loaded, (U32)toLoad); zcs->inBuffPos += loaded; ip += loaded; if ( (zcs->inBuffPos==zcs->inToCompress) || (!flush && (toLoad != loaded)) ) { someMoreWork = 0; break; /* not enough input to get a full block : stop there, wait for more */ } } /* compress current block (note : this stage cannot be stopped in the middle) */ + DEBUGLOG(5, "stream compression stage (flush==%u)\n", flush); { void* cDst; size_t cSize; size_t const iSize = zcs->inBuffPos - zcs->inToCompress; @@ -3338,29 +3340,33 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, else cDst = zcs->outBuff, oSize = zcs->outBuffSize; cSize = (flush == zsf_end) ? - ZSTD_compressEnd(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) : - ZSTD_compressContinue(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize); + ZSTD_compressEnd(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) : + ZSTD_compressContinue(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize); if (ZSTD_isError(cSize)) return cSize; + DEBUGLOG(5, "cSize = %u \n", (U32)cSize); if (flush == zsf_end) zcs->frameEnded = 1; /* prepare next block */ zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; if (zcs->inBuffTarget > zcs->inBuffSize) - zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; /* note : inBuffSize >= blockSize */ + zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; /* note : inBuffTarget == blockSize <= inBuffSize */ + assert(zcs->inBuffTarget <= zcs->inBuffSize); zcs->inToCompress = zcs->inBuffPos; if (cDst == op) { op += cSize; break; } /* no need to flush */ zcs->outBuffContentSize = cSize; zcs->outBuffFlushedSize = 0; - zcs->stage = zcss_flush; /* pass-through to flush stage */ + zcs->streamStage = zcss_flush; /* pass-through to flush stage */ } case zcss_flush: + DEBUGLOG(5, "flush stage \n"); { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; size_t const flushed = ZSTD_limitCopy(op, oend-op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush); + DEBUGLOG(5, "toFlush: %u ; flushed: %u \n", (U32)toFlush, (U32)flushed); op += flushed; zcs->outBuffFlushedSize += flushed; if (toFlush!=flushed) { someMoreWork = 0; break; } /* dst too small to store flushed data : stop there */ zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; - zcs->stage = zcss_load; + zcs->streamStage = zcss_load; break; } @@ -3419,7 +3425,8 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) BYTE* const oend = (BYTE*)(output->dst) + output->size; BYTE* op = ostart; - if (zcs->stage != zcss_final) { + DEBUGLOG(5, "ZSTD_endStream (dstCapacity : %u) \n", (U32)(oend-op)); + if (zcs->streamStage != zcss_final) { /* flush whatever remains */ size_t srcSize = 0; size_t sizeWritten = output->size - output->pos; @@ -3429,13 +3436,14 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) op += sizeWritten; if (remainingToFlush) { output->pos += sizeWritten; - return remainingToFlush + ZSTD_BLOCKHEADERSIZE /* final empty block */ + (zcs->checksum * 4); + return remainingToFlush + ZSTD_BLOCKHEADERSIZE /* final empty block */ + + ((zcs->params.fParams.checksumFlag > 0) * 4) /* optional 32-bits checksum */; } /* create epilogue */ - zcs->stage = zcss_final; + zcs->streamStage = zcss_final; zcs->outBuffContentSize = !notEnded ? 0 : /* write epilogue, including final empty block, into outBuff */ - ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 0); + ZSTD_compressEnd(zcs, zcs->outBuff, zcs->outBuffSize, NULL, 0); if (ZSTD_isError(zcs->outBuffContentSize)) return zcs->outBuffContentSize; } @@ -3445,7 +3453,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) op += flushed; zcs->outBuffFlushedSize += flushed; output->pos += op-ostart; - if (toFlush==flushed) zcs->stage = zcss_init; /* end reached */ + if (toFlush==flushed) zcs->streamStage = zcss_init; /* end reached */ return toFlush - flushed; } } diff --git a/lib/zstd.h b/lib/zstd.h index f8050c13..3179c8c7 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -281,7 +281,8 @@ typedef struct ZSTD_outBuffer_s { * * *******************************************************************/ -typedef struct ZSTD_CStream_s ZSTD_CStream; +typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are effectively same object */ + /* Continue due distinghish them for compatibility with versions <= v1.2.0 */ /*===== ZSTD_CStream management functions =====*/ ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 0e09e185..6c210f2f 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -53,13 +53,15 @@ static const U32 prime32 = 2654435761U; * Display Macros **************************************/ #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } +#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { \ + DISPLAY(__VA_ARGS__); \ + if (g_displayLevel>=4) fflush(stderr); } static U32 g_displayLevel = 2; #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ if ((FUZ_GetClockSpan(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \ { g_displayClock = clock(); DISPLAY(__VA_ARGS__); \ - if (g_displayLevel>=4) fflush(stderr); } } + if (g_displayLevel>=4) fflush(stderr); } } static const clock_t g_refreshRate = CLOCKS_PER_SEC / 6; static clock_t g_displayClock = 0; @@ -155,7 +157,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo void* decodedBuffer = malloc(decodedBufferSize); size_t cSize; int testResult = 0; - U32 testNb=0; + U32 testNb = 1; ZSTD_CStream* zc = ZSTD_createCStream_advanced(customMem); ZSTD_DStream* zd = ZSTD_createDStream_advanced(customMem); ZSTD_inBuffer inBuff, inBuff2; @@ -344,6 +346,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo if (zc==NULL) goto _output_error; /* memory allocation issue */ /* use 1 */ { size_t const inSize = 513; + DISPLAYLEVEL(5, "use1 "); ZSTD_initCStream_advanced(zc, NULL, 0, ZSTD_getParams(19, inSize, 0), inSize); /* needs btopt + search3 to trigger hashLog3 */ inBuff.src = CNBuffer; inBuff.size = inSize; @@ -351,14 +354,17 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo outBuff.dst = (char*)(compressedBuffer)+cSize; outBuff.size = ZSTD_compressBound(inSize); outBuff.pos = 0; + DISPLAYLEVEL(5, "compress1 "); { size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff); if (ZSTD_isError(r)) goto _output_error; } if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ + DISPLAYLEVEL(5, "end1 "); { size_t const r = ZSTD_endStream(zc, &outBuff); if (r != 0) goto _output_error; } /* error, or some data not flushed */ } /* use 2 */ { size_t const inSize = 1025; /* will not continue, because tables auto-adjust and are therefore different size */ + DISPLAYLEVEL(5, "use2 "); ZSTD_initCStream_advanced(zc, NULL, 0, ZSTD_getParams(19, inSize, 0), inSize); /* needs btopt + search3 to trigger hashLog3 */ inBuff.src = CNBuffer; inBuff.size = inSize; @@ -366,9 +372,11 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo outBuff.dst = (char*)(compressedBuffer)+cSize; outBuff.size = ZSTD_compressBound(inSize); outBuff.pos = 0; + DISPLAYLEVEL(5, "compress2 "); { size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff); if (ZSTD_isError(r)) goto _output_error; } if (inBuff.pos != inBuff.size) goto _output_error; /* entire input should be consumed */ + DISPLAYLEVEL(5, "end2 "); { size_t const r = ZSTD_endStream(zc, &outBuff); if (r != 0) goto _output_error; } /* error, or some data not flushed */ } @@ -770,7 +778,9 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres outBuff.size = outBuff.pos + adjustedDstSize; remainingToFlush = ZSTD_endStream(zc, &outBuff); CHECK (ZSTD_isError(remainingToFlush), "flush error : %s", ZSTD_getErrorName(remainingToFlush)); - CHECK (enoughDstSize && remainingToFlush, "ZSTD_endStream() not fully flushed (%u remaining), but enough space available", (U32)remainingToFlush); + CHECK (enoughDstSize && remainingToFlush, + "ZSTD_endStream() not fully flushed (%u remaining), but enough space available (%u)", + (U32)remainingToFlush, (U32)adjustedDstSize); } } crcOrig = XXH64_digest(&xxhState); cSize = outBuff.pos; From 791d74427925351c776de1e94ea701a41e894e20 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 May 2017 16:17:30 -0700 Subject: [PATCH 02/15] Updated ZSTD_sizeof_CCtx() can now contain buffers if object used as CStream. ZSTD_sizeof_CStream() is now just a thin wrapper of ZSTD_sizeof_CCtx(). --- lib/compress/zstd_compress.c | 7 ++++--- lib/zstd.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d7f90dff..d55ea505 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -165,7 +165,9 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx) { if (cctx==NULL) return 0; /* support sizeof on NULL */ - return sizeof(*cctx) + cctx->workSpaceSize; + return sizeof(*cctx) + cctx->workSpaceSize + + ZSTD_sizeof_CDict(cctx->cdictLocal) + + cctx->outBuffSize + cctx->inBuffSize; } size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value) @@ -3285,8 +3287,7 @@ size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) { - if (zcs==NULL) return 0; /* support sizeof on NULL */ - return sizeof(*zcs) + ZSTD_sizeof_CDict(zcs->cdictLocal) + zcs->outBuffSize + zcs->inBuffSize; + return ZSTD_sizeof_CCtx(zcs); /* same object */ } /*====== Compression ======*/ diff --git a/lib/zstd.h b/lib/zstd.h index 3179c8c7..bb447ee1 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -468,7 +468,7 @@ ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); /*! ZSTD_sizeofCCtx() : - * Gives the amount of memory used by a given ZSTD_CCtx */ + * amount of used memory is variable, depending primarily on compression level */ ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); typedef enum { @@ -597,7 +597,7 @@ 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); -ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); /**< size of CStream is variable, depending primarily on compression level */ +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_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, From fc5145955a0c53a9157579ce9dc2abcadeff5e32 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 May 2017 17:07:59 -0700 Subject: [PATCH 03/15] updated ZSTD_estimateCCtxSize() added a parameter streaming, to estimate memory allocation size when the CCtx is used for streaming (CStream). Note : this function is not able to estimate memory cost of a potential internal CDict which can only happen when starting with ZSTD_initCStream_usingDict() --- doc/zstd_manual.html | 6 +++--- lib/compress/zstd_compress.c | 23 ++++++++++++++--------- lib/zstd.h | 8 +++++--- tests/paramgrill.c | 4 ++-- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 8cac4294..d7091545 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -372,7 +372,7 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v

Advanced compression functions


 
-
size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams);
+
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


@@ -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; v
 

Advanced 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; v

Create 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


@@ -476,6 +483,11 @@ 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


@@ -509,7 +521,7 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v

Advanced Streaming compression functions

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 
Date: Mon, 8 May 2017 17:52:46 -0700
Subject: [PATCH 06/15] bumped version number

---
 lib/zstd.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/zstd.h b/lib/zstd.h
index 270943b3..c3a8a52a 100644
--- a/lib/zstd.h
+++ b/lib/zstd.h
@@ -55,7 +55,7 @@ extern "C" {
 
 /*------   Version   ------*/
 #define ZSTD_VERSION_MAJOR    1
-#define ZSTD_VERSION_MINOR    2
+#define ZSTD_VERSION_MINOR    3
 #define ZSTD_VERSION_RELEASE  0
 
 #define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE

From fa8dadb294cbda271c3c0b645a5adabd208d998b Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Mon, 8 May 2017 18:24:16 -0700
Subject: [PATCH 07/15] separated ZSTD_estimateCStreamSize() from
 ZSTD_estimateCCtxSize()

for clarity
---
 doc/zstd_manual.html         | 16 +++++++++-------
 lib/compress/zstd_compress.c | 22 ++++++++++++++--------
 lib/zstd.h                   | 12 +++++++-----
 tests/paramgrill.c           |  4 ++--
 4 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
index 9cfb6710..a5612c92 100644
--- a/doc/zstd_manual.html
+++ b/doc/zstd_manual.html
@@ -1,10 +1,10 @@
 
 
 
-zstd 1.2.0 Manual
+zstd 1.3.0 Manual
 
 
-

zstd 1.2.0 Manual

+

zstd 1.3.0 Manual


Contents

    @@ -376,11 +376,8 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v

    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; 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 */
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 Collet 
Date: 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; v
     

    Create 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; v
     

    Create 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 Collet 
    Date: 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 Collet 
    Date: 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;
    +

    Custom memory allocation functions

    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;
    -

    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);
    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 
    Date: Tue, 9 May 2017 16:53:09 -0700
    Subject: [PATCH 11/15] fixed symbols test
    
    ---
     tests/symbols.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/tests/symbols.c b/tests/symbols.c
    index 7dacfc05..ade3aa02 100644
    --- a/tests/symbols.c
    +++ b/tests/symbols.c
    @@ -88,7 +88,7 @@ static const void *symbols[] = {
       &ZSTD_copyCCtx,
       &ZSTD_compressContinue,
       &ZSTD_compressEnd,
    -  &ZSTD_getFrameParams,
    +  &ZSTD_getFrameHeader,
       &ZSTD_decompressBegin,
       &ZSTD_decompressBegin_usingDict,
       &ZSTD_copyDCtx,
    
    From 6fb2f241322ec6f66ce53132f4226bed20f5f1bc Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Wed, 10 May 2017 11:06:06 -0700
    Subject: [PATCH 12/15] shortened ZSTD_createCStream_Advanced()
    
    https://github.com/facebook/zstd/pull/689#discussion_r115637613
    ---
     lib/compress/zstd_compress.c | 12 ++----------
     1 file changed, 2 insertions(+), 10 deletions(-)
    
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 37590fca..b1d799cd 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -3136,16 +3136,8 @@ ZSTD_CStream* ZSTD_createCStream(void)
     
     ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
     {
    -    ZSTD_CStream* zcs;
    -
    -    if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
    -    if (!customMem.customAlloc || !customMem.customFree) return NULL;
    -
    -    zcs = (ZSTD_CStream*)ZSTD_malloc(sizeof(ZSTD_CStream), customMem);
    -    if (zcs==NULL) return NULL;
    -    memset(zcs, 0, sizeof(ZSTD_CStream));
    -    memcpy(&zcs->customMem, &customMem, sizeof(ZSTD_customMem));
    -    return zcs;
    +    /* CStream and CCtx are now same object */
    +    return ZSTD_createCCtx_advanced(customMem);
     }
     
     size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
    
    From 669346fe8b015c26586c8e3ca75751fffd161bb0 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Wed, 10 May 2017 11:08:00 -0700
    Subject: [PATCH 13/15] fixed ZSTD_estimateCStreamSize()
    
    https://github.com/facebook/zstd/pull/689#discussion_r115637721
    ---
     lib/compress/zstd_compress.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index b1d799cd..848472ec 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -3153,7 +3153,7 @@ size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams)
         size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
         size_t const streamingSize = inBuffSize + outBuffSize;
     
    -    return sizeof(ZSTD_CCtx) + CCtxSize + streamingSize;
    +    return CCtxSize + streamingSize;
     }
     
     
    
    From cef02d9317743fba04673fa2da038670cd07f8b6 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Wed, 10 May 2017 11:14:08 -0700
    Subject: [PATCH 14/15] changed variable name, for clarity
    
    fhiPtr -> zfhPtr
    https://github.com/facebook/zstd/pull/689#discussion_r115638676
    ---
     doc/zstd_manual.html             |  2 +-
     lib/decompress/zstd_decompress.c | 18 +++++++++---------
     lib/zstd.h                       |  2 +-
     3 files changed, 11 insertions(+), 11 deletions(-)
    
    diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
    index 9cfb1b68..cb376741 100644
    --- a/doc/zstd_manual.html
    +++ b/doc/zstd_manual.html
    @@ -646,7 +646,7 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned lo
       It also returns Frame Size as fparamsPtr->frameContentSize.
     
    -

    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 */
    +

    Buffer-less streaming decompression functions

    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 
    Date: Wed, 10 May 2017 11:30:19 -0700
    Subject: [PATCH 15/15] added test for ZSTD_estimateCStreamSize()
    
    ---
     tests/zstreamtest.c | 26 ++++++++++++++++++--------
     1 file changed, 18 insertions(+), 8 deletions(-)
    
    diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c
    index 6ce309c5..5c166bfb 100644
    --- a/tests/zstreamtest.c
    +++ b/tests/zstreamtest.c
    @@ -163,6 +163,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
         ZSTD_inBuffer  inBuff, inBuff2;
         ZSTD_outBuffer outBuff;
         buffer_t dictionary = g_nullBuffer;
    +    size_t const dictSize = 128 KB;
         unsigned dictID = 0;
     
         /* Create compressible test buffer */
    @@ -188,7 +189,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
     
         /* Basic compression test */
         DISPLAYLEVEL(3, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
    -    ZSTD_initCStream_usingDict(zc, CNBuffer, 128 KB, 1);
    +    ZSTD_initCStream_usingDict(zc, CNBuffer, dictSize, 1);
         outBuff.dst = (char*)(compressedBuffer)+cSize;
         outBuff.size = compressedBufferSize;
         outBuff.pos = 0;
    @@ -203,7 +204,16 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
         cSize += outBuff.pos;
         DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
     
    -    DISPLAYLEVEL(3, "test%3i : check CStream size : ", testNb++);
    +    /* context size functions */
    +    DISPLAYLEVEL(3, "test%3i : estimate CStream size : ", testNb++);
    +    {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictSize);
    +        size_t const s = ZSTD_estimateCStreamSize(cParams)
    +                       + ZSTD_estimateCDictSize(cParams, dictSize);  /* uses ZSTD_initCStream_usingDict() */
    +            if (ZSTD_isError(s)) goto _output_error;
    +            DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
    +    }
    +
    +    DISPLAYLEVEL(3, "test%3i : check actual CStream size : ", testNb++);
         { size_t const s = ZSTD_sizeof_CStream(zc);
           if (ZSTD_isError(s)) goto _output_error;
           DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
    @@ -221,7 +231,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
     
         /* skippable frame test */
         DISPLAYLEVEL(3, "test%3i : decompress skippable frame : ", testNb++);
    -    ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
    +    ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
         inBuff.src = compressedBuffer;
         inBuff.size = cSize;
         inBuff.pos = 0;
    @@ -236,7 +246,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
         /* Basic decompression test */
         inBuff2 = inBuff;
         DISPLAYLEVEL(3, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
    -    ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
    +    ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
         { size_t const r = ZSTD_setDStreamParameter(zd, DStream_p_maxWindowSize, 1000000000);  /* large limit */
           if (ZSTD_isError(r)) goto _output_error; }
         { size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff);
    @@ -270,7 +280,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
             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() */
    +                           + ZSTD_estimateDDictSize(dictSize);  /* uses ZSTD_initDStream_usingDict() */
                 if (ZSTD_isError(s)) goto _output_error;
                 DISPLAYLEVEL(3, "OK (%u bytes) \n", (U32)s);
         }   }
    @@ -285,7 +295,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
         DISPLAYLEVEL(3, "test%3i : decompress byte-by-byte : ", testNb++);
         {   /* skippable frame */
             size_t r = 1;
    -        ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
    +        ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
             inBuff.src = compressedBuffer;
             outBuff.dst = decodedBuffer;
             inBuff.pos = 0;
    @@ -297,7 +307,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
                 if (ZSTD_isError(r)) goto _output_error;
             }
             /* normal frame */
    -        ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
    +        ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
             r=1;
             while (r) {
                 inBuff.size = inBuff.pos + 1;
    @@ -456,7 +466,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
     
         /* Memory restriction */
         DISPLAYLEVEL(3, "test%3i : maxWindowSize < frame requirement : ", testNb++);
    -    ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
    +    ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);
         { size_t const r = ZSTD_setDStreamParameter(zd, DStream_p_maxWindowSize, 1000);  /* too small limit */
           if (ZSTD_isError(r)) goto _output_error; }
         inBuff.src = compressedBuffer;