diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 590e92c8e..7a5043284 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -72,9 +72,11 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_calloc(sizeof(ZSTD_CCtx), customMem); if (!cctx) return NULL; cctx->customMem = customMem; - cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; - cctx->requestedParams.fParams.contentSizeFlag = 1; cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); + { size_t const err = ZSTD_CCtx_resetParameters(cctx); + assert(!ZSTD_isError(err)); + (void)err; + } return cctx; } } @@ -657,18 +659,19 @@ size_t ZSTD_CCtx_refPrefix_advanced( return 0; } -static void ZSTD_startNewCompression(ZSTD_CCtx* cctx) +/*! ZSTD_CCtx_reset() : + * Also dumps dictionary */ +void ZSTD_CCtx_reset(ZSTD_CCtx* cctx) { cctx->streamStage = zcss_init; cctx->pledgedSrcSizePlusOne = 0; } -/*! ZSTD_CCtx_reset() : - * Also dumps dictionary */ -void ZSTD_CCtx_reset(ZSTD_CCtx* cctx) +size_t ZSTD_CCtx_resetParameters(ZSTD_CCtx* cctx) { - ZSTD_startNewCompression(cctx); + if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); cctx->cdict = NULL; + return ZSTD_CCtxParams_reset(&cctx->requestedParams); } /** ZSTD_checkCParams() : @@ -3181,7 +3184,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, ip = iend; op += cSize; zcs->frameEnded = 1; - ZSTD_startNewCompression(zcs); + ZSTD_CCtx_reset(zcs); someMoreWork = 0; break; } /* complete loading into inBuffer */ @@ -3234,7 +3237,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, if (zcs->frameEnded) { DEBUGLOG(5, "Frame completed directly in outBuffer"); someMoreWork = 0; - ZSTD_startNewCompression(zcs); + ZSTD_CCtx_reset(zcs); } break; } @@ -3262,7 +3265,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, if (zcs->frameEnded) { DEBUGLOG(5, "Frame completed on flush"); someMoreWork = 0; - ZSTD_startNewCompression(zcs); + ZSTD_CCtx_reset(zcs); break; } zcs->streamStage = zcss_load; @@ -3359,7 +3362,7 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); if ( ZSTD_isError(flushMin) || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ - ZSTD_startNewCompression(cctx); + ZSTD_CCtx_reset(cctx); } return flushMin; } } diff --git a/lib/zstd.h b/lib/zstd.h index 913c599bb..387586c1e 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1141,12 +1141,19 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre * Return a CCtx to clean state. * Useful after an error, or to interrupt an ongoing compression job and start a new one. * Any internal data not yet flushed is cancelled. - * Dictionary (if any) is dropped. - * All parameters are back to default values (compression level is ZSTD_CLEVEL_DEFAULT). - * After a reset, all compression parameters can be modified again. + * The parameters and dictionary are kept unchanged, to reset them use ZSTD_CCtx_resetParameters(). */ ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx); +/*! ZSTD_CCtx_resetParameters() : + * All parameters are back to default values (compression level is ZSTD_CLEVEL_DEFAULT). + * Dictionary (if any) is dropped. + * Resetting parameters is only possible during frame initialization (before starting compression). + * To reset the context use ZSTD_CCtx_reset(). + * @return 0 or an error code (which can be checked with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtx_resetParameters(ZSTD_CCtx* cctx); + typedef enum { diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 33d27cda7..9b49ddd08 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -433,6 +433,12 @@ static int basicUnitTests(U32 seed, double compressibility) CHECK_EQ(value, 7); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); CHECK_EQ(value, ZSTD_HASHLOG_MIN); + /* Reset the parameters */ + ZSTD_CCtx_resetParameters(cctx); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_compressionLevel, &value)); + CHECK_EQ(value, 3); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_p_hashLog, &value)); + CHECK_EQ(value, 0); ZSTD_freeCCtx(cctx); }