From 22572d68bf62b740f003287605741310ae5efe13 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 29 Jan 2025 11:49:59 -0800 Subject: [PATCH 01/36] Separate Public and Private CParam Structs Even though the `ZSTD_compressionParameters` struct is part of the unstable API, and therefore we are allowed to modify it, it seems likely that to actually do so would cause widespread chaos and bloodshed. So we are strongly incentivized to avoid changing it. We would, however, like to modify the CParams that are actually passed around internally. In particular, we want to be able to configure non-power-of-2 window sizes. So we need something more expressive than an integral window log. And we want this new field to be next to the window log, rather than hanging out in the CCtxParams, which are not passed to the block compressors. So, in order to support that, this commit: 1. Introduces a new struct, the `ZSTD_CParams`, that (for the moment) mirrors the definition of the public `ZSTD_compressionParameters` struct. 2. Codemods all internal use and storage of `cparams` internally to use the new struct definition. (The exception to this is the `ZSTD_parameters` struct, which is a public definition but is also passed around internally sometimes.) 3. Adds translation functions to convert the public and private struct defs to each other. 4. Uses those translation functions at the user API boundary (and when handling `ZSTD_parameters`). --- lib/compress/clevels.h | 4 +- lib/compress/zstd_compress.c | 287 ++++++++++++++++---------- lib/compress/zstd_compress_internal.h | 41 +++- lib/compress/zstd_double_fast.c | 12 +- lib/compress/zstd_fast.c | 12 +- lib/compress/zstd_lazy.c | 16 +- lib/compress/zstd_ldm.c | 4 +- lib/compress/zstd_ldm.h | 2 +- lib/compress/zstd_opt.c | 8 +- lib/compress/zstdmt_compress.c | 13 +- 10 files changed, 254 insertions(+), 145 deletions(-) diff --git a/lib/compress/clevels.h b/lib/compress/clevels.h index c18da465f32..4c8d12fabfe 100644 --- a/lib/compress/clevels.h +++ b/lib/compress/clevels.h @@ -11,7 +11,7 @@ #ifndef ZSTD_CLEVELS_H #define ZSTD_CLEVELS_H -#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */ +#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_CParams */ #include "../zstd.h" /*-===== Pre-defined compression levels =====-*/ @@ -22,7 +22,7 @@ __attribute__((__unused__)) #endif -static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { +static const ZSTD_CParams ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { { /* "default" - for any srcSize > 256 KB */ /* W, C, H, S, L, TL, strat */ { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d928b1d3ee3..b32d5c4cf6d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -236,7 +236,7 @@ static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_Para /* Returns row matchfinder usage given an initial mode and cParams */ static ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode, - const ZSTD_compressionParameters* const cParams) { + const ZSTD_CParams* const cParams) { if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */ mode = ZSTD_ps_disable; if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode; @@ -246,7 +246,7 @@ static ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode /* Returns block splitter usage (generally speaking, when using slower/stronger compression modes) */ static ZSTD_ParamSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_ParamSwitch_e mode, - const ZSTD_compressionParameters* const cParams) { + const ZSTD_CParams* const cParams) { if (mode != ZSTD_ps_auto) return mode; return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17) ? ZSTD_ps_enable : ZSTD_ps_disable; } @@ -266,8 +266,9 @@ static int ZSTD_allocateChainTable(const ZSTD_strategy strategy, * enable long distance matching (wlog >= 27, strategy >= btopt). * Returns ZSTD_ps_disable otherwise. */ -static ZSTD_ParamSwitch_e ZSTD_resolveEnableLdm(ZSTD_ParamSwitch_e mode, - const ZSTD_compressionParameters* const cParams) { +static ZSTD_ParamSwitch_e ZSTD_resolveEnableLdm( + ZSTD_ParamSwitch_e mode, + const ZSTD_CParams* const cParams) { if (mode != ZSTD_ps_auto) return mode; return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable; } @@ -296,12 +297,12 @@ static ZSTD_ParamSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_ParamSwitch_e v /* Returns 1 if compression parameters are such that CDict hashtable and chaintable indices are tagged. * If so, the tags need to be removed in ZSTD_resetCCtx_byCopyingCDict. */ -static int ZSTD_CDictIndicesAreTagged(const ZSTD_compressionParameters* const cParams) { +static int ZSTD_CDictIndicesAreTagged(const ZSTD_CParams* const cParams) { return cParams->strategy == ZSTD_fast || cParams->strategy == ZSTD_dfast; } static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( - ZSTD_compressionParameters cParams) + ZSTD_CParams cParams) { ZSTD_CCtx_params cctxParams; /* should not matter, as all cParams are presumed properly defined */ @@ -321,7 +322,7 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( cctxParams.maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams.maxBlockSize); cctxParams.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams.searchForExternalRepcodes, cctxParams.compressionLevel); - assert(!ZSTD_checkCParams(cParams)); + assert(!ZSTD_checkCParams_internal(cParams)); return cctxParams; } @@ -376,15 +377,15 @@ ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, { assert(!ZSTD_checkCParams(params->cParams)); ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); - cctxParams->cParams = params->cParams; + cctxParams->cParams = ZSTD_getCParamsFromPublicCParams(params->cParams); cctxParams->fParams = params->fParams; /* Should not matter, as all cParams are presumed properly defined. * But, set it for tracing anyway. */ cctxParams->compressionLevel = compressionLevel; - cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, ¶ms->cParams); - cctxParams->postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->postBlockSplitter, ¶ms->cParams); - cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, ¶ms->cParams); + cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, &cctxParams->cParams); + cctxParams->postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->postBlockSplitter, &cctxParams->cParams); + cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, &cctxParams->cParams); cctxParams->validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams->validateSequences); cctxParams->maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams->maxBlockSize); cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, compressionLevel); @@ -408,7 +409,7 @@ static void ZSTD_CCtxParams_setZstdParams( ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) { assert(!ZSTD_checkCParams(params->cParams)); - cctxParams->cParams = params->cParams; + cctxParams->cParams = ZSTD_getCParamsFromPublicCParams(params->cParams); cctxParams->fParams = params->fParams; /* Should not matter, as all cParams are presumed properly defined. * But, set it for tracing anyway. @@ -1236,13 +1237,13 @@ size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSr return 0; } -static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams( +static ZSTD_CParams ZSTD_dedicatedDictSearch_getCParams( int const compressionLevel, size_t const dictSize); static int ZSTD_dedicatedDictSearch_isSupported( - const ZSTD_compressionParameters* cParams); + const ZSTD_CParams* cParams); static void ZSTD_dedicatedDictSearch_revertCParams( - ZSTD_compressionParameters* cParams); + ZSTD_CParams* cParams); /** * Initializes the local dictionary using requested parameters. @@ -1381,27 +1382,31 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) return 0; } +size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams) +{ + BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); + BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); + BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); + BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); + BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); + BOUNDCHECK(ZSTD_c_targetLength, (int)cParams.targetLength); + BOUNDCHECK(ZSTD_c_strategy, (int)cParams.strategy); + return 0; +} /** ZSTD_checkCParams() : control CParam values remain within authorized range. @return : 0, or an error code if one value is beyond authorized range */ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) { - BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); - BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); - BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); - BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); - BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); - BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength); - BOUNDCHECK(ZSTD_c_strategy, (int)cParams.strategy); - return 0; + return ZSTD_checkCParams_internal(ZSTD_getCParamsFromPublicCParams(cParams)); } /** ZSTD_clampCParams() : * make CParam values within valid range. * @return : valid CParams */ -static ZSTD_compressionParameters -ZSTD_clampCParams(ZSTD_compressionParameters cParams) +static ZSTD_CParams +ZSTD_clampCParams(ZSTD_CParams cParams) { # define CLAMP_TYPE(cParam, val, type) \ do { \ @@ -1410,13 +1415,13 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams) else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \ } while (0) # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) - CLAMP(ZSTD_c_windowLog, cParams.windowLog); - CLAMP(ZSTD_c_chainLog, cParams.chainLog); - CLAMP(ZSTD_c_hashLog, cParams.hashLog); - CLAMP(ZSTD_c_searchLog, cParams.searchLog); - CLAMP(ZSTD_c_minMatch, cParams.minMatch); - CLAMP(ZSTD_c_targetLength,cParams.targetLength); - CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy); + CLAMP(ZSTD_c_windowLog, cParams.windowLog); + CLAMP(ZSTD_c_chainLog, cParams.chainLog); + CLAMP(ZSTD_c_hashLog, cParams.hashLog); + CLAMP(ZSTD_c_searchLog, cParams.searchLog); + CLAMP(ZSTD_c_minMatch, cParams.minMatch); + CLAMP(ZSTD_c_targetLength, cParams.targetLength); + CLAMP_TYPE(ZSTD_c_strategy, cParams.strategy, ZSTD_strategy); return cParams; } @@ -1469,8 +1474,8 @@ static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize) * `mode` is the mode for parameter adjustment. See docs for `ZSTD_CParamMode_e`. * note : `srcSize==0` means 0! * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */ -static ZSTD_compressionParameters -ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, +static ZSTD_CParams +ZSTD_adjustCParams_internal(ZSTD_CParams cPar, unsigned long long srcSize, size_t dictSize, ZSTD_CParamMode_e mode, @@ -1478,7 +1483,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, { const U64 minSrcSize = 513; /* (1<<9) + 1 */ const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); - assert(ZSTD_checkCParams(cPar)==0); + assert(ZSTD_checkCParams_internal(cPar)==0); /* Cascade the selected strategy down to the next-highest one built into * this binary. */ @@ -1613,17 +1618,45 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize) { - cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */ + ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(cPar); + cParams = ZSTD_clampCParams(cParams); /* resulting cPar is necessarily valid (all parameters within range) */ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto); + cParams = ZSTD_adjustCParams_internal(cParams, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto); + return ZSTD_getPublicCParamsFromCParams(cParams); +} + +ZSTD_CParams ZSTD_getCParamsFromPublicCParams( + ZSTD_compressionParameters cParams) { + return (ZSTD_CParams){ + cParams.windowLog, + cParams.chainLog, + cParams.hashLog, + cParams.searchLog, + cParams.minMatch, + cParams.targetLength, + cParams.strategy + }; } -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); +ZSTD_compressionParameters ZSTD_getPublicCParamsFromCParams( + ZSTD_CParams cParams) { + return (ZSTD_compressionParameters){ + cParams.windowLog, + cParams.chainLog, + cParams.hashLog, + cParams.searchLog, + cParams.minMatch, + cParams.targetLength, + cParams.strategy + }; +} + +static ZSTD_CParams ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); static void ZSTD_overrideCParams( - ZSTD_compressionParameters* cParams, - const ZSTD_compressionParameters* overrides) + ZSTD_CParams* cParams, + const ZSTD_CParams* overrides) { if (overrides->windowLog) cParams->windowLog = overrides->windowLog; if (overrides->hashLog) cParams->hashLog = overrides->hashLog; @@ -1634,10 +1667,10 @@ static void ZSTD_overrideCParams( if (overrides->strategy) cParams->strategy = overrides->strategy; } -ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( +ZSTD_CParams ZSTD_getCParamsFromCCtxParams( const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) { - ZSTD_compressionParameters cParams; + ZSTD_CParams cParams; if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { assert(CCtxParams->srcSizeHint>=0); srcSizeHint = (U64)CCtxParams->srcSizeHint; @@ -1645,13 +1678,13 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; ZSTD_overrideCParams(&cParams, &CCtxParams->cParams); - assert(!ZSTD_checkCParams(cParams)); + assert(!ZSTD_checkCParams_internal(cParams)); /* srcSizeHint == 0 means 0 */ return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode, CCtxParams->useRowMatchFinder); } static size_t -ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, +ZSTD_sizeof_matchState(const ZSTD_CParams* const cParams, const ZSTD_ParamSwitch_e useRowMatchFinder, const int enableDedicatedDictSearch, const U32 forCCtx) @@ -1700,7 +1733,7 @@ static size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useSequence } static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( - const ZSTD_compressionParameters* cParams, + const ZSTD_CParams* cParams, const ldmParams_t* ldmParams, const int isStatic, const ZSTD_ParamSwitch_e useRowMatchFinder, @@ -1753,7 +1786,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) { - ZSTD_compressionParameters const cParams = + ZSTD_CParams const cParams = ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, &cParams); @@ -1766,7 +1799,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize); } -size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) +static size_t ZSTD_estimateCCtxSize_usingCParams_internal(ZSTD_CParams cParams) { ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { @@ -1783,6 +1816,12 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) } } +size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters publicParams) +{ + ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); + return ZSTD_estimateCCtxSize_usingCParams_internal(cParams); +} + static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) { int tier = 0; @@ -1790,8 +1829,8 @@ static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN}; for (; tier < 4; ++tier) { /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */ - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); - largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize); + ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); + largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams_internal(cParams), largestSize); } return largestSize; } @@ -1811,7 +1850,7 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel) size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) { RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); - { ZSTD_compressionParameters const cParams = + { ZSTD_CParams const cParams = ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), (size_t)1 << cParams.windowLog); size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered) @@ -1828,7 +1867,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) } } -size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) +static size_t ZSTD_estimateCStreamSize_usingCParams_internal(ZSTD_CParams cParams) { ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { @@ -1845,10 +1884,16 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) } } +size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters publicParams) +{ + ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); + return ZSTD_estimateCStreamSize_usingCParams_internal(cParams); +} + static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); - return ZSTD_estimateCStreamSize_usingCParams(cParams); + ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + return ZSTD_estimateCStreamSize_usingCParams_internal(cParams); } size_t ZSTD_estimateCStreamSize(int compressionLevel) @@ -1901,8 +1946,8 @@ size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx) return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */ } -static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1, - ZSTD_compressionParameters cParams2) +static void ZSTD_assertEqualCParams(ZSTD_CParams cParams1, + ZSTD_CParams cParams2) { (void)cParams1; (void)cParams2; @@ -1984,7 +2029,7 @@ static void ZSTD_advanceHashSalt(ZSTD_MatchState_t* ms) { static size_t ZSTD_reset_matchState(ZSTD_MatchState_t* ms, ZSTD_cwksp* ws, - const ZSTD_compressionParameters* cParams, + const ZSTD_CParams* cParams, const ZSTD_ParamSwitch_e useRowMatchFinder, const ZSTD_compResetPolicy_e crp, const ZSTD_indexResetPolicy_e forceResetIndex, @@ -2107,7 +2152,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, ZSTD_cwksp* const ws = &zc->workspace; DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d useBlockSplitter=%d", (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->postBlockSplitter); - assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); + assert(!ZSTD_isError(ZSTD_checkCParams_internal(params->cParams))); zc->isFirstBlock = 1; @@ -2331,7 +2376,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, DEBUGLOG(4, "ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu", (unsigned long long)pledgedSrcSize); { - ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams; + ZSTD_CParams adjusted_cdict_cParams = cdict->matchState.cParams; unsigned const windowLog = params.cParams.windowLog; assert(windowLog != 0); /* Resize working context table params for input only, since the dict @@ -2384,7 +2429,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, } static void ZSTD_copyCDictTableIntoCCtx(U32* dst, U32 const* src, size_t tableSize, - ZSTD_compressionParameters const* cParams) { + ZSTD_CParams const* cParams) { if (ZSTD_CDictIndicesAreTagged(cParams)){ /* Remove tags from the CDict table if they are present. * See docs on "short cache" in zstd_compress_internal.h for context. */ @@ -2405,7 +2450,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { - const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams; + const ZSTD_CParams *cdict_cParams = &cdict->matchState.cParams; assert(!cdict->matchState.dedicatedDictSearch); DEBUGLOG(4, "ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu", @@ -3234,7 +3279,7 @@ static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seq /** * Function to validate sequences produced by a block compressor. */ -static void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_compressionParameters* cParams) +static void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_CParams* cParams) { #if DEBUGLEVEL >= 1 const SeqDef* seq = seqStore->sequencesStart; @@ -4868,8 +4913,8 @@ size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, static size_t ZSTD_getBlockSize_deprecated(const ZSTD_CCtx* cctx) { - ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams; - assert(!ZSTD_checkCParams(cParams)); + ZSTD_CParams const cParams = cctx->appliedParams.cParams; + assert(!ZSTD_checkCParams_internal(cParams)); return MIN(cctx->appliedParams.maxBlockSize, (size_t)1 << cParams.windowLog); } @@ -5249,7 +5294,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, #endif DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog); /* params are supposed to be fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); + assert(!ZSTD_isError(ZSTD_checkCParams_internal(params->cParams))); assert(!((dict) && (cdict))); /* either dict or cdict, not both */ if ( (cdict) && (cdict->dictContentSize > 0) @@ -5292,7 +5337,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, { DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog); /* compression parameters verification and optimization */ - FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams_internal(params->cParams) , ""); return ZSTD_compressBegin_internal(cctx, dict, dictSize, dictContentType, dtlm, cdict, @@ -5516,10 +5561,8 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, /* ===== Dictionary API ===== */ -/*! ZSTD_estimateCDictSize_advanced() : - * Estimate amount of memory that will be needed to create a dictionary with following arguments */ -size_t ZSTD_estimateCDictSize_advanced( - size_t dictSize, ZSTD_compressionParameters cParams, +static size_t ZSTD_estimateCDictSize_internal( + size_t dictSize, ZSTD_CParams cParams, ZSTD_dictLoadMethod_e dictLoadMethod) { DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict)); @@ -5533,10 +5576,20 @@ size_t ZSTD_estimateCDictSize_advanced( : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *)))); } +/*! ZSTD_estimateCDictSize_advanced() : + * Estimate amount of memory that will be needed to create a dictionary with following arguments */ +size_t ZSTD_estimateCDictSize_advanced( + size_t dictSize, ZSTD_compressionParameters publicParams, + ZSTD_dictLoadMethod_e dictLoadMethod) +{ + ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); + return ZSTD_estimateCDictSize_internal(dictSize, cParams, dictLoadMethod); +} + size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); + ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + return ZSTD_estimateCDictSize_internal(dictSize, cParams, ZSTD_dlm_byCopy); } size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) @@ -5556,7 +5609,7 @@ static size_t ZSTD_initCDict_internal( ZSTD_CCtx_params params) { DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType); - assert(!ZSTD_checkCParams(params.cParams)); + assert(!ZSTD_checkCParams_internal(params.cParams)); cdict->matchState.cParams = params.cParams; cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch; if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) { @@ -5604,7 +5657,7 @@ static size_t ZSTD_initCDict_internal( static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_compressionParameters cParams, + ZSTD_CParams cParams, ZSTD_ParamSwitch_e useRowMatchFinder, int enableDedicatedDictSearch, ZSTD_customMem customMem) @@ -5639,10 +5692,10 @@ ZSTD_createCDict_advanced_internal(size_t dictSize, } } -ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, +ZSTD_CDict* ZSTD_createCDict_internal(const void* dictBuffer, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams, + ZSTD_CParams cParams, ZSTD_customMem customMem) { ZSTD_CCtx_params cctxParams; @@ -5657,6 +5710,19 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, &cctxParams, customMem); } +ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters publicParams, + ZSTD_customMem customMem) +{ + ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); + return ZSTD_createCDict_internal( + dictBuffer, dictSize, + dictLoadMethod, dictContentType, + cParams, customMem); +} + ZSTD_CDict* ZSTD_createCDict_advanced2( const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, @@ -5665,7 +5731,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_customMem customMem) { ZSTD_CCtx_params cctxParams = *originalCctxParams; - ZSTD_compressionParameters cParams; + ZSTD_CParams cParams; ZSTD_CDict* cdict; DEBUGLOG(3, "ZSTD_createCDict_advanced2, dictSize=%u, mode=%u", (unsigned)dictSize, (unsigned)dictContentType); @@ -5709,10 +5775,11 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, - ZSTD_dlm_byCopy, ZSTD_dct_auto, - cParams, ZSTD_defaultCMem); + ZSTD_CParams cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_internal( + dict, dictSize, + ZSTD_dlm_byCopy, ZSTD_dct_auto, + cParams, ZSTD_defaultCMem); if (cdict) cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; @@ -5720,10 +5787,11 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, - ZSTD_dlm_byRef, ZSTD_dct_auto, - cParams, ZSTD_defaultCMem); + ZSTD_CParams cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_internal( + dict, dictSize, + ZSTD_dlm_byRef, ZSTD_dct_auto, + cParams, ZSTD_defaultCMem); if (cdict) cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; @@ -5760,8 +5828,9 @@ const ZSTD_CDict* ZSTD_initStaticCDict( const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams) + ZSTD_compressionParameters publicParams) { + ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams); /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */ size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0); @@ -5801,7 +5870,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict( return cdict; } -ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) +ZSTD_CParams ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) { assert(cdict != NULL); return cdict->matchState.cParams; @@ -5831,14 +5900,16 @@ static size_t ZSTD_compressBegin_usingCDict_internal( { ZSTD_parameters params; params.fParams = fParams; - params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF + if ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || cdict->compressionLevel == 0 ) ? - ZSTD_getCParamsFromCDict(cdict) - : ZSTD_getCParams(cdict->compressionLevel, - pledgedSrcSize, - cdict->dictContentSize); + || cdict->compressionLevel == 0 ) { + params.cParams = ZSTD_getPublicCParamsFromCParams(ZSTD_getCParamsFromCDict(cdict)); + } else { + params.cParams = ZSTD_getCParams(cdict->compressionLevel, + pledgedSrcSize, + cdict->dictContentSize); + } ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->compressionLevel); } /* Increase window log to fit the entire dictionary and source if the @@ -5991,7 +6062,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, DEBUGLOG(4, "ZSTD_initCStream_internal"); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); + assert(!ZSTD_isError(ZSTD_checkCParams_internal(params->cParams))); zcs->requestedParams = *params; assert(!((dict) && (cdict))); /* either dict or cdict, not both */ if (dict) { @@ -6418,7 +6489,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, } else #endif /* ZSTD_MULTITHREAD */ { U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1; - assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); + assert(!ZSTD_isError(ZSTD_checkCParams_internal(params.cParams))); FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast, cctx->cdict, @@ -7674,9 +7745,9 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; } -static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) +static ZSTD_CParams ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); + ZSTD_CParams cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); switch (cParams.strategy) { case ZSTD_fast: case ZSTD_dfast: @@ -7696,7 +7767,7 @@ static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const } static int ZSTD_dedicatedDictSearch_isSupported( - ZSTD_compressionParameters const* cParams) + ZSTD_CParams const* cParams) { return (cParams->strategy >= ZSTD_greedy) && (cParams->strategy <= ZSTD_lazy2) @@ -7710,7 +7781,7 @@ static int ZSTD_dedicatedDictSearch_isSupported( * context. (Otherwise, those tables would also grow.) */ static void ZSTD_dedicatedDictSearch_revertCParams( - ZSTD_compressionParameters* cParams) { + ZSTD_CParams* cParams) { switch (cParams->strategy) { case ZSTD_fast: case ZSTD_dfast: @@ -7752,11 +7823,15 @@ static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_CParamMo } /*! ZSTD_getCParams_internal() : - * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. + * @return ZSTD_CParams structure for a selected compression level, srcSize and dictSize. * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. * Use dictSize == 0 for unknown or unused. * Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_CParamMode_e`. */ -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) +static ZSTD_CParams ZSTD_getCParams_internal( + int compressionLevel, + unsigned long long srcSizeHint, + size_t dictSize, + ZSTD_CParamMode_e mode) { U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode); U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); @@ -7769,7 +7844,7 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; else row = compressionLevel; - { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; + { ZSTD_CParams cp = ZSTD_defaultCParameters[tableID][row]; DEBUGLOG(5, "ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)cp.strategy); /* acceleration factor */ if (compressionLevel < 0) { @@ -7782,12 +7857,12 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, } /*! ZSTD_getCParams() : - * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. + * @return ZSTD_CParams structure for a selected compression level, srcSize and dictSize. * Size values are optional, provide 0 if not known or unused */ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); + return ZSTD_getPublicCParamsFromCParams(ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown)); } /*! ZSTD_getParams() : @@ -7798,17 +7873,17 @@ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) { ZSTD_parameters params; - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); + ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); ZSTD_memset(¶ms, 0, sizeof(params)); - params.cParams = cParams; + params.cParams = ZSTD_getPublicCParamsFromCParams(cParams); params.fParams.contentSizeFlag = 1; return params; } /*! ZSTD_getParams() : * same idea as ZSTD_getCParams() - * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). + * @return a `ZSTD_parameters` structure (instead of `ZSTD_CParams`). * Fields of `ZSTD_frameParameters` are set to default values */ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ca5e2a4c5bf..9663084ead7 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -191,6 +191,19 @@ size_t ZSTD_buildBlockEntropyStats( * Compression internals structs * *********************************/ +/** + * Internal equivalent of public ZSTD_compressionParameters struct. + */ +typedef struct { + unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ + unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ + unsigned hashLog; /**< dispatch table : larger == faster, more memory */ + unsigned searchLog; /**< nb of searches : larger == more compression, slower */ + unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */ + unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ + ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ +} ZSTD_CParams; + typedef struct { U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */ U32 len; /* Raw length of match */ @@ -298,7 +311,7 @@ struct ZSTD_MatchState_t { */ optState_t opt; /* optimal parser state */ const ZSTD_MatchState_t* dictMatchState; - ZSTD_compressionParameters cParams; + ZSTD_CParams cParams; const RawSeqStore_t* ldmSeqStore; /* Controls prefetching in some dictMatchState matchfinders. @@ -361,7 +374,7 @@ typedef struct { struct ZSTD_CCtx_params_s { ZSTD_format_e format; - ZSTD_compressionParameters cParams; + ZSTD_CParams cParams; ZSTD_frameParameters fParams; int compressionLevel; @@ -1538,12 +1551,22 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs); * These prototypes shall only be called from within lib/compress * ============================================================== */ +/* ZSTD_getCParamsFromPublicCParams(), ZSTD_getPublicCParamsFromCParams() : + * Translates between the public and internal structs. + * + * Note: as these structs diverge, this may increasingly become a lossy + * translation. The only long-term justified use of these should be at the + * User API. + */ +ZSTD_CParams ZSTD_getCParamsFromPublicCParams(ZSTD_compressionParameters cParams); +ZSTD_compressionParameters ZSTD_getPublicCParamsFromCParams(ZSTD_CParams cParams); + /* ZSTD_getCParamsFromCCtxParams() : * cParams are built depending on compressionLevel, src size hints, * LDM and manually set compression parameters. * Note: srcSizeHint == 0 means 0! */ -ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( +ZSTD_CParams ZSTD_getCParamsFromCCtxParams( const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); /*! ZSTD_initCStream_internal() : @@ -1560,7 +1583,17 @@ void ZSTD_resetSeqStore(SeqStore_t* ssPtr); /*! ZSTD_getCParamsFromCDict() : * as the name implies */ -ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict); +ZSTD_CParams ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict); + +size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams); + +/* ZSTD_createCDict_internal() : + * Private use only. To be called from zstdmt_compress.c. */ +ZSTD_CDict* ZSTD_createCDict_internal(const void* dictBuffer, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_CParams cParams, + ZSTD_customMem customMem); /* ZSTD_compressBegin_advanced_internal() : * Private use only. To be called from zstdmt_compress.c. */ diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 1a266e7d955..9c23ad57400 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -18,7 +18,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_fillDoubleHashTableForCDict(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashLarge = ms->hashTable; U32 const hBitsL = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; U32 const mls = cParams->minMatch; @@ -56,7 +56,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_fillDoubleHashTableForCCtx(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashLarge = ms->hashTable; U32 const hBitsL = cParams->hashLog; U32 const mls = cParams->minMatch; @@ -106,7 +106,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { - ZSTD_compressionParameters const* cParams = &ms->cParams; + ZSTD_CParams const* cParams = &ms->cParams; U32* const hashLong = ms->hashTable; const U32 hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; @@ -330,7 +330,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( void const* src, size_t srcSize, U32 const mls /* template */) { - ZSTD_compressionParameters const* cParams = &ms->cParams; + ZSTD_CParams const* cParams = &ms->cParams; U32* const hashLong = ms->hashTable; const U32 hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; @@ -348,7 +348,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( U32 offset_1=rep[0], offset_2=rep[1]; const ZSTD_MatchState_t* const dms = ms->dictMatchState; - const ZSTD_compressionParameters* const dictCParams = &dms->cParams; + const ZSTD_CParams* const dictCParams = &dms->cParams; const U32* const dictHashLong = dms->hashTable; const U32* const dictHashSmall = dms->chainTable; const U32 dictStartIndex = dms->window.dictLimit; @@ -612,7 +612,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict_generic( void const* src, size_t srcSize, U32 const mls /* template */) { - ZSTD_compressionParameters const* cParams = &ms->cParams; + ZSTD_CParams const* cParams = &ms->cParams; U32* const hashLong = ms->hashTable; U32 const hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index ee25bcbac8d..ebd547719e4 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -17,7 +17,7 @@ void ZSTD_fillHashTableForCDict(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hBits = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; U32 const mls = cParams->minMatch; @@ -54,7 +54,7 @@ void ZSTD_fillHashTableForCCtx(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hBits = cParams->hashLog; U32 const mls = cParams->minMatch; @@ -194,7 +194,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( void const* src, size_t srcSize, U32 const mls, int useCmov) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; /* min 2 */ @@ -484,7 +484,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; /* support stepSize of 0 */ @@ -501,7 +501,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( U32 offset_1=rep[0], offset_2=rep[1]; const ZSTD_MatchState_t* const dms = ms->dictMatchState; - const ZSTD_compressionParameters* const dictCParams = &dms->cParams ; + const ZSTD_CParams* const dictCParams = &dms->cParams; const U32* const dictHashTable = dms->hashTable; const U32 dictStartIndex = dms->window.dictLimit; const BYTE* const dictBase = dms->window.base; @@ -710,7 +710,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; /* support stepSize of 0 */ diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 272ebe0ece7..d9206b669e9 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -30,7 +30,7 @@ void ZSTD_updateDUBT(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend, U32 mls) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; @@ -76,7 +76,7 @@ void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 nbCompares, U32 btLow, const ZSTD_dictMode_e dictMode) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const bt = ms->chainTable; U32 const btLog = cParams->chainLog - 1; U32 const btMask = (1 << btLog) - 1; @@ -171,7 +171,7 @@ size_t ZSTD_DUBT_findBetterDictMatch ( const ZSTD_dictMode_e dictMode) { const ZSTD_MatchState_t * const dms = ms->dictMatchState; - const ZSTD_compressionParameters* const dmsCParams = &dms->cParams; + const ZSTD_CParams* const dmsCParams = &dms->cParams; const U32 * const dictHashTable = dms->hashTable; U32 const hashLog = dmsCParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -246,7 +246,7 @@ size_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms, U32 const mls, const ZSTD_dictMode_e dictMode) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -631,7 +631,7 @@ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR U32 ZSTD_insertAndFindFirstIndex_internal( ZSTD_MatchState_t* ms, - const ZSTD_compressionParameters* const cParams, + const ZSTD_CParams* const cParams, const BYTE* ip, U32 const mls, U32 const lazySkipping) { U32* const hashTable = ms->hashTable; @@ -657,7 +657,7 @@ U32 ZSTD_insertAndFindFirstIndex_internal( } U32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch, /* lazySkipping*/ 0); } @@ -670,7 +670,7 @@ size_t ZSTD_HcFindBestMatch( size_t* offsetPtr, const U32 mls, const ZSTD_dictMode_e dictMode) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const chainTable = ms->chainTable; const U32 chainSize = (1 << cParams->chainLog); const U32 chainMask = chainSize-1; @@ -1149,7 +1149,7 @@ size_t ZSTD_RowFindBestMatch( BYTE* const tagTable = ms->tagTable; U32* const hashCache = ms->hashCache; const U32 hashLog = ms->rowHashLog; - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; const BYTE* const base = ms->window.base; const BYTE* const dictBase = ms->window.dictBase; const U32 dictLimit = ms->window.dictLimit; diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 070551cad81..f68e29627e7 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -133,7 +133,7 @@ static size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state, } void ZSTD_ldm_adjustParameters(ldmParams_t* params, - const ZSTD_compressionParameters* cParams) + const ZSTD_CParams* cParams) { params->windowLog = cParams->windowLog; ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX); @@ -683,7 +683,7 @@ size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore, ZSTD_ParamSwitch_e useRowMatchFinder, void const* src, size_t srcSize) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; unsigned const minMatch = cParams->minMatch; ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms)); diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index 42736231aa8..11f36d6d17e 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -104,6 +104,6 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize); * Ensures that the minMatchLength >= targetLength during optimal parsing. */ void ZSTD_ldm_adjustParameters(ldmParams_t* params, - ZSTD_compressionParameters const* cParams); + ZSTD_CParams const* cParams); #endif /* ZSTD_FAST_H */ diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 3d7171b755b..65ea8bedbae 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -445,7 +445,7 @@ U32 ZSTD_insertBt1( U32 const target, U32 const mls, const int extDict) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -598,7 +598,7 @@ ZSTD_insertBtAndGetAllMatches ( const U32 lengthToBeat, const U32 mls /* template */) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); const BYTE* const base = ms->window.base; U32 const curr = (U32)(ip-base); @@ -626,7 +626,7 @@ ZSTD_insertBtAndGetAllMatches ( U32 nbCompares = 1U << cParams->searchLog; const ZSTD_MatchState_t* dms = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL; - const ZSTD_compressionParameters* const dmsCParams = + const ZSTD_CParams* const dmsCParams = dictMode == ZSTD_dictMatchState ? &dms->cParams : NULL; const BYTE* const dmsBase = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL; const BYTE* const dmsEnd = dictMode == ZSTD_dictMatchState ? dms->window.nextSrc : NULL; @@ -1089,7 +1089,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, const BYTE* const ilimit = iend - 8; const BYTE* const base = ms->window.base; const BYTE* const prefixStart = base + ms->window.dictLimit; - const ZSTD_compressionParameters* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cParams; ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode); diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 0f1fe6d7469..cebda55bff3 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1100,7 +1100,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; - { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + { ZSTD_CParams cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); cParams.windowLog = saved_wlog; mtctx->params.cParams = cParams; } @@ -1256,7 +1256,7 @@ size_t ZSTDMT_initCStream_internal( (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx); /* params supposed partially fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); + assert(!ZSTD_isError(ZSTD_checkCParams_internal(params.cParams))); assert(!((dict) && (cdict))); /* either dict or cdict, not both */ /* init */ @@ -1276,9 +1276,10 @@ size_t ZSTDMT_initCStream_internal( mtctx->frameContentSize = pledgedSrcSize; ZSTD_freeCDict(mtctx->cdictLocal); if (dict) { - mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, - ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */ - params.cParams, mtctx->cMem); + mtctx->cdictLocal = ZSTD_createCDict_internal( + dict, dictSize, + ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */ + params.cParams, mtctx->cMem); mtctx->cdict = mtctx->cdictLocal; if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); } else { @@ -1358,7 +1359,7 @@ size_t ZSTDMT_initCStream_internal( mtctx->inBuff.prefix.size = dictSize; } else { /* note : a loadPrefix becomes an internal CDict */ - mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, + mtctx->cdictLocal = ZSTD_createCDict_internal(dict, dictSize, ZSTD_dlm_byRef, dictContentType, params.cParams, mtctx->cMem); mtctx->cdict = mtctx->cdictLocal; From 768a55c89b88d054e5c9c6e1a17f3d12a801ee8e Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 29 Jan 2025 13:53:13 -0800 Subject: [PATCH 02/36] Also Separate Public and Private Params Structs This commit extends the refactor done in the previous and applies it to the `ZSTD_parameters` public struct, introducing an internal variant called `ZSTD_Params` whose only difference is containing a `ZSTD_CParams` instead of a `ZSTD_compressionParameters`. This commit similarly introduces conversion functions and rewrites internal functions to use the new, private definition. This allows us to clean up some internal conversions of the private `CParams` back into the public `CParams` in order to put them in a `ZSTD_parameters` struct to pass into something. --- lib/compress/zstd_compress.c | 78 +++++++++++++++++---------- lib/compress/zstd_compress_internal.h | 19 +++++++ 2 files changed, 68 insertions(+), 29 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b32d5c4cf6d..011611f4f20 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -372,12 +372,12 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) */ static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, - const ZSTD_parameters* params, + const ZSTD_Params* params, int compressionLevel) { - assert(!ZSTD_checkCParams(params->cParams)); + assert(!ZSTD_checkCParams_internal(params->cParams)); ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); - cctxParams->cParams = ZSTD_getCParamsFromPublicCParams(params->cParams); + cctxParams->cParams = params->cParams; cctxParams->fParams = params->fParams; /* Should not matter, as all cParams are presumed properly defined. * But, set it for tracing anyway. @@ -393,10 +393,11 @@ ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, cctxParams->useRowMatchFinder, cctxParams->postBlockSplitter, cctxParams->ldmParams.enableLdm); } -size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) +size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters publicParams) { + ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); - FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams_internal(params.cParams) , ""); ZSTD_CCtxParams_init_internal(cctxParams, ¶ms, ZSTD_NO_CLEVEL); return 0; } @@ -406,10 +407,10 @@ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_paramete * @param params Validated zstd parameters. */ static void ZSTD_CCtxParams_setZstdParams( - ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) + ZSTD_CCtx_params* cctxParams, const ZSTD_Params* params) { - assert(!ZSTD_checkCParams(params->cParams)); - cctxParams->cParams = ZSTD_getCParamsFromPublicCParams(params->cParams); + assert(!ZSTD_checkCParams_internal(params->cParams)); + cctxParams->cParams = params->cParams; cctxParams->fParams = params->fParams; /* Should not matter, as all cParams are presumed properly defined. * But, set it for tracing anyway. @@ -1651,8 +1652,22 @@ ZSTD_compressionParameters ZSTD_getPublicCParamsFromCParams( }; } +ZSTD_Params ZSTD_getParamsFromPublicParams(ZSTD_parameters params) { + return (ZSTD_Params){ + ZSTD_getCParamsFromPublicCParams(params.cParams), + params.fParams + }; +} + +ZSTD_parameters ZSTD_getPublicParamsFromParams(ZSTD_Params params) { + return (ZSTD_parameters){ + ZSTD_getPublicCParamsFromCParams(params.cParams), + params.fParams + }; +} + static ZSTD_CParams ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); +static ZSTD_Params ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); static void ZSTD_overrideCParams( ZSTD_CParams* cParams, @@ -5349,9 +5364,11 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, * @return : 0, or an error code */ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pledgedSrcSize) + ZSTD_parameters publicParams, + unsigned long long pledgedSrcSize) { ZSTD_CCtx_params cctxParams; + ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL); return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, @@ -5363,7 +5380,7 @@ static size_t ZSTD_compressBegin_usingDict_deprecated(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { ZSTD_CCtx_params cctxParams; - { ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); + { ZSTD_Params const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel); } DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); @@ -5487,10 +5504,11 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict,size_t dictSize, - ZSTD_parameters params) + ZSTD_parameters publicParams) { + ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); DEBUGLOG(4, "ZSTD_compress_advanced"); - FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); + FORWARD_IF_ERROR(ZSTD_checkCParams_internal(params.cParams), ""); ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, ZSTD_NO_CLEVEL); return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, @@ -5521,7 +5539,7 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, int compressionLevel) { { - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); + ZSTD_Params const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); assert(params.fParams.contentSizeFlag == 1); ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel); } @@ -5898,17 +5916,19 @@ static size_t ZSTD_compressBegin_usingCDict_internal( RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!"); /* Initialize the cctxParams from the cdict */ { - ZSTD_parameters params; + ZSTD_Params params; params.fParams = fParams; if ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN || cdict->compressionLevel == 0 ) { - params.cParams = ZSTD_getPublicCParamsFromCParams(ZSTD_getCParamsFromCDict(cdict)); + params.cParams = ZSTD_getCParamsFromCDict(cdict); } else { - params.cParams = ZSTD_getCParams(cdict->compressionLevel, - pledgedSrcSize, - cdict->dictContentSize); + params.cParams = ZSTD_getCParams_internal( + cdict->compressionLevel, + pledgedSrcSize, + cdict->dictContentSize, + ZSTD_cpm_unknown); } ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->compressionLevel); } @@ -6105,8 +6125,9 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict) * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pss) + ZSTD_parameters publicParams, unsigned long long pss) { + ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); /* for compatibility with older programs relying on this behavior. * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. * This line will be removed in the future. @@ -6115,7 +6136,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, DEBUGLOG(4, "ZSTD_initCStream_advanced"); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams_internal(params.cParams) , ""); ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, ¶ms); FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); return 0; @@ -7865,30 +7886,29 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l return ZSTD_getPublicCParamsFromCParams(ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown)); } -/*! ZSTD_getParams() : +/*! ZSTD_getParams_internal() : * same idea as ZSTD_getCParams() - * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). + * @return a `ZSTD_Params` structure (instead of `ZSTD_CParams`). * Fields of `ZSTD_frameParameters` are set to default values */ -static ZSTD_parameters +static ZSTD_Params ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) { - ZSTD_parameters params; - ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); + ZSTD_Params params; DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); ZSTD_memset(¶ms, 0, sizeof(params)); - params.cParams = ZSTD_getPublicCParamsFromCParams(cParams); + params.cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); params.fParams.contentSizeFlag = 1; return params; } /*! ZSTD_getParams() : * same idea as ZSTD_getCParams() - * @return a `ZSTD_parameters` structure (instead of `ZSTD_CParams`). + * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). * Fields of `ZSTD_frameParameters` are set to default values */ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); + return ZSTD_getPublicParamsFromParams(ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown)); } void ZSTD_registerSequenceProducer( diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 9663084ead7..2297c3f065c 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -204,6 +204,15 @@ typedef struct { ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ } ZSTD_CParams; +/** + * Internal equivalent of public ZSTD_Params struct, wrapping the internal + * ZSTD_CParams struct rather than the public ZSTD_compressionParameters. + */ +typedef struct { + ZSTD_CParams cParams; + ZSTD_frameParameters fParams; +} ZSTD_Params; + typedef struct { U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */ U32 len; /* Raw length of match */ @@ -1561,6 +1570,16 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs); ZSTD_CParams ZSTD_getCParamsFromPublicCParams(ZSTD_compressionParameters cParams); ZSTD_compressionParameters ZSTD_getPublicCParamsFromCParams(ZSTD_CParams cParams); +/* ZSTD_getParamsFromPublicParams(), ZSTD_getPublicParamsFromParams() : + * Translates between the public and internal structs. + * + * Note: as these structs diverge, this may increasingly become a lossy + * translation. The only long-term justified use of these should be at the + * User API. + */ +ZSTD_Params ZSTD_getParamsFromPublicParams(ZSTD_parameters params); +ZSTD_parameters ZSTD_getPublicParamsFromParams(ZSTD_Params params); + /* ZSTD_getCParamsFromCCtxParams() : * cParams are built depending on compressionLevel, src size hints, * LDM and manually set compression parameters. From aa76d3fe9c49c09c2b214c30f53feeb8f49a78bc Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 29 Jan 2025 11:53:31 -0800 Subject: [PATCH 03/36] Add a `windowFrac` Field to `ZSTD_CParams` --- lib/compress/clevels.h | 192 +++++++++++++------------- lib/compress/zstd_compress.c | 3 + lib/compress/zstd_compress_internal.h | 1 + 3 files changed, 100 insertions(+), 96 deletions(-) diff --git a/lib/compress/clevels.h b/lib/compress/clevels.h index 4c8d12fabfe..0ff8875fdb3 100644 --- a/lib/compress/clevels.h +++ b/lib/compress/clevels.h @@ -24,108 +24,108 @@ __attribute__((__unused__)) static const ZSTD_CParams ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { { /* "default" - for any srcSize > 256 KB */ - /* W, C, H, S, L, TL, strat */ - { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ - { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ - { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ - { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ - { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ - { 21, 18, 19, 3, 5, 2, ZSTD_greedy }, /* level 5 */ - { 21, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6 */ - { 21, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */ - { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 8 */ - { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ - { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 10 */ - { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 11 */ - { 22, 22, 23, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */ - { 22, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */ - { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ - { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ - { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ - { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ - { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ - { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ - { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ - { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ - { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ + /* W, WF, C, H, S, L, TL, strat */ + { 19, 0, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ + { 19, 0, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ + { 20, 0, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ + { 21, 0, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ + { 21, 0, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ + { 21, 0, 18, 19, 3, 5, 2, ZSTD_greedy }, /* level 5 */ + { 21, 0, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6 */ + { 21, 0, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */ + { 21, 0, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 8 */ + { 22, 0, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ + { 22, 0, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 10 */ + { 22, 0, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 11 */ + { 22, 0, 22, 23, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */ + { 22, 0, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */ + { 22, 0, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ + { 22, 0, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ + { 22, 0, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ + { 23, 0, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ + { 23, 0, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ + { 23, 0, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ + { 25, 0, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ + { 26, 0, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ + { 27, 0, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ }, { /* for srcSize <= 256 KB */ - /* W, C, H, S, L, T, strat */ - { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ - { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ - { 18, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/ - { 18, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/ - { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ - { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ - { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ - { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ - { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ - { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ + /* W, WF, C, H, S, L, T, strat */ + { 18, 0, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 18, 0, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 18, 0, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ + { 18, 0, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ + { 18, 0, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/ + { 18, 0, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/ + { 18, 0, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ + { 18, 0, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ + { 18, 0, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 18, 0, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 18, 0, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 18, 0, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ + { 18, 0, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ + { 18, 0, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ + { 18, 0, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 18, 0, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ + { 18, 0, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 18, 0, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 18, 0, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ + { 18, 0, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 18, 0, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 18, 0, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 18, 0, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ }, { /* for srcSize <= 128 KB */ - /* W, C, H, S, L, T, strat */ - { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ - { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ - { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ - { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ - { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ - { 17, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 17, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 17, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 17, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ - { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ - { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ - { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ - { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ - { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ + /* W, WF, C, H, S, L, T, strat */ + { 17, 0, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 17, 0, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 17, 0, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ + { 17, 0, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ + { 17, 0, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ + { 17, 0, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ + { 17, 0, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ + { 17, 0, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 17, 0, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 17, 0, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 17, 0, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 17, 0, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ + { 17, 0, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ + { 17, 0, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ + { 17, 0, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 17, 0, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ + { 17, 0, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 17, 0, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 17, 0, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ + { 17, 0, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 17, 0, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 17, 0, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 17, 0, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ }, { /* for srcSize <= 16 KB */ - /* W, C, H, S, L, T, strat */ - { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ - { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ - { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ - { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ - { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ - { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ - { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ - { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ - { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ - { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ - { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ - { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ - { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ - { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ - { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ - { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ + /* W, WF, C, H, S, L, T, strat */ + { 14, 0, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 14, 0, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ + { 14, 0, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ + { 14, 0, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ + { 14, 0, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ + { 14, 0, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ + { 14, 0, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ + { 14, 0, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 14, 0, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ + { 14, 0, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ + { 14, 0, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ + { 14, 0, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ + { 14, 0, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ + { 14, 0, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ + { 14, 0, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ + { 14, 0, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ + { 14, 0, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ + { 14, 0, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ + { 14, 0, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ + { 14, 0, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 14, 0, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 14, 0, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 14, 0, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ }, }; diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 011611f4f20..5c0b6d5611f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1386,6 +1386,7 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams) { BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); + /* TODO: check windowFrac */ BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); @@ -1630,6 +1631,7 @@ ZSTD_CParams ZSTD_getCParamsFromPublicCParams( ZSTD_compressionParameters cParams) { return (ZSTD_CParams){ cParams.windowLog, + 0, /* windowFrac */ cParams.chainLog, cParams.hashLog, cParams.searchLog, @@ -1674,6 +1676,7 @@ static void ZSTD_overrideCParams( const ZSTD_CParams* overrides) { if (overrides->windowLog) cParams->windowLog = overrides->windowLog; + if (overrides->windowFrac) cParams->windowFrac = overrides->windowFrac; if (overrides->hashLog) cParams->hashLog = overrides->hashLog; if (overrides->chainLog) cParams->chainLog = overrides->chainLog; if (overrides->searchLog) cParams->searchLog = overrides->searchLog; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 2297c3f065c..69eabd0902c 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -196,6 +196,7 @@ size_t ZSTD_buildBlockEntropyStats( */ typedef struct { unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ + unsigned windowFrac; /**< fractional component of window size representation */ unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ unsigned hashLog; /**< dispatch table : larger == faster, more memory */ unsigned searchLog; /**< nb of searches : larger == more compression, slower */ From 139b72592d672f3a204c2ca7e125a46014e60020 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 29 Jan 2025 14:22:31 -0800 Subject: [PATCH 04/36] Add Public `ZSTD_c_windowFrac` CCtxParam Store it in the CParams. Don't use it yet. --- lib/compress/zstd_compress.c | 15 +++++++++++++++ lib/zstd.h | 18 ++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 5c0b6d5611f..88c5dbe57c3 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -434,6 +434,11 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = ZSTD_WINDOWLOG_MAX; return bounds; + case ZSTD_c_windowFrac: + bounds.lowerBound = 0; + bounds.upperBound = 7; + return bounds; + case ZSTD_c_hashLog: bounds.lowerBound = ZSTD_HASHLOG_MIN; bounds.upperBound = ZSTD_HASHLOG_MAX; @@ -673,6 +678,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_format: case ZSTD_c_windowLog: + case ZSTD_c_windowFrac: case ZSTD_c_contentSizeFlag: case ZSTD_c_checksumFlag: case ZSTD_c_dictIDFlag: @@ -726,6 +732,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_compressionLevel: case ZSTD_c_windowLog: + case ZSTD_c_windowFrac: case ZSTD_c_hashLog: case ZSTD_c_chainLog: case ZSTD_c_searchLog: @@ -796,6 +803,11 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->cParams.windowLog = (U32)value; return CCtxParams->cParams.windowLog; + case ZSTD_c_windowFrac : + BOUNDCHECK(ZSTD_c_windowFrac, value); + CCtxParams->cParams.windowFrac = (U32)value; + return CCtxParams->cParams.windowFrac; + case ZSTD_c_hashLog : if (value!=0) /* 0 => use default */ BOUNDCHECK(ZSTD_c_hashLog, value); @@ -1041,6 +1053,9 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_windowLog : *value = (int)CCtxParams->cParams.windowLog; break; + case ZSTD_c_windowFrac : + *value = (int)CCtxParams->cParams.windowFrac; + break; case ZSTD_c_hashLog : *value = (int)CCtxParams->cParams.hashLog; break; diff --git a/lib/zstd.h b/lib/zstd.h index b8c0644a7ec..4b0dcab2ba7 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -372,7 +372,10 @@ typedef enum { * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX. * Special: value 0 means "use default windowLog". * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT - * requires explicitly allowing such size at streaming decompression stage. */ + * requires explicitly allowing such size at streaming + * decompression stage. + * Note: The ZSTD_c_windowFrac parameter allows finer-grained + * tweaking of the window size set by this parameter. */ ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2. * Resulting memory usage is (1 << (hashLog+2)). * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX. @@ -538,7 +541,8 @@ typedef enum { ZSTD_c_experimentalParam17=1014, ZSTD_c_experimentalParam18=1015, ZSTD_c_experimentalParam19=1016, - ZSTD_c_experimentalParam20=1017 + ZSTD_c_experimentalParam20=1017, + ZSTD_c_experimentalParam21=1018 } ZSTD_cParameter; typedef struct { @@ -2355,6 +2359,16 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo #define ZSTD_c_repcodeResolution ZSTD_c_experimentalParam19 #define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 /* older name */ +/* ZSTD_c_windowFrac + * The Zstandard format allows expressing window sizes in a more fine-grained + * way than just the power-of-two sizes captured by the windowLog parameter. + * The window size is `(1 + WF / 8) * 2 ^ WL` bytes, where WL is the windowLog + * and WF is the windowFrac. + * + * The valid range of values for this parameter is 0 to 7. The default value + * is 0. + */ +#define ZSTD_c_windowFrac ZSTD_c_experimentalParam21 /*! ZSTD_CCtx_getParameter() : * Get the requested compression parameter value, selected by enum ZSTD_cParameter, From 7e695b816033c8bf3b56d77881861d2c41c5bd3f Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Jan 2025 10:42:29 -0800 Subject: [PATCH 05/36] Fix Fuzzer Tests Using a blocksize of 100KB with a 65KB dictionary just *happens* to work with the current window-sizing logic, because it has to round all the way up to the next power of two. But it doesn't *have* to work. So this pre-emptively fixes up this test to use a size that will work after switching to tighter window sizing, but still uses a block size that is bigger than the dict size in case that matters for some reason? --- lib/compress/zstd_compress.c | 1 - tests/fuzzer.c | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 88c5dbe57c3..17d510fd711 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4957,7 +4957,6 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx) return ZSTD_getBlockSize_deprecated(cctx); } -/* NOTE: Must just wrap ZSTD_compressBlock_deprecated() */ size_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index b74460bb573..868df78a0cc 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -707,8 +707,8 @@ static int basicUnitTests(U32 const seed, double compressibility) params.hashLog = 19; params.chainLog = 19; params = ZSTD_adjustCParams(params, 1000, 100000); - if (params.hashLog != 18) goto _output_error; - if (params.chainLog != 17) goto _output_error; + CHECK_EQ(params.chainLog, 17); + CHECK_EQ(params.hashLog, 18); } DISPLAYLEVEL(3, "OK \n"); @@ -3670,7 +3670,7 @@ static int basicUnitTests(U32 const seed, double compressibility) { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); ZSTD_DCtx* const dctx = ZSTD_createDCtx(); static const size_t dictSize = 65 KB; - static const size_t blockSize = 100 KB; /* won't cause pb with small dict size */ + static const size_t blockSize = 71 KB; /* won't cause pb with small dict size */ size_t cSize2; assert(cctx != NULL); assert(dctx != NULL); @@ -3734,6 +3734,7 @@ static int basicUnitTests(U32 const seed, double compressibility) { ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 3); if (cdict==NULL) goto _output_error; CHECK_Z( ZSTD_compressBegin_usingCDict(cctx, cdict) ); + CHECK_Z( ZSTD_getBlockSize(cctx) >= blockSize); CHECK_Z( ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize) ); ZSTD_freeCDict(cdict); } From 4dbc1a15fc0902035e73b81b4e14847b2ae901c9 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 29 Jan 2025 14:29:02 -0800 Subject: [PATCH 06/36] Implement Support for Fractional Window Sizes --- lib/compress/zstd_compress.c | 117 ++++++++++++++++---------- lib/compress/zstd_compress_internal.h | 76 +++++++++++++++-- lib/compress/zstd_double_fast.c | 10 +-- lib/compress/zstd_fast.c | 8 +- lib/compress/zstd_lazy.c | 19 ++--- lib/compress/zstd_ldm.c | 3 +- lib/compress/zstd_opt.c | 4 +- lib/compress/zstdmt_compress.c | 8 +- 8 files changed, 167 insertions(+), 78 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 17d510fd711..23ccc3ed1c7 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1401,7 +1401,7 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams) { BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); - /* TODO: check windowFrac */ + BOUNDCHECK(ZSTD_c_windowFrac, (int)cParams.windowFrac); BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); @@ -1433,6 +1433,7 @@ ZSTD_clampCParams(ZSTD_CParams cParams) } while (0) # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) CLAMP(ZSTD_c_windowLog, cParams.windowLog); + CLAMP(ZSTD_c_windowFrac, cParams.windowFrac); CLAMP(ZSTD_c_chainLog, cParams.chainLog); CLAMP(ZSTD_c_hashLog, cParams.hashLog); CLAMP(ZSTD_c_searchLog, cParams.searchLog); @@ -1451,35 +1452,36 @@ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) } /** ZSTD_dictAndWindowLog() : - * Returns an adjusted window log that is large enough to fit the source and the dictionary. + * Adjusts the provided window params to be large enough to fit the source and the dictionary. * The zstd format says that the entire dictionary is valid if one byte of the dictionary * is within the window. So the hashLog and chainLog should be large enough to reference both * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing * the hashLog and windowLog. * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN. */ -static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize) +static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSize) { const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX; /* No dictionary ==> No change */ if (dictSize == 0) { - return windowLog; + return; } - assert(windowLog <= ZSTD_WINDOWLOG_MAX); + assert(cParams->windowLog <= ZSTD_WINDOWLOG_MAX); assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */ { - U64 const windowSize = 1ULL << windowLog; + U64 const windowSize = ZSTD_windowSize(cParams); U64 const dictAndWindowSize = dictSize + windowSize; /* If the window size is already large enough to fit both the source and the dictionary * then just use the window size. Otherwise adjust so that it fits the dictionary and * the window. */ if (windowSize >= dictSize + srcSize) { - return windowLog; /* Window size large enough already */ + /* Window size large enough already */ } else if (dictAndWindowSize >= maxWindowSize) { - return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */ + cParams->windowLog = ZSTD_WINDOWLOG_MAX; /* Larger than max window log */ + cParams->windowFrac = 0; } else { - return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1; + ZSTD_setMinimalWindowLogAndFrac(cParams, dictAndWindowSize); } } } @@ -1576,20 +1578,34 @@ ZSTD_adjustCParams_internal(ZSTD_CParams cPar, && (dictSize <= maxWindowResize) ) { U32 const tSize = (U32)(srcSize + dictSize); static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN; - U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN : - ZSTD_highbit32(tSize-1) + 1; - if (cPar.windowLog > srcLog) cPar.windowLog = srcLog; + if (ZSTD_windowSize(&cPar) > tSize) { + if (tSize < hashSizeMin) { + cPar.windowLog = ZSTD_HASHLOG_MIN; + cPar.windowFrac = 0; + } else { + ZSTD_setMinimalWindowLogAndFrac(&cPar, tSize); + } + } } if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) { - U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize); + ZSTD_CParams dictWindowCParams = cPar; U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); - if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1; - if (cycleLog > dictAndWindowLog) - cPar.chainLog -= (cycleLog - dictAndWindowLog); + ZSTD_dictAndWindowLog(&dictWindowCParams, (U64)srcSize, (U64)dictSize); + if (dictWindowCParams.windowFrac != 0) { + /* Round up to a whole power of two. */ + dictWindowCParams.windowLog++; + dictWindowCParams.windowFrac = 0; + } + if (cPar.hashLog > dictWindowCParams.windowLog+1) + cPar.hashLog = dictWindowCParams.windowLog+1; + if (cycleLog > dictWindowCParams.windowLog) + cPar.chainLog -= (cycleLog - dictWindowCParams.windowLog); } - if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) + if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) { cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */ + cPar.windowFrac = 0; + } /* We can't use more than 32 bits of hash in total, so that means that we require: * (hashLog + 8) <= 32 && (chainLog + 8) <= 32 @@ -1776,7 +1792,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( int useSequenceProducer, size_t maxBlockSize) { - size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize); + size_t const windowSize = (size_t) BOUNDED(1ULL, ZSTD_windowSize(cParams), pledgedSrcSize); size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize); size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer); size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) @@ -1885,9 +1901,10 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); { ZSTD_CParams const cParams = ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); - size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), (size_t)1 << cParams.windowLog); + size_t const windowSize = ZSTD_windowSize(&cParams); + size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), windowSize); size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered) - ? ((size_t)1 << cParams.windowLog) + blockSize + ? windowSize + blockSize : 0; size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered) ? ZSTD_compressBound(blockSize) + 1 @@ -1985,6 +2002,7 @@ static void ZSTD_assertEqualCParams(ZSTD_CParams cParams1, (void)cParams1; (void)cParams2; assert(cParams1.windowLog == cParams2.windowLog); + assert(cParams1.windowFrac == cParams2.windowFrac); assert(cParams1.chainLog == cParams2.chainLog); assert(cParams1.hashLog == cParams2.hashLog); assert(cParams1.searchLog == cParams2.searchLog); @@ -2206,7 +2224,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, assert(params->ldmParams.hashRateLog < 32); } - { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize)); + { size_t const windowSize = MAX(1, (size_t)MIN(ZSTD_windowSize(¶ms->cParams), pledgedSrcSize)); size_t const blockSize = MIN(params->maxBlockSize, windowSize); size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, ZSTD_hasExtSeqProd(params)); size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered) @@ -2411,6 +2429,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, { ZSTD_CParams adjusted_cdict_cParams = cdict->matchState.cParams; unsigned const windowLog = params.cParams.windowLog; + unsigned const windowFrac = params.cParams.windowFrac; assert(windowLog != 0); /* Resize working context table params for input only, since the dict * has its own tables. */ @@ -2423,7 +2442,8 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize, cdict->dictContentSize, ZSTD_cpm_attachDict, params.useRowMatchFinder); - params.cParams.windowLog = windowLog; + params.cParams.windowLog = windowLog; + params.cParams.windowFrac = windowFrac; params.useRowMatchFinder = cdict->useRowMatchFinder; /* cdict overrides */ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, /* loadedDictSize */ 0, @@ -2489,11 +2509,13 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, DEBUGLOG(4, "ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu", (unsigned long long)pledgedSrcSize); - { unsigned const windowLog = params.cParams.windowLog; + { unsigned const windowLog = params.cParams.windowLog; + unsigned const windowFrac = params.cParams.windowFrac; assert(windowLog != 0); /* Copy only compression parameters related to tables. */ params.cParams = *cdict_cParams; - params.cParams.windowLog = windowLog; + params.cParams.windowLog = windowLog; + params.cParams.windowFrac = windowFrac; params.useRowMatchFinder = cdict->useRowMatchFinder; FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, /* loadedDictSize */ 0, @@ -2613,6 +2635,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, /* loadedDictSize */ 0, ZSTDcrp_leaveDirty, zbuff); assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog); + assert(dstCCtx->appliedParams.cParams.windowFrac == srcCCtx->appliedParams.cParams.windowFrac); assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy); assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog); assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog); @@ -3432,7 +3455,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) ); assert(zc->appliedParams.extSeqProdFunc != NULL); - { U32 const windowSize = (U32)1 << zc->appliedParams.cParams.windowLog; + { U32 const windowSize = ZSTD_windowSize(&zc->appliedParams.cParams); size_t const nbExternalSeqs = (zc->appliedParams.extSeqProdFunc)( zc->appliedParams.extSeqProdState, @@ -4608,7 +4631,7 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms, void const* iend) { U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy); - U32 const maxDist = (U32)1 << params->cParams.windowLog; + U32 const maxDist = ZSTD_windowSize(¶ms->cParams); if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) { U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); @@ -4676,10 +4699,11 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; - U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; + U32 const maxDist = ZSTD_windowSize(&cctx->appliedParams.cParams); S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); + assert(cctx->appliedParams.cParams.windowFrac == 0 || cctx->appliedParams.cParams.windowLog != ZSTD_WINDOWLOG_MAX); DEBUGLOG(5, "ZSTD_compress_frameChunk (srcSize=%u, blockSizeMax=%u)", (unsigned)srcSize, (unsigned)blockSizeMax); if (cctx->appliedParams.fParams.checksumFlag && srcSize) @@ -4778,9 +4802,9 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */ U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */ U32 const checksumFlag = params->fParams.checksumFlag>0; - U32 const windowSize = (U32)1 << params->cParams.windowLog; + U32 const windowSize = ZSTD_windowSize(¶ms->cParams); U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); - BYTE const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); + BYTE const windowByte = (BYTE)(((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3) | (params->cParams.windowFrac & 7)); U32 const fcsCode = params->fParams.contentSizeFlag ? (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */ BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); @@ -4796,7 +4820,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, pos = 4; } op[pos++] = frameHeaderDescriptionByte; - if (!singleSegment) op[pos++] = windowLogByte; + if (!singleSegment) op[pos++] = windowByte; switch(dictIDSizeCode) { default: @@ -4948,7 +4972,7 @@ static size_t ZSTD_getBlockSize_deprecated(const ZSTD_CCtx* cctx) { ZSTD_CParams const cParams = cctx->appliedParams.cParams; assert(!ZSTD_checkCParams_internal(cParams)); - return MIN(cctx->appliedParams.maxBlockSize, (size_t)1 << cParams.windowLog); + return MIN(cctx->appliedParams.maxBlockSize, (size_t)ZSTD_windowSize(&cParams)); } /* NOTE: Must just wrap ZSTD_getBlockSize_deprecated() */ @@ -5956,7 +5980,11 @@ static size_t ZSTD_compressBegin_usingCDict_internal( if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1; - cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog); + U32 const curWindowLog = cctxParams.cParams.windowLog; + if (limitedSrcLog > curWindowLog) { + cctxParams.cParams.windowLog = limitedSrcLog; + cctxParams.cParams.windowFrac = 0; + } } return ZSTD_compressBegin_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, @@ -6710,17 +6738,18 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, * @returns a ZSTD error code if sequence is not valid */ static size_t -ZSTD_validateSequence(U32 offBase, U32 matchLength, U32 minMatch, - size_t posInSrc, U32 windowLog, size_t dictSize, int useSequenceProducer) +ZSTD_validateSequence( + U32 offBase, U32 matchLength, const ZSTD_CParams* cParams, + size_t posInSrc, size_t dictSize, int useSequenceProducer) { - U32 const windowSize = 1u << windowLog; + U32 const windowSize = ZSTD_windowSize(cParams); /* posInSrc represents the amount of data the decoder would decode up to this point. * As long as the amount of data decoded is less than or equal to window size, offsets may be * larger than the total length of output decoded in order to reference the dict, even larger than * window size. After output surpasses windowSize, we're limited to windowSize offsets again. */ size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize; - size_t const matchLenLowerBound = (minMatch == 3 || useSequenceProducer) ? 3 : 4; + size_t const matchLenLowerBound = (cParams->minMatch == 3 || useSequenceProducer) ? 3 : 4; RETURN_ERROR_IF(offBase > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, "Offset too large!"); /* Validate maxNbSeq is large enough for the given matchLength and minMatch */ RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, "Matchlength too small for the minMatch"); @@ -6790,11 +6819,10 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); if (cctx->appliedParams.validateSequences) { seqPos->posInSrc += litLength + matchLength; - FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, - seqPos->posInSrc, - cctx->appliedParams.cParams.windowLog, dictSize, - ZSTD_hasExtSeqProd(&cctx->appliedParams)), - "Sequence validation failed"); + FORWARD_IF_ERROR(ZSTD_validateSequence( + offBase, matchLength, &cctx->appliedParams.cParams, + seqPos->posInSrc, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), + "Sequence validation failed"); } RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); @@ -6945,9 +6973,10 @@ ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx, if (cctx->appliedParams.validateSequences) { seqPos->posInSrc += litLength + matchLength; - FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc, - cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), - "Sequence validation failed"); + FORWARD_IF_ERROR(ZSTD_validateSequence( + offBase, matchLength, &cctx->appliedParams.cParams, + seqPos->posInSrc, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), + "Sequence validation failed"); } DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 69eabd0902c..ce0ab182451 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -371,8 +371,9 @@ typedef struct { U32 hashLog; /* Log size of hashTable */ U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */ U32 minMatchLength; /* Minimum match length */ - U32 hashRateLog; /* Log number of entries to skip */ + U32 hashRateLog; /* Log number of entries to skip */ U32 windowLog; /* Window log for the LDM */ + U32 windowFrac; /* Window log for the LDM */ } ldmParams_t; typedef struct { @@ -1100,6 +1101,55 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) ZSTD_noDict; } +/** + * Return the window size described by the windowLog and windowFrac in the + * provided CParams. + */ +MEM_STATIC U32 ZSTD_windowSize(const ZSTD_CParams* cParams) { + return (U32)(((8ull + cParams->windowFrac) << cParams->windowLog) >> 3); +} +MEM_STATIC U32 ZSTD_windowSizeLDM(const ldmParams_t* ldmParams) { + return (U32)(((8ull + ldmParams->windowFrac) << ldmParams->windowLog) >> 3); +} + +/** + * Checks that the selected windowSize satisfies the inequality + * srcSize <= windowSize <= srcSize * 1.25, in the range where the window + */ +MEM_STATIC int ZSTD_windowLogAndFracAreMinimal(ZSTD_CParams* cParams, const U32 srcSize) { + const U32 lowerBound = MIN(srcSize, 1u << ZSTD_WINDOWLOG_MAX); + const U32 upperBound = MAX(srcSize + (srcSize >> 3), 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN); + const U32 windowSize = ZSTD_windowSize(cParams); + if (windowSize < lowerBound) { + return 0; + } + if (windowSize > upperBound) { + return 0; + } + return 1; +} + +/** + * Calculates the minimum legal window log and fraction that contain the + * provided source size. + */ +MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 srcSize) { + const U32 minSize = 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN; + if (srcSize < minSize) { + cParams->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; + cParams->windowFrac = 0; + } else { + const U32 srcSizeMinusOne = srcSize - 1; + cParams->windowLog = ZSTD_highbit32(srcSizeMinusOne); + cParams->windowFrac = (((srcSizeMinusOne << 3) >> cParams->windowLog) & 7) + 1; + if (cParams->windowFrac == 8) { + cParams->windowFrac = 0; + cParams->windowLog++; + } + } + assert(ZSTD_windowLogAndFracAreMinimal(cParams, srcSize)); +} + /* Defining this macro to non-zero tells zstd to run the overflow correction * code much more frequently. This is very inefficient, and should only be * used for tests and fuzzers. @@ -1123,10 +1173,12 @@ MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window, U32 loadedDictEnd, void const* src) { + /* overflow correction only handles power-of-two index moves. */ + U32 const roundedMaxDist = 1u << (ZSTD_highbit32(maxDist - 1) + 1); U32 const cycleSize = 1u << cycleLog; U32 const curr = (U32)((BYTE const*)src - window.base); U32 const minIndexToOverflowCorrect = cycleSize - + MAX(maxDist, cycleSize) + + MAX(roundedMaxDist, cycleSize) + ZSTD_WINDOW_START_INDEX; /* Adjust the min index to backoff the overflow correction frequency, @@ -1201,23 +1253,29 @@ U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, * 3. (cctx->lowLimit + 1< 3<<29 + 1<base); U32 const currentCycle = curr & cycleMask; - /* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */ + /* Ensure newCurrent - roundedMaxDist >= ZSTD_WINDOW_START_INDEX. */ U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX ? MAX(cycleSize, ZSTD_WINDOW_START_INDEX) : 0; U32 const newCurrent = currentCycle + currentCycleCorrection - + MAX(maxDist, cycleSize); + + MAX(roundedMaxDist, cycleSize); U32 const correction = curr - newCurrent; /* maxDist must be a power of two so that: * (newCurrent & cycleMask) == (curr & cycleMask) * This is required to not corrupt the chains / binary tree. + * + * Now that window sizes can be non-power-of-two, we round it up to the + * next power of two. */ - assert((maxDist & (maxDist - 1)) == 0); + assert(roundedMaxDist >= maxDist); + assert(roundedMaxDist < maxDist + 7 * (maxDist >> 3)); + assert((roundedMaxDist & (roundedMaxDist - 1)) == 0); assert((curr & cycleMask) == (newCurrent & cycleMask)); assert(curr > newCurrent); if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) { @@ -1415,9 +1473,9 @@ U32 ZSTD_window_update(ZSTD_window_t* window, /** * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix. */ -MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr) { - U32 const maxDistance = 1U << windowLog; + U32 const maxDistance = ZSTD_windowSize(&ms->cParams); U32 const lowestValid = ms->window.lowLimit; U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); @@ -1432,9 +1490,9 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr, u /** * Returns the lowest allowed match index in the prefix. */ -MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_MatchState_t* ms, U32 curr) { - U32 const maxDistance = 1U << windowLog; + U32 const maxDistance = ZSTD_windowSize(&ms->cParams); U32 const lowestValid = ms->window.dictLimit; U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 9c23ad57400..8fdb3062de5 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -116,7 +116,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( const BYTE* anchor = istart; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); /* presumes that, if there is a dictionary, it must be using Attach mode */ - const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); + const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex); const BYTE* const prefixLowest = base + prefixLowestIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; @@ -157,7 +157,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( ip += ((ip - prefixLowest) == 0); { U32 const current = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current); U32 const maxRep = current - windowLow; if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0; @@ -341,7 +341,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( const BYTE* anchor = istart; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); /* presumes that, if there is a dictionary, it must be using Attach mode */ - const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); + const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex); const BYTE* const prefixLowest = base + prefixLowestIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; @@ -363,7 +363,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_dictMatchState_generic"); /* if a dictionary is attached, it must be within window range */ - assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex); + assert(ms->window.dictLimit + ZSTD_windowSize(cParams) >= endIndex); if (ms->prefetchCDictTables) { size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32); @@ -624,7 +624,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* const ilimit = iend - 8; const BYTE* const base = ms->window.base; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); + const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex); const U32 dictStartIndex = lowLimit; const U32 dictLimit = ms->window.dictLimit; const U32 prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit; diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index ebd547719e4..2145353f233 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -201,7 +201,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( const BYTE* const base = ms->window.base; const BYTE* const istart = (const BYTE*)src; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); + const U32 prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex); const BYTE* const prefixStart = base + prefixStartIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; @@ -237,7 +237,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); ip0 += (ip0 == prefixStart); { U32 const curr = (U32)(ip0 - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr); U32 const maxRep = curr - windowLow; if (rep_offset2 > maxRep) offsetSaved2 = rep_offset2, rep_offset2 = 0; if (rep_offset1 > maxRep) offsetSaved1 = rep_offset1, rep_offset1 = 0; @@ -513,7 +513,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( /* if a dictionary is still attached, it necessarily means that * it is within window size. So we just check it. */ - const U32 maxDistance = 1U << cParams->windowLog; + const U32 maxDistance = ZSTD_windowSize(cParams); const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); assert(endIndex - prefixStartIndex <= maxDistance); (void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */ @@ -720,7 +720,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic( const BYTE* const istart = (const BYTE*)src; const BYTE* anchor = istart; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); + const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex); const U32 dictStartIndex = lowLimit; const BYTE* const dictStart = dictBase + dictStartIndex; const U32 dictLimit = ms->window.dictLimit; diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index d9206b669e9..f3cbc7f73ef 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -94,7 +94,7 @@ void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */ U32 dummy32; /* to be nullified at the end */ U32 const windowValid = ms->window.lowLimit; - U32 const maxDistance = 1U << cParams->windowLog; + U32 const maxDistance = ZSTD_windowSize(cParams); U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid; @@ -254,7 +254,7 @@ size_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms, const BYTE* const base = ms->window.base; U32 const curr = (U32)(ip-base); - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr); U32* const bt = ms->chainTable; U32 const btLog = cParams->chainLog - 1; @@ -680,7 +680,7 @@ size_t ZSTD_HcFindBestMatch( const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const U32 curr = (U32)(ip-base); - const U32 maxDistance = 1U << cParams->windowLog; + const U32 maxDistance = ZSTD_windowSize(cParams); const U32 lowestValid = ms->window.lowLimit; const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; const U32 isDictionary = (ms->loadedDictEnd != 0); @@ -1156,7 +1156,7 @@ size_t ZSTD_RowFindBestMatch( const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const U32 curr = (U32)(ip-base); - const U32 maxDistance = 1U << cParams->windowLog; + const U32 maxDistance = ZSTD_windowSize(cParams); const U32 lowestValid = ms->window.lowLimit; const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; const U32 isDictionary = (ms->loadedDictEnd != 0); @@ -1551,7 +1551,7 @@ size_t ZSTD_compressBlock_lazy_generic( ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { U32 const curr = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, ms->cParams.windowLog); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr); U32 const maxRep = curr - windowLow; if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0; @@ -1951,7 +1951,6 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const BYTE* const dictBase = ms->window.dictBase; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const dictStart = dictBase + ms->window.lowLimit; - const U32 windowLog = ms->cParams.windowLog; const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6); const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); @@ -1982,7 +1981,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( U32 curr = (U32)(ip-base); /* check repCode */ - { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1, windowLog); + { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1); const U32 repIndex = (U32)(curr+1 - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; @@ -2023,7 +2022,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( curr++; /* check repCode */ if (offBase) { - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr); const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; @@ -2055,7 +2054,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( curr++; /* check repCode */ if (offBase) { - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr); const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; @@ -2109,7 +2108,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( /* check immediate repcode */ while (ip <= ilimit) { const U32 repCurrent = (U32)(ip-base); - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, repCurrent, windowLog); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, repCurrent); const U32 repIndex = repCurrent - offset_2; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index f68e29627e7..894830d82fe 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -136,6 +136,7 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, const ZSTD_CParams* cParams) { params->windowLog = cParams->windowLog; + params->windowFrac = cParams->windowFrac; ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX); DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (params->hashRateLog == 0) { @@ -527,7 +528,7 @@ size_t ZSTD_ldm_generateSequences( ldmState_t* ldmState, RawSeqStore_t* sequences, ldmParams_t const* params, void const* src, size_t srcSize) { - U32 const maxDist = 1U << params->windowLog; + U32 const maxDist = ZSTD_windowSizeLDM(params); BYTE const* const istart = (BYTE const*)src; BYTE const* const iend = istart + srcSize; size_t const kMaxChunkSize = 1 << 20; diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 65ea8bedbae..3b8584badae 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -468,7 +468,7 @@ U32 ZSTD_insertBt1( /* windowLow is based on target because * we only need positions that will be in the window at the end of the tree update. */ - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, target, cParams->windowLog); + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, target); U32 matchEndIdx = curr+8+1; size_t bestLength = 8; U32 nbCompares = 1U << cParams->searchLog; @@ -616,7 +616,7 @@ ZSTD_insertBtAndGetAllMatches ( const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; U32 const btLow = (btMask >= curr) ? 0 : curr - btMask; - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr); U32 const matchLow = windowLow ? windowLow : 1; U32* smallerPtr = bt + 2*(curr&btMask); U32* largerPtr = bt + 2*(curr&btMask) + 1; diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index cebda55bff3..9168fefb7ac 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -494,7 +494,7 @@ ZSTDMT_serialState_reset(SerialState* serialState, { /* Adjust parameters */ if (params.ldmParams.enableLdm == ZSTD_ps_enable) { - DEBUGLOG(4, "LDM window size = %u KB", (1U << params.cParams.windowLog) >> 10); + DEBUGLOG(4, "LDM window size = %u KB", ZSTD_windowSize(¶ms.cParams) >> 10); ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams); assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); assert(params.ldmParams.hashRateLog < 32); @@ -1095,13 +1095,15 @@ static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers) * New parameters will be applied to next compression job. */ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams) { - U32 const saved_wlog = mtctx->params.cParams.windowLog; /* Do not modify windowLog while compressing */ + U32 const saved_wlog = mtctx->params.cParams.windowLog; /* Do not modify windowLog while compressing */ + U32 const saved_wfrac = mtctx->params.cParams.windowFrac; /* Do not modify windowFrac while compressing */ int const compressionLevel = cctxParams->compressionLevel; DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; { ZSTD_CParams cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); cParams.windowLog = saved_wlog; + cParams.windowFrac = saved_wfrac; mtctx->params.cParams = cParams; } } @@ -1313,7 +1315,7 @@ size_t ZSTDMT_initCStream_internal( ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize)); { /* If ldm is enabled we need windowSize space. */ - size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? (1U << mtctx->params.cParams.windowLog) : 0; + size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? ZSTD_windowSize(&mtctx->params.cParams) : 0; /* Two buffers of slack, plus extra space for the overlap * This is the minimum slack that LDM works with. One extra because * flush might waste up to targetSectionSize-1 bytes. Another extra From 3e308e28f977c1e4a6076ca1d93a23c2ca83979d Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Jan 2025 08:46:43 -0800 Subject: [PATCH 07/36] Easy: Rename Arg to `ZSTD_cycleLog` --- lib/compress/zstd_compress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 23ccc3ed1c7..01648eed2ed 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1445,10 +1445,10 @@ ZSTD_clampCParams(ZSTD_CParams cParams) /** ZSTD_cycleLog() : * condition for correct operation : hashLog > 1 */ -U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) +U32 ZSTD_cycleLog(U32 chainLog, ZSTD_strategy strat) { U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2); - return hashLog - btScale; + return chainLog - btScale; } /** ZSTD_dictAndWindowLog() : From a8da4549b6471d5a640274b691a7d55c70ba89ee Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Jan 2025 10:50:27 -0800 Subject: [PATCH 08/36] Trivial `fuzzer.c` Additions --- tests/fuzzer.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 868df78a0cc..0bf77f04d62 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1771,6 +1771,8 @@ static int basicUnitTests(U32 const seed, double compressibility) CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); CHECK_EQ(value, 0); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowFrac, &value)); + CHECK_EQ(value, 0); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); CHECK_EQ(value, 0); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); @@ -1789,6 +1791,8 @@ static int basicUnitTests(U32 const seed, double compressibility) CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); CHECK_EQ(value, (int)cparams.windowLog); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowFrac, &value)); + CHECK_EQ(value, 0); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); CHECK_EQ(value, (int)cparams.chainLog); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); @@ -1839,6 +1843,8 @@ static int basicUnitTests(U32 const seed, double compressibility) CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); CHECK_EQ(value, 0); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowFrac, &value)); + CHECK_EQ(value, 0); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); CHECK_EQ(value, 0); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); @@ -1866,6 +1872,8 @@ static int basicUnitTests(U32 const seed, double compressibility) CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); CHECK_EQ(value, (int)params.cParams.windowLog); + CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowFrac, &value)); + CHECK_EQ(value, 0); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value)); CHECK_EQ(value, (int)params.cParams.chainLog); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value)); From 301a34dd44a367df3df2e94af5c728e8a19c89dc Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Jan 2025 13:52:26 -0800 Subject: [PATCH 09/36] Macro Guard to Control Picking Fractional Window Sizes --- lib/compress/zstd_compress.c | 23 +++++++---------- lib/compress/zstd_compress_internal.h | 37 +++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 01648eed2ed..95b3b59b575 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1461,12 +1461,11 @@ U32 ZSTD_cycleLog(U32 chainLog, ZSTD_strategy strat) */ static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSize) { - const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX; /* No dictionary ==> No change */ if (dictSize == 0) { return; } - assert(cParams->windowLog <= ZSTD_WINDOWLOG_MAX); + assert(cParams->windowLog + !!cParams->windowFrac <= ZSTD_WINDOWLOG_MAX); assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */ { U64 const windowSize = ZSTD_windowSize(cParams); @@ -1477,10 +1476,7 @@ static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSi */ if (windowSize >= dictSize + srcSize) { /* Window size large enough already */ - } else if (dictAndWindowSize >= maxWindowSize) { - cParams->windowLog = ZSTD_WINDOWLOG_MAX; /* Larger than max window log */ - cParams->windowFrac = 0; - } else { + } else { ZSTD_setMinimalWindowLogAndFrac(cParams, dictAndWindowSize); } } @@ -1725,7 +1721,10 @@ ZSTD_CParams ZSTD_getCParamsFromCCtxParams( srcSizeHint = (U64)CCtxParams->srcSizeHint; } cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); - if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; + if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) { + cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; + cParams.windowFrac = 0; + } ZSTD_overrideCParams(&cParams, &CCtxParams->cParams); assert(!ZSTD_checkCParams_internal(cParams)); /* srcSizeHint == 0 means 0 */ @@ -4702,8 +4701,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, U32 const maxDist = ZSTD_windowSize(&cctx->appliedParams.cParams); S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; - assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); - assert(cctx->appliedParams.cParams.windowFrac == 0 || cctx->appliedParams.cParams.windowLog != ZSTD_WINDOWLOG_MAX); + assert(cctx->appliedParams.cParams.windowLog + !!cctx->appliedParams.cParams.windowFrac <= ZSTD_WINDOWLOG_MAX); DEBUGLOG(5, "ZSTD_compress_frameChunk (srcSize=%u, blockSizeMax=%u)", (unsigned)srcSize, (unsigned)blockSizeMax); if (cctx->appliedParams.fParams.checksumFlag && srcSize) @@ -5979,11 +5977,8 @@ static size_t ZSTD_compressBegin_usingCDict_internal( */ if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); - U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1; - U32 const curWindowLog = cctxParams.cParams.windowLog; - if (limitedSrcLog > curWindowLog) { - cctxParams.cParams.windowLog = limitedSrcLog; - cctxParams.cParams.windowFrac = 0; + if (limitedSrcSize > 1 && ZSTD_windowSize(&cctxParams.cParams) < limitedSrcSize) { + ZSTD_setMinimalWindowLogAndFrac(&cctxParams.cParams, limitedSrcSize); } } return ZSTD_compressBegin_internal(cctx, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ce0ab182451..50c22257253 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1101,6 +1101,18 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) ZSTD_noDict; } +/** + * Fractional window sizes can always be picked by the user explicitly + * setting ZSTD_c_windowFrac. This macro controls whether, when Zstd is + * picking a window size itself, it is allowed to pick a non-power-of-two + * window size. + * + * For now, this defaults to false. + */ +#ifndef ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES +#define ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES 0 +#endif + /** * Return the window size described by the windowLog and windowFrac in the * provided CParams. @@ -1114,11 +1126,18 @@ MEM_STATIC U32 ZSTD_windowSizeLDM(const ldmParams_t* ldmParams) { /** * Checks that the selected windowSize satisfies the inequality - * srcSize <= windowSize <= srcSize * 1.25, in the range where the window + * `srcSize <= windowSize <= srcSize * margin`, in the range where the window + * isn't pressed up against one of the hard bounds, where `margin` is either + * 1.125 or 2, depending on whether we're allowed to pick fractional window + * sizes. */ MEM_STATIC int ZSTD_windowLogAndFracAreMinimal(ZSTD_CParams* cParams, const U32 srcSize) { const U32 lowerBound = MIN(srcSize, 1u << ZSTD_WINDOWLOG_MAX); - const U32 upperBound = MAX(srcSize + (srcSize >> 3), 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN); +#if ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES + const U32 upperBound = MAX(lowerBound + (lowerBound >> 3), 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN); +#else + const U32 upperBound = MAX(2 * lowerBound - 1, 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN); +#endif const U32 windowSize = ZSTD_windowSize(cParams); if (windowSize < lowerBound) { return 0; @@ -1135,6 +1154,7 @@ MEM_STATIC int ZSTD_windowLogAndFracAreMinimal(ZSTD_CParams* cParams, const U32 */ MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 srcSize) { const U32 minSize = 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN; +#if ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES if (srcSize < minSize) { cParams->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; cParams->windowFrac = 0; @@ -1147,6 +1167,19 @@ MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 cParams->windowLog++; } } +#else + if (srcSize < minSize) { + cParams->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; + cParams->windowFrac = 0; + } else { + cParams->windowLog = ZSTD_highbit32(srcSize - 1) + 1; + cParams->windowFrac = 0; + } +#endif + if (cParams->windowLog + !!cParams->windowFrac > ZSTD_WINDOWLOG_MAX) { + cParams->windowLog = ZSTD_WINDOWLOG_MAX; + cParams->windowFrac = 0; + } assert(ZSTD_windowLogAndFracAreMinimal(cParams, srcSize)); } From a2f3b98a3ffbbb214ae82995f29cc4e94ba2d674 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 3 Feb 2025 11:35:32 -0500 Subject: [PATCH 10/36] A Little More Bounds-Checking --- lib/compress/zstd_compress.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 95b3b59b575..e26eb1ace0d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1402,6 +1402,9 @@ size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams) { BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); BOUNDCHECK(ZSTD_c_windowFrac, (int)cParams.windowFrac); + RETURN_ERROR_IF( + cParams.windowLog + !!cParams.windowFrac > ZSTD_WINDOWLOG_MAX, + parameter_outOfBound, "Param out of bounds"); BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); @@ -1433,6 +1436,9 @@ ZSTD_clampCParams(ZSTD_CParams cParams) } while (0) # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) CLAMP(ZSTD_c_windowLog, cParams.windowLog); + if (ZSTD_c_windowLog == ZSTD_WINDOWLOG_MAX) { + cParams.windowFrac = 0; + } CLAMP(ZSTD_c_windowFrac, cParams.windowFrac); CLAMP(ZSTD_c_chainLog, cParams.chainLog); CLAMP(ZSTD_c_hashLog, cParams.hashLog); From 0561a5094aae6c3a94c50753c30e07e0d74d3b17 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 3 Feb 2025 12:16:02 -0500 Subject: [PATCH 11/36] Add Enablement Flag to Some GitHub Workflows We want to turn this on by default immediately after this release. And we want to thoroughly exercise the underlying code paths handling fractional windows, because they will be available in this upcoming release via new APIs (the explicit CCtx param and the constrain window for protocol path). And it's scary stuff. We can remove all these flags once we turn this on by default. --- .github/workflows/dev-long-tests.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index 899a57b754b..47af1c17aae 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -28,7 +28,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: make test - run: make test + run: MOREFLAGS="-DZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES=1" make test # lasts ~26mn make-test-macos: @@ -51,7 +51,7 @@ jobs: sudo apt-get -qqq update make libc6install make clean - CFLAGS="-m32 -O2" make -j test V=1 + CFLAGS="-m32 -O2" MOREFLAGS="-DZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES=1" make -j test V=1 no-intrinsics-fuzztest: runs-on: ubuntu-latest @@ -72,7 +72,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: ub + address sanitizer on zstreamtest - run: CC=clang make uasan-test-zstream + run: CC=clang MOREFLAGS="-DZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES=1" make uasan-test-zstream # lasts ~15mn tsan-fuzztest: @@ -91,7 +91,7 @@ jobs: run: | sudo apt-get -qqq update make libc6install - CC=clang make -C tests test-zstream32 FUZZER_FLAGS="--big-tests" + CC=clang MOREFLAGS="-DZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES=1" make -C tests test-zstream32 FUZZER_FLAGS="--big-tests" # lasts ~23mn gcc-8-asan-ubsan-testzstd: @@ -121,7 +121,7 @@ jobs: run: | sudo apt-get -qqq update make libc6install - make -j uasan-test-zstd32 V=1 + MOREFLAGS="-DZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES=1" make -j uasan-test-zstd32 V=1 # Note : external libraries must be turned off when using MSAN tests, # because they are not msan-instrumented, @@ -144,7 +144,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: clang + ASan + UBSan + Fuzz Test - run: CC=clang FUZZER_FLAGS="--long-tests" make clean uasan-fuzztest + run: CC=clang FUZZER_FLAGS="--long-tests" MOREFLAGS="-DZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES=1" make clean uasan-fuzztest gcc-asan-ubsan-fuzz32: runs-on: ubuntu-latest @@ -154,7 +154,7 @@ jobs: run: | sudo apt-get -qqq update make libc6install - CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest + CFLAGS="-O3 -m32" MOREFLAGS="-DZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES=1" FUZZER_FLAGS="--long-tests" make uasan-fuzztest clang-asan-fuzz32: runs-on: ubuntu-latest From fe80106ad6a0d03f54ddffd6b154b6aa903cf350 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 3 Feb 2025 15:08:30 -0500 Subject: [PATCH 12/36] Only Apply `windowFrac` when `windowLog` is Also Set --- lib/compress/zstd_compress.c | 3 ++- lib/zstd.h | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e26eb1ace0d..54c74b5e208 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1709,7 +1709,8 @@ static void ZSTD_overrideCParams( const ZSTD_CParams* overrides) { if (overrides->windowLog) cParams->windowLog = overrides->windowLog; - if (overrides->windowFrac) cParams->windowFrac = overrides->windowFrac; + /* An explicit windowFrac only applies if windowLog is set explicitly. */ + if (overrides->windowLog) cParams->windowFrac = overrides->windowFrac; if (overrides->hashLog) cParams->hashLog = overrides->hashLog; if (overrides->chainLog) cParams->chainLog = overrides->chainLog; if (overrides->searchLog) cParams->searchLog = overrides->searchLog; diff --git a/lib/zstd.h b/lib/zstd.h index 4b0dcab2ba7..222e1793dc3 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -2366,7 +2366,10 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo * and WF is the windowFrac. * * The valid range of values for this parameter is 0 to 7. The default value - * is 0. + * is 0. The value configured only takes effect if the windowLog has also + * explicitly been set. The windowFrac is ignored when the windowLog is + * ZSTD_WINDOWLOG_MAX (you can't select a window size larger than + * `2 ^ ZSTD_WINDOWLOG_MAX`). */ #define ZSTD_c_windowFrac ZSTD_c_experimentalParam21 From abc3d6f854df5da9c6353ab7c39a726b78e74a4e Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 5 Feb 2025 14:08:39 -0800 Subject: [PATCH 13/36] Avoid Illegal WL and WF Combos --- lib/compress/zstd_compress.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 54c74b5e208..af33ff3a8ce 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -801,11 +801,18 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, if (value!=0) /* 0 => use default */ BOUNDCHECK(ZSTD_c_windowLog, value); CCtxParams->cParams.windowLog = (U32)value; + if (value == ZSTD_WINDOWLOG_MAX) { + CCtxParams->cParams.windowFrac = 0; + } return CCtxParams->cParams.windowLog; case ZSTD_c_windowFrac : BOUNDCHECK(ZSTD_c_windowFrac, value); - CCtxParams->cParams.windowFrac = (U32)value; + if (CCtxParams->cParams.windowLog != ZSTD_WINDOWLOG_MAX) { + CCtxParams->cParams.windowFrac = (U32)value; + } else { + CCtxParams->cParams.windowFrac = 0; + } return CCtxParams->cParams.windowFrac; case ZSTD_c_hashLog : From 78996a609f121c36ae418f0bca3b059c918fbfd8 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 6 Feb 2025 11:02:13 -0500 Subject: [PATCH 14/36] Correct Corner-Case Bugs in Window Sizing I found some slight errors via the exhaustive testing added to the fuzzer. This commit fixes them. --- lib/compress/zstd_compress.c | 12 ++++++++++-- lib/compress/zstd_compress_internal.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index af33ff3a8ce..455ebf508e8 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1510,7 +1510,7 @@ ZSTD_adjustCParams_internal(ZSTD_CParams cPar, ZSTD_ParamSwitch_e useRowMatchFinder) { const U64 minSrcSize = 513; /* (1<<9) + 1 */ - const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); + const U64 maxWindowResize = 15ULL << (ZSTD_WINDOWLOG_MAX-4); assert(ZSTD_checkCParams_internal(cPar)==0); /* Cascade the selected strategy down to the next-highest one built into @@ -1591,7 +1591,15 @@ ZSTD_adjustCParams_internal(ZSTD_CParams cPar, if (tSize < hashSizeMin) { cPar.windowLog = ZSTD_HASHLOG_MIN; cPar.windowFrac = 0; - } else { + } else +#if !ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES + /* Prevents adjustment in the scenario where we have explicitly + * selected a fractional window size that is slightly larger than + * the src size hint. If we allow picking without this check, we + * might end up growing the window to the next power of two. */ + if (ZSTD_windowSize(&cPar) > (1u << (ZSTD_highbit32(tSize - 1) + 1))) +#endif + { ZSTD_setMinimalWindowLogAndFrac(&cPar, tSize); } } diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 50c22257253..22ba30c37bf 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1161,7 +1161,7 @@ MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 } else { const U32 srcSizeMinusOne = srcSize - 1; cParams->windowLog = ZSTD_highbit32(srcSizeMinusOne); - cParams->windowFrac = (((srcSizeMinusOne << 3) >> cParams->windowLog) & 7) + 1; + cParams->windowFrac = ((srcSizeMinusOne >> (cParams->windowLog - 3)) & 7) + 1; if (cParams->windowFrac == 8) { cParams->windowFrac = 0; cParams->windowLog++; From 9848c21b3d1beca74374ebe5da1e6b010666f796 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 5 Feb 2025 10:48:32 -0500 Subject: [PATCH 15/36] Exhaustive Testing of Window Sizing Combinations --- tests/fuzzer.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 0bf77f04d62..604a1898bac 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -43,6 +43,7 @@ #include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */ /* must be included after util.h, due to ERROR macro redefinition issue on Visual Studio */ #include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */ +#include "zstd_compress_internal.h" /* ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES */ #include "threading.h" /* ZSTD_pthread_create, ZSTD_pthread_join */ @@ -3385,6 +3386,108 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : check fractional window sizes : \n", testNb++); + { + int windowLog; + int windowFrac; + + for (windowLog = 0; windowLog <= ZSTD_WINDOWLOG_MAX; windowLog++) { + if (windowLog == 1) { + windowLog = ZSTD_WINDOWLOG_MIN; + } + for (windowFrac = 0; windowFrac <= 7; windowFrac++) { + int hint; + for (hint = 0; hint <= 1; hint++) { + unsigned long long inputSize; + for (inputSize = 100; inputSize < (3ull << ZSTD_WINDOWLOG_MAX); inputSize += (1ull << (ZSTD_highbit32(inputSize >> 4)))) { + ZSTD_inBuffer input = {CNBuffer, CNBuffSize, 0}; + ZSTD_outBuffer compressed = {compressedBuffer, compressedBufferSize, 0}; + ZSTD_FrameHeader zfh; + unsigned long long maxWindowSize; + + DISPLAYLEVEL(5, + "Checking %s input = 0x%16llx, windowLog = %2d, windowFrac = %d: ", + hint ? "hinted" : " fixed", + inputSize, windowLog, windowFrac); + + if (input.size > 16) { + /* We don't have to compress too much. */ + input.size = 16; + } + if (input.size > inputSize) { + input.size = (size_t)inputSize; + } + + ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, windowLog)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowFrac, windowFrac)); + if (hint) { + if (inputSize >= (1ull << 31)) { + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_srcSizeHint, (int)((1ull << 31) - 1))); + } else { + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_srcSizeHint, inputSize)); + } + } else { + CHECK_Z(ZSTD_CCtx_setPledgedSrcSize(cctx, inputSize)); + } + + CHECK_Z(ZSTD_compressStream2(cctx, &compressed, &input, inputSize == 0 ? ZSTD_e_end : ZSTD_e_flush)); + CHECK_LT(0, compressed.size); + + CHECK_Z(ZSTD_getFrameHeader(&zfh, compressed.dst, compressed.pos)); + if (!hint) { + CHECK_EQ(zfh.frameContentSize, inputSize); + } + + DISPLAYLEVEL(5, + "got frame size = 0x%16llx, window size = 0x%8llx, ", + zfh.frameContentSize, zfh.windowSize); + + maxWindowSize = 1ull << ZSTD_WINDOWLOG_MAX; + + if (windowLog != 0 && maxWindowSize > (1ull << windowLog)) { + maxWindowSize = ((8ull + windowFrac) << windowLog) >> 3; + } + + if (!hint) { + if (maxWindowSize > inputSize) { + maxWindowSize = inputSize; + } + } else { + int winLogAndFrac; + for (winLogAndFrac = ZSTD_WINDOWLOG_MIN << 3; winLogAndFrac < (ZSTD_WINDOWLOG_MAX << 3); winLogAndFrac++) { + unsigned long long candidateWindowSize = ((8ull + (winLogAndFrac & 7)) << (winLogAndFrac >> 3)) >> 3; + if (candidateWindowSize >= inputSize && (windowLog == 0 || maxWindowSize > candidateWindowSize)) { + maxWindowSize = candidateWindowSize; + break; + } +#if !ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES + winLogAndFrac += 7; /* skip over fractional windows */ +#endif + } + } + + if (hint && (maxWindowSize < (1ull << ZSTD_WINDOWLOG_MIN))) { + maxWindowSize = 1ull << ZSTD_WINDOWLOG_MIN; + } + + DISPLAYLEVEL(5, + "expected window size = 0x%16llx\n", + maxWindowSize); + + if (windowLog != 0) { + CHECK_EQ(zfh.windowSize, maxWindowSize); + } else { + CHECK_LT(zfh.windowSize, maxWindowSize + 1); + } + } + } + } + } + } + DISPLAYLEVEL(3, "OK \n"); + ZSTD_freeCCtx(cctx); free(dictBuffer); free(samplesSizes); From 705a5b27c6140f67012be09419e552cb1e2157b1 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 6 Feb 2025 11:19:00 -0500 Subject: [PATCH 16/36] Add WindowFrac Param to Fuzz Tests --- tests/fuzz/sequence_compression_api.c | 15 +++++++++++---- tests/fuzz/zstd_helpers.c | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/fuzz/sequence_compression_api.c b/tests/fuzz/sequence_compression_api.c index 9295d248ccd..f2ad92a7b11 100644 --- a/tests/fuzz/sequence_compression_api.c +++ b/tests/fuzz/sequence_compression_api.c @@ -142,10 +142,11 @@ static size_t decodeSequences(void* dst, size_t nbSequences, */ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, size_t literalsSizeLimit, size_t dictSize, - size_t windowLog, ZSTD_SequenceFormat_e mode) + uint32_t windowLog, uint32_t windowFrac, + ZSTD_SequenceFormat_e mode) { const uint32_t repCode = 0; /* not used by sequence ingestion api */ - size_t windowSize = 1ULL << windowLog; + uint64_t windowSize = ((8ULL + windowFrac) << windowLog) >> 3; size_t blockSizeMax = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); uint32_t matchLengthMax = ZSTD_FUZZ_MATCHLENGTH_MAXSIZE; uint32_t bytesGenerated = 0; @@ -346,6 +347,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size) size_t dictSize = 0; unsigned hasDict; unsigned wLog; + unsigned wFrac; int cLevel; ZSTD_SequenceFormat_e mode; @@ -361,8 +363,12 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size) FUZZ_ASSERT(dctx); } - /* Generate window log first so we don't generate offsets too large */ + /* Generate window size first so we don't generate offsets too large */ wLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX); + wFrac = FUZZ_dataProducer_uint32Range(producer, 0, 7); + if (wLog == ZSTD_WINDOWLOG_MAX) { + wFrac = 0; + } cLevel = FUZZ_dataProducer_int32Range(producer, -3, 22); mode = (ZSTD_SequenceFormat_e)FUZZ_dataProducer_int32Range(producer, 0, 1); @@ -370,6 +376,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size) ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0); ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel); ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)wLog); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowFrac, (int)wFrac); ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, ZSTD_MINMATCH_MIN); ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1); ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, (int)mode); @@ -415,7 +422,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size) generatedSrc = FUZZ_malloc(ZSTD_FUZZ_GENERATED_SRC_MAXSIZE); } - nbSequences = generateRandomSequences(producer, ZSTD_FUZZ_GENERATED_LITERALS_SIZE, dictSize, wLog, mode); + nbSequences = generateRandomSequences(producer, ZSTD_FUZZ_GENERATED_LITERALS_SIZE, dictSize, wLog, wFrac, mode); generatedSrcSize = decodeSequences(generatedSrc, nbSequences, ZSTD_FUZZ_GENERATED_LITERALS_SIZE, dictBuffer, dictSize, mode); /* Note : in explicit block delimiters mode, diff --git a/tests/fuzz/zstd_helpers.c b/tests/fuzz/zstd_helpers.c index f3b2e6fba4c..755b81b6c26 100644 --- a/tests/fuzz/zstd_helpers.c +++ b/tests/fuzz/zstd_helpers.c @@ -102,6 +102,7 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer { ZSTD_compressionParameters cParams = FUZZ_randomCParams(srcSize, producer); set(cctx, ZSTD_c_windowLog, cParams.windowLog); + setRand(cctx, ZSTD_c_windowFrac, 0, 7, producer); set(cctx, ZSTD_c_hashLog, cParams.hashLog); set(cctx, ZSTD_c_chainLog, cParams.chainLog); set(cctx, ZSTD_c_searchLog, cParams.searchLog); From d7205585ba9ffe01f22cd7d854aede087d957ac1 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 6 Feb 2025 12:25:08 -0800 Subject: [PATCH 17/36] Add Advanced Parameter to CLI to Set Window Fraction --- programs/fileio.c | 6 ++++++ programs/fileio.h | 1 + programs/fileio_types.h | 1 + programs/zstdcli.c | 7 +++++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 0ecca40d2ab..593e9b402e7 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -308,6 +308,7 @@ FIO_prefs_t* FIO_createPreferences(void) ret->allowBlockDevices = 0; ret->asyncIO = AIO_supported(); ret->passThrough = -1; + ret->windowFrac = 0; return ret; } @@ -427,6 +428,10 @@ void FIO_setLiteralCompressionMode( prefs->literalCompressionMode = mode; } +void FIO_setWindowFrac(FIO_prefs_t* const prefs, int windowFrac) { + prefs->windowFrac = windowFrac; +} + void FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel) { #ifndef ZSTD_NOCOMPRESS @@ -1171,6 +1176,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_useRowMatchFinder, prefs->useRowMatchFinder)); /* compression parameters */ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, (int)comprParams.windowLog) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowFrac, prefs->windowFrac) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, (int)comprParams.chainLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, (int)comprParams.hashLog) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, (int)comprParams.searchLog) ); diff --git a/programs/fileio.h b/programs/fileio.h index cb53ef53781..bb36922cf96 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -91,6 +91,7 @@ void FIO_setTestMode(FIO_prefs_t* const prefs, int testMode); void FIO_setLiteralCompressionMode( FIO_prefs_t* const prefs, ZSTD_ParamSwitch_e mode); +void FIO_setWindowFrac(FIO_prefs_t* const prefs, int windowFrac); void FIO_setProgressSetting(FIO_progressSetting_e progressSetting); void FIO_setNotificationLevel(int level); diff --git a/programs/fileio_types.h b/programs/fileio_types.h index 23bda4168d8..6b573da4837 100644 --- a/programs/fileio_types.h +++ b/programs/fileio_types.h @@ -54,6 +54,7 @@ typedef struct FIO_prefs_s { int srcSizeHint; int testMode; ZSTD_ParamSwitch_e literalCompressionMode; + int windowFrac; /* IO preferences */ int removeSrcFile; diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 83d9b881e50..03291d59879 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -616,10 +616,11 @@ static unsigned parseAdaptParameters(const char* stringPtr, int* adaptMinPtr, in * @return 1 means that compression parameters were correct * @return 0 in case of malformed parameters */ -static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressionParameters* params) +static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressionParameters* params, int* windowFrac) { for ( ; ;) { if (longCommandWArg(&stringPtr, "windowLog=") || longCommandWArg(&stringPtr, "wlog=")) { params->windowLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } + if (longCommandWArg(&stringPtr, "windowFrac=") || longCommandWArg(&stringPtr, "wfrac=")) { *windowFrac = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } if (longCommandWArg(&stringPtr, "chainLog=") || longCommandWArg(&stringPtr, "clog=")) { params->chainLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } if (longCommandWArg(&stringPtr, "hashLog=") || longCommandWArg(&stringPtr, "hlog=")) { params->hashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } if (longCommandWArg(&stringPtr, "searchLog=") || longCommandWArg(&stringPtr, "slog=")) { params->searchLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } @@ -878,6 +879,7 @@ int main(int argCount, const char* argv[]) FIO_progressSetting_e progress = FIO_ps_auto; zstd_operation_mode operation = zom_compress; ZSTD_compressionParameters compressionParams; + int windowFrac = 0; int cLevel = init_cLevel(); int cLevelLast = MINCLEVEL - 1; /* lower than minimum */ unsigned recursive = 0; @@ -1076,7 +1078,7 @@ int main(int argCount, const char* argv[]) if (longCommandWArg(&argument, "--block-size")) { NEXT_TSIZE(blockSize); continue; } if (longCommandWArg(&argument, "--maxdict")) { NEXT_UINT32(maxDictSize); continue; } if (longCommandWArg(&argument, "--dictID")) { NEXT_UINT32(dictID); continue; } - if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } ; cType = FIO_zstdCompression; continue; } + if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams, &windowFrac)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } ; cType = FIO_zstdCompression; continue; } if (longCommandWArg(&argument, "--stream-size")) { NEXT_TSIZE(streamSrcSize); continue; } if (longCommandWArg(&argument, "--target-compressed-block-size")) { NEXT_TSIZE(targetCBlockSize); continue; } if (longCommandWArg(&argument, "--size-hint")) { NEXT_TSIZE(srcSizeHint); continue; } @@ -1600,6 +1602,7 @@ int main(int argCount, const char* argv[]) FIO_setSrcSizeHint(prefs, srcSizeHint); FIO_setLiteralCompressionMode(prefs, literalCompressionMode); FIO_setSparseWrite(prefs, 0); + FIO_setWindowFrac(prefs, windowFrac); if (adaptMin > cLevel) cLevel = adaptMin; if (adaptMax < cLevel) cLevel = adaptMax; From 8b12bd62cf1cf87f37ff48bd4730583208252fde Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 6 Feb 2025 12:38:25 -0800 Subject: [PATCH 18/36] Add Man Page Documentation --- programs/zstd.1.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index e5c1b7fd215..e602c106990 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -387,6 +387,18 @@ The list of available _options_: Note: If `windowLog` is set to larger than 27, `--long=windowLog` or `--memory=windowSize` needs to be passed to the decompressor. +- `windowFrac`=_wfrac_, `wfrac`=_wfrac_: + Set the window size to a non-power-of-two value, as an adjustment to the + power-of-two window size set by the `windowLog` parameter. + + The Zstd format supports expressing window sizes as + `(1 + wfrac / 8) * (2 ^ wlog)` where `wfrac` has an integer value between + 0 and 7 inclusive and `wlog` has an integer value between 10 and 41. + (Although see the documentation on `windowLog` above.) + + This parameter has no effect unless the `windowLog` is also set. It also + has no effect when the `windowLog` is set to its maximum supported value. + - `hashLog`=_hlog_, `hlog`=_hlog_: Specify the maximum number of bits for a hash table. From 2af69f9f43faa07b995dc2485e23b6e22566f3cc Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 6 Feb 2025 12:44:57 -0800 Subject: [PATCH 19/36] Add CLI Test for Fractional Window Size Param --- tests/cli-tests/compression/window-frac.sh | 6 ++++++ tests/cli-tests/compression/window-frac.sh.stderr.ignore | 0 tests/cli-tests/compression/window-frac.sh.stdout.glob | 5 +++++ 3 files changed, 11 insertions(+) create mode 100755 tests/cli-tests/compression/window-frac.sh create mode 100644 tests/cli-tests/compression/window-frac.sh.stderr.ignore create mode 100644 tests/cli-tests/compression/window-frac.sh.stdout.glob diff --git a/tests/cli-tests/compression/window-frac.sh b/tests/cli-tests/compression/window-frac.sh new file mode 100755 index 00000000000..507f6036480 --- /dev/null +++ b/tests/cli-tests/compression/window-frac.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e + +zstd --zstd=wlog=21,wfrac=5 < file > file.zst +zstd -vv -l file.zst diff --git a/tests/cli-tests/compression/window-frac.sh.stderr.ignore b/tests/cli-tests/compression/window-frac.sh.stderr.ignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/cli-tests/compression/window-frac.sh.stdout.glob b/tests/cli-tests/compression/window-frac.sh.stdout.glob new file mode 100644 index 00000000000..d26dbedfa06 --- /dev/null +++ b/tests/cli-tests/compression/window-frac.sh.stdout.glob @@ -0,0 +1,5 @@ +file.zst +# Zstandard Frames: 1 +... +Window Size: 3407872 B (3407872 B) +... \ No newline at end of file From 72c38c9be770180006fb2743c2ceb4a7b5dc25c0 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 7 Feb 2025 10:30:32 -0500 Subject: [PATCH 20/36] Fix Various Contbuild Warnings --- lib/compress/zstd_compress.c | 56 ++++++++++++++++++------------------ tests/fuzzer.c | 4 +-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 455ebf508e8..8115440fd60 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1490,7 +1490,7 @@ static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSi if (windowSize >= dictSize + srcSize) { /* Window size large enough already */ } else { - ZSTD_setMinimalWindowLogAndFrac(cParams, dictAndWindowSize); + ZSTD_setMinimalWindowLogAndFrac(cParams, (U32)dictAndWindowSize); } } } @@ -1677,43 +1677,43 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, ZSTD_CParams ZSTD_getCParamsFromPublicCParams( ZSTD_compressionParameters cParams) { - return (ZSTD_CParams){ - cParams.windowLog, - 0, /* windowFrac */ - cParams.chainLog, - cParams.hashLog, - cParams.searchLog, - cParams.minMatch, - cParams.targetLength, - cParams.strategy - }; + ZSTD_CParams ret; + ret.windowLog = cParams.windowLog; + ret.windowFrac = 0; + ret.chainLog = cParams.chainLog; + ret.hashLog = cParams.hashLog; + ret.searchLog = cParams.searchLog; + ret.minMatch = cParams.minMatch; + ret.targetLength = cParams.targetLength; + ret.strategy = cParams.strategy; + return ret; } ZSTD_compressionParameters ZSTD_getPublicCParamsFromCParams( ZSTD_CParams cParams) { - return (ZSTD_compressionParameters){ - cParams.windowLog, - cParams.chainLog, - cParams.hashLog, - cParams.searchLog, - cParams.minMatch, - cParams.targetLength, - cParams.strategy - }; + ZSTD_compressionParameters ret; + ret.windowLog = cParams.windowLog; + ret.chainLog = cParams.chainLog; + ret.hashLog = cParams.hashLog; + ret.searchLog = cParams.searchLog; + ret.minMatch = cParams.minMatch; + ret.targetLength = cParams.targetLength; + ret.strategy = cParams.strategy; + return ret; } ZSTD_Params ZSTD_getParamsFromPublicParams(ZSTD_parameters params) { - return (ZSTD_Params){ - ZSTD_getCParamsFromPublicCParams(params.cParams), - params.fParams - }; + ZSTD_Params ret; + ret.cParams = ZSTD_getCParamsFromPublicCParams(params.cParams); + ret.fParams = params.fParams; + return ret; } ZSTD_parameters ZSTD_getPublicParamsFromParams(ZSTD_Params params) { - return (ZSTD_parameters){ - ZSTD_getPublicCParamsFromCParams(params.cParams), - params.fParams - }; + ZSTD_parameters ret; + ret.cParams = ZSTD_getPublicCParamsFromCParams(params.cParams); + ret.fParams = params.fParams; + return ret; } static ZSTD_CParams ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 604a1898bac..213cfd9ba90 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3399,7 +3399,7 @@ static int basicUnitTests(U32 const seed, double compressibility) int hint; for (hint = 0; hint <= 1; hint++) { unsigned long long inputSize; - for (inputSize = 100; inputSize < (3ull << ZSTD_WINDOWLOG_MAX); inputSize += (1ull << (ZSTD_highbit32(inputSize >> 4)))) { + for (inputSize = 100; inputSize < (3ull << ZSTD_WINDOWLOG_MAX); inputSize += (1ull << (ZSTD_highbit32((U32)(inputSize >> 4))))) { ZSTD_inBuffer input = {CNBuffer, CNBuffSize, 0}; ZSTD_outBuffer compressed = {compressedBuffer, compressedBufferSize, 0}; ZSTD_FrameHeader zfh; @@ -3426,7 +3426,7 @@ static int basicUnitTests(U32 const seed, double compressibility) if (inputSize >= (1ull << 31)) { CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_srcSizeHint, (int)((1ull << 31) - 1))); } else { - CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_srcSizeHint, inputSize)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_srcSizeHint, (int)inputSize)); } } else { CHECK_Z(ZSTD_CCtx_setPledgedSrcSize(cctx, inputSize)); From 80bf0845f08e26bd6093906df4a1ef8fc4cac8fa Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 18 Feb 2025 09:34:07 -0800 Subject: [PATCH 21/36] Fix Hash-Table Sizing of Small Inputs For inputs smaller than `1 << ZSTD_WINDOWLOG_MIN` bytes, the pre-existing code in `ZSTD_adjustCParams_internal()` temporarily calculated an illegally small window log for the purposes of adjusting the hash- and chain-table sizes, before fixing that bad window log to comply with the minimums. The new code clamped the window log earlier and therefore didn't shrink the tables as much. This commit fixes that to mirror the pre-existing behavior. This resolves the remaining regression test differences. --- lib/compress/zstd_compress.c | 7 ++++--- lib/compress/zstd_compress_internal.h | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 8115440fd60..b03f2d2e706 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1490,7 +1490,7 @@ static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSi if (windowSize >= dictSize + srcSize) { /* Window size large enough already */ } else { - ZSTD_setMinimalWindowLogAndFrac(cParams, (U32)dictAndWindowSize); + ZSTD_setMinimalWindowLogAndFrac(cParams, (U32)dictAndWindowSize, ZSTD_WINDOWLOG_MIN); } } } @@ -1600,7 +1600,8 @@ ZSTD_adjustCParams_internal(ZSTD_CParams cPar, if (ZSTD_windowSize(&cPar) > (1u << (ZSTD_highbit32(tSize - 1) + 1))) #endif { - ZSTD_setMinimalWindowLogAndFrac(&cPar, tSize); + const U32 tmpMinWindowLog = ZSTD_HASHLOG_MIN < ZSTD_WINDOWLOG_MIN ? ZSTD_HASHLOG_MIN : ZSTD_WINDOWLOG_MIN; + ZSTD_setMinimalWindowLogAndFrac(&cPar, tSize, tmpMinWindowLog); } } } @@ -6000,7 +6001,7 @@ static size_t ZSTD_compressBegin_usingCDict_internal( if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); if (limitedSrcSize > 1 && ZSTD_windowSize(&cctxParams.cParams) < limitedSrcSize) { - ZSTD_setMinimalWindowLogAndFrac(&cctxParams.cParams, limitedSrcSize); + ZSTD_setMinimalWindowLogAndFrac(&cctxParams.cParams, limitedSrcSize, ZSTD_WINDOWLOG_MIN); } } return ZSTD_compressBegin_internal(cctx, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 22ba30c37bf..d9f5a3b45ad 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1152,11 +1152,11 @@ MEM_STATIC int ZSTD_windowLogAndFracAreMinimal(ZSTD_CParams* cParams, const U32 * Calculates the minimum legal window log and fraction that contain the * provided source size. */ -MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 srcSize) { - const U32 minSize = 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN; +MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 srcSize, const U32 minWindowLog) { + const U32 minSize = 1u << minWindowLog; #if ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES if (srcSize < minSize) { - cParams->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; + cParams->windowLog = minWindowLog; cParams->windowFrac = 0; } else { const U32 srcSizeMinusOne = srcSize - 1; @@ -1169,7 +1169,7 @@ MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 } #else if (srcSize < minSize) { - cParams->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; + cParams->windowLog = minWindowLog; cParams->windowFrac = 0; } else { cParams->windowLog = ZSTD_highbit32(srcSize - 1) + 1; From 240410116a369310c576f7cc537cdc9d957b4417 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 7 Feb 2025 11:31:28 -0500 Subject: [PATCH 22/36] ZSTD_MatchState_t Stores CCtxParams Pointer, not CParams This also means the CDict needs to store and init a CCtxParams object. --- lib/compress/zstd_compress.c | 30 ++++++-------- lib/compress/zstd_compress_internal.h | 8 ++-- lib/compress/zstd_double_fast.c | 18 ++++---- lib/compress/zstd_fast.c | 20 ++++----- lib/compress/zstd_lazy.c | 59 ++++++++++++++------------- lib/compress/zstd_ldm.c | 4 +- lib/compress/zstd_opt.c | 14 +++---- 7 files changed, 76 insertions(+), 77 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b03f2d2e706..ddca51ccdb1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -87,6 +87,7 @@ struct ZSTD_CDict_s { ZSTD_compressedBlockState_t cBlockState; ZSTD_customMem customMem; U32 dictID; + ZSTD_CCtx_params params; /* storage for matchState.cctxParams pointer */ int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */ ZSTD_ParamSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use * row-based matchfinder. Unless the cdict is reloaded, we will use @@ -2102,12 +2103,12 @@ static void ZSTD_advanceHashSalt(ZSTD_MatchState_t* ms) { static size_t ZSTD_reset_matchState(ZSTD_MatchState_t* ms, ZSTD_cwksp* ws, - const ZSTD_CParams* cParams, - const ZSTD_ParamSwitch_e useRowMatchFinder, const ZSTD_compResetPolicy_e crp, const ZSTD_indexResetPolicy_e forceResetIndex, const ZSTD_resetTarget_e forWho) { + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_ParamSwitch_e useRowMatchFinder = ms->cctxParams->useRowMatchFinder; /* disable chain table allocation for fast or row-based strategies */ size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, ms->dedicatedDictSearch && (forWho == ZSTD_resetTarget_CDict)) @@ -2179,8 +2180,6 @@ ZSTD_reset_matchState(ZSTD_MatchState_t* ms, ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t)); } - ms->cParams = *cParams; - RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation, "failed a workspace allocation in ZSTD_reset_matchState"); return 0; @@ -2307,7 +2306,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, ZSTD_cwksp_clear(ws); /* init params */ - zc->blockState.matchState.cParams = params->cParams; + zc->blockState.matchState.cctxParams = params; zc->blockState.matchState.prefetchCDictTables = params->prefetchCDictTables == ZSTD_ps_enable; zc->pledgedSrcSizePlusOne = pledgedSrcSize+1; zc->consumedSrcSize = 0; @@ -2328,8 +2327,6 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, FORWARD_IF_ERROR(ZSTD_reset_matchState( &zc->blockState.matchState, ws, - ¶ms->cParams, - params->useRowMatchFinder, crp, needsIndexReset, ZSTD_resetTarget_CCtx), ""); @@ -2428,7 +2425,7 @@ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict, const ZSTD_CCtx_params* params, U64 pledgedSrcSize) { - size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy]; + size_t cutoff = attachDictSizeCutoffs[cdict->params.cParams.strategy]; int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch; return dedicatedDictSearch || ( ( pledgedSrcSize <= cutoff @@ -2449,7 +2446,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, DEBUGLOG(4, "ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu", (unsigned long long)pledgedSrcSize); { - ZSTD_CParams adjusted_cdict_cParams = cdict->matchState.cParams; + ZSTD_CParams adjusted_cdict_cParams = cdict->params.cParams; unsigned const windowLog = params.cParams.windowLog; unsigned const windowFrac = params.cParams.windowFrac; assert(windowLog != 0); @@ -2525,7 +2522,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { - const ZSTD_CParams *cdict_cParams = &cdict->matchState.cParams; + const ZSTD_CParams *cdict_cParams = &cdict->params.cParams; assert(!cdict->matchState.dedicatedDictSearch); DEBUGLOG(4, "ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu", @@ -3389,8 +3386,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) ZSTD_MatchState_t* const ms = &zc->blockState.matchState; DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize); assert(srcSize <= ZSTD_BLOCKSIZE_MAX); - /* Assert that we have correctly flushed the ctx params into the ms's copy */ - ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams); + assert(&zc->appliedParams == ms->cctxParams); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding * additional 1. We need to revisit and change this logic to be more consistent */ if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) { @@ -5034,7 +5030,7 @@ ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, int const loadLdmDict = params->ldmParams.enableLdm == ZSTD_ps_enable && ls != NULL; /* Assert that the ms params match the params we're being given */ - ZSTD_assertEqualCParams(params->cParams, ms->cParams); + ZSTD_assertEqualCParams(params->cParams, ms->cctxParams->cParams); { /* Ensure large dictionaries can't cause index overflow */ @@ -5689,8 +5685,10 @@ static size_t ZSTD_initCDict_internal( ZSTD_CCtx_params params) { DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType); + assert(!ZSTD_checkCParams_internal(params.cParams)); - cdict->matchState.cParams = params.cParams; + cdict->params = params; + cdict->matchState.cctxParams = &cdict->params; cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch; if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) { cdict->dictContent = dictBuffer; @@ -5711,8 +5709,6 @@ static size_t ZSTD_initCDict_internal( FORWARD_IF_ERROR(ZSTD_reset_matchState( &cdict->matchState, &cdict->workspace, - ¶ms.cParams, - params.useRowMatchFinder, ZSTDcrp_makeClean, ZSTDirp_reset, ZSTD_resetTarget_CDict), ""); @@ -5953,7 +5949,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict( ZSTD_CParams ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) { assert(cdict != NULL); - return cdict->matchState.cParams; + return cdict->params.cParams; } /*! ZSTD_getDictID_fromCDict() : diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index d9f5a3b45ad..e6bcbd6a69f 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -321,7 +321,9 @@ struct ZSTD_MatchState_t { */ optState_t opt; /* optimal parser state */ const ZSTD_MatchState_t* dictMatchState; - ZSTD_CParams cParams; + + const ZSTD_CCtx_params* cctxParams; + const RawSeqStore_t* ldmSeqStore; /* Controls prefetching in some dictMatchState matchfinders. @@ -1508,7 +1510,7 @@ U32 ZSTD_window_update(ZSTD_window_t* window, */ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr) { - U32 const maxDistance = ZSTD_windowSize(&ms->cParams); + U32 const maxDistance = ZSTD_windowSize(&ms->cctxParams->cParams); U32 const lowestValid = ms->window.lowLimit; U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); @@ -1525,7 +1527,7 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr) */ MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_MatchState_t* ms, U32 curr) { - U32 const maxDistance = ZSTD_windowSize(&ms->cParams); + U32 const maxDistance = ZSTD_windowSize(&ms->cctxParams->cParams); U32 const lowestValid = ms->window.dictLimit; U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 8fdb3062de5..e4214eabd9d 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -18,7 +18,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_fillDoubleHashTableForCDict(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashLarge = ms->hashTable; U32 const hBitsL = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; U32 const mls = cParams->minMatch; @@ -56,7 +56,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_fillDoubleHashTableForCCtx(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashLarge = ms->hashTable; U32 const hBitsL = cParams->hashLog; U32 const mls = cParams->minMatch; @@ -106,7 +106,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { - ZSTD_CParams const* cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashLong = ms->hashTable; const U32 hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; @@ -330,7 +330,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( void const* src, size_t srcSize, U32 const mls /* template */) { - ZSTD_CParams const* cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashLong = ms->hashTable; const U32 hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; @@ -348,7 +348,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( U32 offset_1=rep[0], offset_2=rep[1]; const ZSTD_MatchState_t* const dms = ms->dictMatchState; - const ZSTD_CParams* const dictCParams = &dms->cParams; + const ZSTD_CParams* const dictCParams = &dms->cctxParams->cParams; const U32* const dictHashLong = dms->hashTable; const U32* const dictHashSmall = dms->chainTable; const U32 dictStartIndex = dms->window.dictLimit; @@ -569,7 +569,7 @@ size_t ZSTD_compressBlock_doubleFast( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { - const U32 mls = ms->cParams.minMatch; + const U32 mls = ms->cctxParams->cParams.minMatch; switch(mls) { default: /* includes case 3 */ @@ -589,7 +589,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { - const U32 mls = ms->cParams.minMatch; + const U32 mls = ms->cctxParams->cParams.minMatch; switch(mls) { default: /* includes case 3 */ @@ -612,7 +612,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict_generic( void const* src, size_t srcSize, U32 const mls /* template */) { - ZSTD_CParams const* cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashLong = ms->hashTable; U32 const hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; @@ -760,7 +760,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { - U32 const mls = ms->cParams.minMatch; + U32 const mls = ms->cctxParams->cParams.minMatch; switch(mls) { default: /* includes case 3 */ diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 2145353f233..6681b054319 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -17,7 +17,7 @@ void ZSTD_fillHashTableForCDict(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hBits = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; U32 const mls = cParams->minMatch; @@ -54,7 +54,7 @@ void ZSTD_fillHashTableForCCtx(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hBits = cParams->hashLog; U32 const mls = cParams->minMatch; @@ -194,7 +194,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( void const* src, size_t srcSize, U32 const mls, int useCmov) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; /* min 2 */ @@ -444,9 +444,9 @@ size_t ZSTD_compressBlock_fast( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { - U32 const mml = ms->cParams.minMatch; + U32 const mml = ms->cctxParams->cParams.minMatch; /* use cmov when "candidate in range" branch is likely unpredictable */ - int const useCmov = ms->cParams.windowLog < 19; + int const useCmov = ms->cctxParams->cParams.windowLog < 19; assert(ms->dictMatchState == NULL); if (useCmov) { switch(mml) @@ -484,7 +484,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; /* support stepSize of 0 */ @@ -501,7 +501,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( U32 offset_1=rep[0], offset_2=rep[1]; const ZSTD_MatchState_t* const dms = ms->dictMatchState; - const ZSTD_CParams* const dictCParams = &dms->cParams; + const ZSTD_CParams* const dictCParams = &dms->cctxParams->cParams; const U32* const dictHashTable = dms->hashTable; const U32 dictStartIndex = dms->window.dictLimit; const BYTE* const dictBase = dms->window.base; @@ -687,7 +687,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { - U32 const mls = ms->cParams.minMatch; + U32 const mls = ms->cctxParams->cParams.minMatch; assert(ms->dictMatchState != NULL); switch(mls) { @@ -710,7 +710,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; /* support stepSize of 0 */ @@ -968,7 +968,7 @@ size_t ZSTD_compressBlock_fast_extDict( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { - U32 const mls = ms->cParams.minMatch; + U32 const mls = ms->cctxParams->cParams.minMatch; assert(ms->dictMatchState == NULL); switch(mls) { diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index f3cbc7f73ef..1ff05bdfe2b 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -30,7 +30,7 @@ void ZSTD_updateDUBT(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend, U32 mls) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; @@ -76,7 +76,7 @@ void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 nbCompares, U32 btLow, const ZSTD_dictMode_e dictMode) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const bt = ms->chainTable; U32 const btLog = cParams->chainLog - 1; U32 const btMask = (1 << btLog) - 1; @@ -171,7 +171,7 @@ size_t ZSTD_DUBT_findBetterDictMatch ( const ZSTD_dictMode_e dictMode) { const ZSTD_MatchState_t * const dms = ms->dictMatchState; - const ZSTD_CParams* const dmsCParams = &dms->cParams; + const ZSTD_CParams* const dmsCParams = &dms->cctxParams->cParams; const U32 * const dictHashTable = dms->hashTable; U32 const hashLog = dmsCParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -246,7 +246,7 @@ size_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms, U32 const mls, const ZSTD_dictMode_e dictMode) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -410,16 +410,17 @@ size_t ZSTD_BtFindBestMatch( ZSTD_MatchState_t* ms, void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip) { + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; const BYTE* const base = ms->window.base; U32 const target = (U32)(ip - base); U32* const hashTable = ms->hashTable; U32* const chainTable = ms->chainTable; - U32 const chainSize = 1 << ms->cParams.chainLog; + U32 const chainSize = 1 << cParams->chainLog; U32 idx = ms->nextToUpdate; U32 const minChain = chainSize < target - idx ? target - chainSize : idx; U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG; U32 const cacheSize = bucketSize - 1; - U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize; + U32 const chainAttempts = (1 << cParams->searchLog) - cacheSize; U32 const chainLimit = chainAttempts > 255 ? 255 : chainAttempts; /* We know the hashtable is oversized by a factor of `bucketSize`. @@ -427,21 +428,21 @@ void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const B * single entry. We will use the rest of the space to construct a temporary * chaintable. */ - U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 const hashLog = cParams->hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; U32* const tmpHashTable = hashTable; U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog); U32 const tmpChainSize = (U32)((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog; U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx; U32 hashIdx; - assert(ms->cParams.chainLog <= 24); - assert(ms->cParams.hashLog > ms->cParams.chainLog); + assert(cParams->chainLog <= 24); + assert(cParams->hashLog > cParams->chainLog); assert(idx != 0); assert(tmpMinChain <= minChain); /* fill conventional hash table and conventional chain table */ for ( ; idx < target; idx++) { - U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch); + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, cParams->minMatch); if (idx >= tmpMinChain) { tmpChainTable[idx - tmpMinChain] = hashTable[h]; } @@ -510,7 +511,7 @@ void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const B /* fill the buckets of the hash table */ for (idx = ms->nextToUpdate; idx < target; idx++) { - U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch) + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, cParams->minMatch) << ZSTD_LAZY_DDSS_BUCKET_LOG; U32 i; /* Shift hash cache down 1. */ @@ -657,8 +658,8 @@ U32 ZSTD_insertAndFindFirstIndex_internal( } U32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip) { - const ZSTD_CParams* const cParams = &ms->cParams; - return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch, /* lazySkipping*/ 0); + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, cParams->minMatch, /* lazySkipping*/ 0); } /* inlining is important to hardwire a hot branch (template emulation) */ @@ -670,7 +671,7 @@ size_t ZSTD_HcFindBestMatch( size_t* offsetPtr, const U32 mls, const ZSTD_dictMode_e dictMode) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const chainTable = ms->chainTable; const U32 chainSize = (1 << cParams->chainLog); const U32 chainMask = chainSize-1; @@ -691,7 +692,7 @@ size_t ZSTD_HcFindBestMatch( const ZSTD_MatchState_t* const dms = ms->dictMatchState; const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch - ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0; + ? dms->cctxParams->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0; const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch ? ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG : 0; @@ -737,7 +738,7 @@ size_t ZSTD_HcFindBestMatch( ip, iLimit, prefixStart, curr, dictLimit, ddsIdx); } else if (dictMode == ZSTD_dictMatchState) { const U32* const dmsChainTable = dms->chainTable; - const U32 dmsChainSize = (1 << dms->cParams.chainLog); + const U32 dmsChainSize = (1 << dms->cctxParams->cParams.chainLog); const U32 dmsChainMask = dmsChainSize - 1; const U32 dmsLowestIndex = dms->window.dictLimit; const BYTE* const dmsBase = dms->window.base; @@ -746,7 +747,7 @@ size_t ZSTD_HcFindBestMatch( const U32 dmsIndexDelta = dictLimit - dmsSize; const U32 dmsMinChain = dmsSize > dmsChainSize ? dmsSize - dmsChainSize : 0; - matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)]; + matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cctxParams->cParams.hashLog, mls)]; for ( ; (matchIndex>=dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) { size_t currentMl=0; @@ -947,9 +948,9 @@ void ZSTD_row_update_internal(ZSTD_MatchState_t* ms, const BYTE* ip, * processing. */ void ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* ip) { - const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); + const U32 rowLog = BOUNDED(4, ms->cctxParams->cParams.searchLog, 6); const U32 rowMask = (1u << rowLog) - 1; - const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */); + const U32 mls = MIN(ms->cctxParams->cParams.minMatch, 6 /* mls caps out at 6 */); DEBUGLOG(5, "ZSTD_row_update(), rowLog=%u", rowLog); ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* don't use cache */); @@ -1149,7 +1150,7 @@ size_t ZSTD_RowFindBestMatch( BYTE* const tagTable = ms->tagTable; U32* const hashCache = ms->hashCache; const U32 hashLog = ms->rowHashLog; - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; const BYTE* const base = ms->window.base; const BYTE* const dictBase = ms->window.dictBase; const U32 dictLimit = ms->window.dictLimit; @@ -1181,7 +1182,7 @@ size_t ZSTD_RowFindBestMatch( BYTE* dmsTagRow = NULL; if (dictMode == ZSTD_dedicatedDictSearch) { - const U32 ddsHashLog = dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; + const U32 ddsHashLog = dms->cctxParams->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; { /* Prefetch DDS hashtable entry */ ddsIdx = ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG; PREFETCH_L1(&dms->hashTable[ddsIdx]); @@ -1368,7 +1369,7 @@ size_t ZSTD_RowFindBestMatch( const BYTE* ip, const BYTE* const iLimit, \ size_t* offBasePtr) \ { \ - assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \ + assert(MAX(4, MIN(6, ms->cctxParams->cParams.minMatch)) == mls); \ return ZSTD_BtFindBestMatch(ms, ip, iLimit, offBasePtr, mls, ZSTD_##dictMode); \ } \ @@ -1378,7 +1379,7 @@ size_t ZSTD_RowFindBestMatch( const BYTE* ip, const BYTE* const iLimit, \ size_t* offsetPtr) \ { \ - assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \ + assert(MAX(4, MIN(6, ms->cctxParams->cParams.minMatch)) == mls); \ return ZSTD_HcFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \ } \ @@ -1388,8 +1389,8 @@ size_t ZSTD_RowFindBestMatch( const BYTE* ip, const BYTE* const iLimit, \ size_t* offsetPtr) \ { \ - assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \ - assert(MAX(4, MIN(6, ms->cParams.searchLog)) == rowLog); \ + assert(MAX(4, MIN(6, ms->cctxParams->cParams.minMatch)) == mls); \ + assert(MAX(4, MIN(6, ms->cctxParams->cParams.searchLog)) == rowLog); \ return ZSTD_RowFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode, rowLog); \ } \ @@ -1528,8 +1529,8 @@ size_t ZSTD_compressBlock_lazy_generic( const BYTE* const base = ms->window.base; const U32 prefixLowestIndex = ms->window.dictLimit; const BYTE* const prefixLowest = base + prefixLowestIndex; - const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6); - const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); + const U32 mls = BOUNDED(4, ms->cctxParams->cParams.minMatch, 6); + const U32 rowLog = BOUNDED(4, ms->cctxParams->cParams.searchLog, 6); U32 offset_1 = rep[0], offset_2 = rep[1]; U32 offsetSaved1 = 0, offsetSaved2 = 0; @@ -1951,8 +1952,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const BYTE* const dictBase = ms->window.dictBase; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const dictStart = dictBase + ms->window.lowLimit; - const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6); - const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); + const U32 mls = BOUNDED(4, ms->cctxParams->cParams.minMatch, 6); + const U32 rowLog = BOUNDED(4, ms->cctxParams->cParams.searchLog, 6); U32 offset_1 = rep[0], offset_2 = rep[1]; diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 894830d82fe..8301058820d 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -254,7 +254,7 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_MatchState_t* ms, { const BYTE* const iend = (const BYTE*)end; - switch(ms->cParams.strategy) + switch(ms->cctxParams->cParams.strategy) { case ZSTD_fast: ZSTD_fillHashTable(ms, iend, ZSTD_dtlm_fast, ZSTD_tfp_forCCtx); @@ -684,7 +684,7 @@ size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore, ZSTD_ParamSwitch_e useRowMatchFinder, void const* src, size_t srcSize) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; unsigned const minMatch = cParams->minMatch; ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms)); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 3b8584badae..a02373ba18f 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -445,7 +445,7 @@ U32 ZSTD_insertBt1( U32 const target, U32 const mls, const int extDict) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -581,7 +581,7 @@ void ZSTD_updateTree_internal( } void ZSTD_updateTree(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend) { - ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.minMatch, ZSTD_noDict); + ZSTD_updateTree_internal(ms, ip, iend, ms->cctxParams->cParams.minMatch, ZSTD_noDict); } FORCE_INLINE_TEMPLATE @@ -598,7 +598,7 @@ ZSTD_insertBtAndGetAllMatches ( const U32 lengthToBeat, const U32 mls /* template */) { - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); const BYTE* const base = ms->window.base; U32 const curr = (U32)(ip-base); @@ -627,7 +627,7 @@ ZSTD_insertBtAndGetAllMatches ( const ZSTD_MatchState_t* dms = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL; const ZSTD_CParams* const dmsCParams = - dictMode == ZSTD_dictMatchState ? &dms->cParams : NULL; + dictMode == ZSTD_dictMatchState ? &dms->cctxParams->cParams : NULL; const BYTE* const dmsBase = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL; const BYTE* const dmsEnd = dictMode == ZSTD_dictMatchState ? dms->window.nextSrc : NULL; U32 const dmsHighLimit = dictMode == ZSTD_dictMatchState ? (U32)(dmsEnd - dmsBase) : 0; @@ -841,7 +841,7 @@ U32 ZSTD_btGetAllMatches_internal( const ZSTD_dictMode_e dictMode, const U32 mls) { - assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls); + assert(BOUNDED(3, ms->cctxParams->cParams.minMatch, 6) == mls); DEBUGLOG(8, "ZSTD_BtGetAllMatches(dictMode=%d, mls=%u)", (int)dictMode, mls); if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */ @@ -893,7 +893,7 @@ ZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_dictMode_e const di ZSTD_BT_GET_ALL_MATCHES_ARRAY(extDict), ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMatchState) }; - U32 const mls = BOUNDED(3, ms->cParams.minMatch, 6); + U32 const mls = BOUNDED(3, ms->cctxParams->cParams.minMatch, 6); assert((U32)dictMode < 3); assert(mls - 3 < 4); return getAllMatchesFns[(int)dictMode][mls - 3]; @@ -1089,7 +1089,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, const BYTE* const ilimit = iend - 8; const BYTE* const base = ms->window.base; const BYTE* const prefixStart = base + ms->window.dictLimit; - const ZSTD_CParams* const cParams = &ms->cParams; + const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode); From 885b21eae08aa8f931b2902df6608584ec1c808d Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 18 Feb 2025 07:35:38 -0800 Subject: [PATCH 23/36] Move `useRowMatchFinder` into CCtxParams in CDict --- 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 ddca51ccdb1..bdbd554713e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -87,12 +87,10 @@ struct ZSTD_CDict_s { ZSTD_compressedBlockState_t cBlockState; ZSTD_customMem customMem; U32 dictID; - ZSTD_CCtx_params params; /* storage for matchState.cctxParams pointer */ + ZSTD_CCtx_params params; /* Storage for matchState.cctxParams pointer. + * Not all member fields are used. Used fields: + * cParams, useRowMatchFinder. */ int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */ - ZSTD_ParamSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use - * row-based matchfinder. Unless the cdict is reloaded, we will use - * the same greedy/lazy matchfinder at compression time. - */ }; /* typedef'd to ZSTD_CDict within "zstd.h" */ ZSTD_CCtx* ZSTD_createCCtx(void) @@ -2463,7 +2461,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, params.useRowMatchFinder); params.cParams.windowLog = windowLog; params.cParams.windowFrac = windowFrac; - params.useRowMatchFinder = cdict->useRowMatchFinder; /* cdict overrides */ + params.useRowMatchFinder = cdict->params.useRowMatchFinder; /* cdict overrides */ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, /* loadedDictSize */ 0, ZSTDcrp_makeClean, zbuff), ""); @@ -2535,7 +2533,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, params.cParams = *cdict_cParams; params.cParams.windowLog = windowLog; params.cParams.windowFrac = windowFrac; - params.useRowMatchFinder = cdict->useRowMatchFinder; + params.useRowMatchFinder = cdict->params.useRowMatchFinder; FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, /* loadedDictSize */ 0, ZSTDcrp_leaveDirty, zbuff), ""); @@ -2548,7 +2546,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, assert(params.useRowMatchFinder != ZSTD_ps_auto); /* copy tables */ - { size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->useRowMatchFinder, 0 /* DDS guaranteed disabled */) + { size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->params.useRowMatchFinder, 0 /* DDS guaranteed disabled */) ? ((size_t)1 << cdict_cParams->chainLog) : 0; size_t const hSize = (size_t)1 << cdict_cParams->hashLog; @@ -2564,7 +2562,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, chainSize, cdict_cParams); } /* copy tag table */ - if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->useRowMatchFinder)) { + if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->params.useRowMatchFinder)) { size_t const tagTableSize = hSize; ZSTD_memcpy(cctx->blockState.matchState.tagTable, cdict->matchState.tagTable, @@ -5763,7 +5761,7 @@ ZSTD_createCDict_advanced_internal(size_t dictSize, ZSTD_cwksp_move(&cdict->workspace, &ws); cdict->customMem = customMem; cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */ - cdict->useRowMatchFinder = useRowMatchFinder; + cdict->params.useRowMatchFinder = useRowMatchFinder; return cdict; } } @@ -5934,7 +5932,6 @@ const ZSTD_CDict* ZSTD_initStaticCDict( ZSTD_CCtxParams_init(¶ms, 0); params.cParams = cParams; params.useRowMatchFinder = useRowMatchFinder; - cdict->useRowMatchFinder = useRowMatchFinder; cdict->compressionLevel = ZSTD_NO_CLEVEL; if (ZSTD_isError( ZSTD_initCDict_internal(cdict, From e423daafae92ca2bdadde3b56b2fbc8bc46e18df Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 18 Feb 2025 07:40:01 -0800 Subject: [PATCH 24/36] Move `compressionLevel` into CCtxParams in CDict --- lib/compress/zstd_compress.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bdbd554713e..7a2452a1823 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -89,8 +89,8 @@ struct ZSTD_CDict_s { U32 dictID; ZSTD_CCtx_params params; /* Storage for matchState.cctxParams pointer. * Not all member fields are used. Used fields: - * cParams, useRowMatchFinder. */ - int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */ + * cParams, compressionLevel, useRowMatchFinder. */ + /* A compression level of 0 indicates that advanced API was used to select CDict params */ }; /* typedef'd to ZSTD_CDict within "zstd.h" */ ZSTD_CCtx* ZSTD_createCCtx(void) @@ -5372,7 +5372,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || cdict->compressionLevel == 0) + || cdict->params.compressionLevel == 0) && (params->attachDictPref != ZSTD_dictForceLoad) ) { return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff); } @@ -5760,7 +5760,7 @@ ZSTD_createCDict_advanced_internal(size_t dictSize, assert(cdict != NULL); ZSTD_cwksp_move(&cdict->workspace, &ws); cdict->customMem = customMem; - cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */ + cdict->params.compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */ cdict->params.useRowMatchFinder = useRowMatchFinder; return cdict; } @@ -5855,7 +5855,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL ZSTD_dlm_byCopy, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); if (cdict) - cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + cdict->params.compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; } @@ -5867,7 +5867,7 @@ ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); if (cdict) - cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + cdict->params.compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; } @@ -5932,7 +5932,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict( ZSTD_CCtxParams_init(¶ms, 0); params.cParams = cParams; params.useRowMatchFinder = useRowMatchFinder; - cdict->compressionLevel = ZSTD_NO_CLEVEL; + params.compressionLevel = ZSTD_NO_CLEVEL; if (ZSTD_isError( ZSTD_initCDict_internal(cdict, dict, dictSize, @@ -5976,16 +5976,16 @@ static size_t ZSTD_compressBegin_usingCDict_internal( if ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || cdict->compressionLevel == 0 ) { + || cdict->params.compressionLevel == 0 ) { params.cParams = ZSTD_getCParamsFromCDict(cdict); } else { params.cParams = ZSTD_getCParams_internal( - cdict->compressionLevel, + cdict->params.compressionLevel, pledgedSrcSize, cdict->dictContentSize, ZSTD_cpm_unknown); } - ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->compressionLevel); + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->params.compressionLevel); } /* Increase window log to fit the entire dictionary and source if the * source size is known. Limit the increase to 19, which is the @@ -6508,7 +6508,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, * But do not take the cdict's compression level if the "cdict" is actually a localDict * generated from ZSTD_initLocalDict(). */ - params.compressionLevel = cctx->cdict->compressionLevel; + params.compressionLevel = cctx->cdict->params.compressionLevel; } DEBUGLOG(4, "ZSTD_CCtx_init_compressStream2 : transparent init stage"); if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-determine pledgedSrcSize */ From 28ce1eebc379a826e3caf59ea3bd511b92c9bfc7 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 19 Feb 2025 08:09:19 -0800 Subject: [PATCH 25/36] Convert `ZSTD_adjustCParams_internal()` to Operate on CCtxParams --- lib/compress/zstd_compress.c | 152 +++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 7a2452a1823..725f12d3d45 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1501,56 +1501,57 @@ static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSi * `mode` is the mode for parameter adjustment. See docs for `ZSTD_CParamMode_e`. * note : `srcSize==0` means 0! * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */ -static ZSTD_CParams -ZSTD_adjustCParams_internal(ZSTD_CParams cPar, +static void +ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, unsigned long long srcSize, size_t dictSize, ZSTD_CParamMode_e mode, ZSTD_ParamSwitch_e useRowMatchFinder) { + ZSTD_CParams* cPar = ¶ms->cParams; const U64 minSrcSize = 513; /* (1<<9) + 1 */ const U64 maxWindowResize = 15ULL << (ZSTD_WINDOWLOG_MAX-4); - assert(ZSTD_checkCParams_internal(cPar)==0); + assert(ZSTD_checkCParams_internal(*cPar)==0); /* Cascade the selected strategy down to the next-highest one built into * this binary. */ #ifdef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR - if (cPar.strategy == ZSTD_btultra2) { - cPar.strategy = ZSTD_btultra; + if (cPar->strategy == ZSTD_btultra2) { + cPar->strategy = ZSTD_btultra; } - if (cPar.strategy == ZSTD_btultra) { - cPar.strategy = ZSTD_btopt; + if (cPar->strategy == ZSTD_btultra) { + cPar->strategy = ZSTD_btopt; } #endif #ifdef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR - if (cPar.strategy == ZSTD_btopt) { - cPar.strategy = ZSTD_btlazy2; + if (cPar->strategy == ZSTD_btopt) { + cPar->strategy = ZSTD_btlazy2; } #endif #ifdef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR - if (cPar.strategy == ZSTD_btlazy2) { - cPar.strategy = ZSTD_lazy2; + if (cPar->strategy == ZSTD_btlazy2) { + cPar->strategy = ZSTD_lazy2; } #endif #ifdef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR - if (cPar.strategy == ZSTD_lazy2) { - cPar.strategy = ZSTD_lazy; + if (cPar->strategy == ZSTD_lazy2) { + cPar->strategy = ZSTD_lazy; } #endif #ifdef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR - if (cPar.strategy == ZSTD_lazy) { - cPar.strategy = ZSTD_greedy; + if (cPar->strategy == ZSTD_lazy) { + cPar->strategy = ZSTD_greedy; } #endif #ifdef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR - if (cPar.strategy == ZSTD_greedy) { - cPar.strategy = ZSTD_dfast; + if (cPar->strategy == ZSTD_greedy) { + cPar->strategy = ZSTD_dfast; } #endif #ifdef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR - if (cPar.strategy == ZSTD_dfast) { - cPar.strategy = ZSTD_fast; - cPar.targetLength = 0; + if (cPar->strategy == ZSTD_dfast) { + cPar->strategy = ZSTD_fast; + cPar->targetLength = 0; } #endif @@ -1586,54 +1587,54 @@ ZSTD_adjustCParams_internal(ZSTD_CParams cPar, && (dictSize <= maxWindowResize) ) { U32 const tSize = (U32)(srcSize + dictSize); static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN; - if (ZSTD_windowSize(&cPar) > tSize) { + if (ZSTD_windowSize(cPar) > tSize) { if (tSize < hashSizeMin) { - cPar.windowLog = ZSTD_HASHLOG_MIN; - cPar.windowFrac = 0; + cPar->windowLog = ZSTD_HASHLOG_MIN; + cPar->windowFrac = 0; } else #if !ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES /* Prevents adjustment in the scenario where we have explicitly * selected a fractional window size that is slightly larger than * the src size hint. If we allow picking without this check, we * might end up growing the window to the next power of two. */ - if (ZSTD_windowSize(&cPar) > (1u << (ZSTD_highbit32(tSize - 1) + 1))) + if (ZSTD_windowSize(cPar) > (1u << (ZSTD_highbit32(tSize - 1) + 1))) #endif { const U32 tmpMinWindowLog = ZSTD_HASHLOG_MIN < ZSTD_WINDOWLOG_MIN ? ZSTD_HASHLOG_MIN : ZSTD_WINDOWLOG_MIN; - ZSTD_setMinimalWindowLogAndFrac(&cPar, tSize, tmpMinWindowLog); + ZSTD_setMinimalWindowLogAndFrac(cPar, tSize, tmpMinWindowLog); } } } if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) { - ZSTD_CParams dictWindowCParams = cPar; - U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); + ZSTD_CParams dictWindowCParams = *cPar; + U32 const cycleLog = ZSTD_cycleLog(cPar->chainLog, cPar->strategy); ZSTD_dictAndWindowLog(&dictWindowCParams, (U64)srcSize, (U64)dictSize); if (dictWindowCParams.windowFrac != 0) { /* Round up to a whole power of two. */ dictWindowCParams.windowLog++; dictWindowCParams.windowFrac = 0; } - if (cPar.hashLog > dictWindowCParams.windowLog+1) - cPar.hashLog = dictWindowCParams.windowLog+1; + if (cPar->hashLog > dictWindowCParams.windowLog+1) + cPar->hashLog = dictWindowCParams.windowLog+1; if (cycleLog > dictWindowCParams.windowLog) - cPar.chainLog -= (cycleLog - dictWindowCParams.windowLog); + cPar->chainLog -= (cycleLog - dictWindowCParams.windowLog); } - if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) { - cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */ - cPar.windowFrac = 0; + if (cPar->windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) { + cPar->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */ + cPar->windowFrac = 0; } /* We can't use more than 32 bits of hash in total, so that means that we require: * (hashLog + 8) <= 32 && (chainLog + 8) <= 32 */ - if (mode == ZSTD_cpm_createCDict && ZSTD_CDictIndicesAreTagged(&cPar)) { + if (mode == ZSTD_cpm_createCDict && ZSTD_CDictIndicesAreTagged(cPar)) { U32 const maxShortCacheHashLog = 32 - ZSTD_SHORT_CACHE_TAG_BITS; - if (cPar.hashLog > maxShortCacheHashLog) { - cPar.hashLog = maxShortCacheHashLog; + if (cPar->hashLog > maxShortCacheHashLog) { + cPar->hashLog = maxShortCacheHashLog; } - if (cPar.chainLog > maxShortCacheHashLog) { - cPar.chainLog = maxShortCacheHashLog; + if (cPar->chainLog > maxShortCacheHashLog) { + cPar->chainLog = maxShortCacheHashLog; } } @@ -1649,18 +1650,16 @@ ZSTD_adjustCParams_internal(ZSTD_CParams cPar, /* We can't hash more than 32-bits in total. So that means that we require: * (hashLog - rowLog + 8) <= 32 */ - if (ZSTD_rowMatchFinderUsed(cPar.strategy, useRowMatchFinder)) { + if (ZSTD_rowMatchFinderUsed(cPar->strategy, useRowMatchFinder)) { /* Switch to 32-entry rows if searchLog is 5 (or more) */ - U32 const rowLog = BOUNDED(4, cPar.searchLog, 6); + U32 const rowLog = BOUNDED(4, cPar->searchLog, 6); U32 const maxRowHashLog = 32 - ZSTD_ROW_HASH_TAG_BITS; U32 const maxHashLog = maxRowHashLog + rowLog; - assert(cPar.hashLog >= rowLog); - if (cPar.hashLog > maxHashLog) { - cPar.hashLog = maxHashLog; + assert(cPar->hashLog >= rowLog); + if (cPar->hashLog > maxHashLog) { + cPar->hashLog = maxHashLog; } } - - return cPar; } ZSTD_compressionParameters @@ -1668,11 +1667,13 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize) { - ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(cPar); - cParams = ZSTD_clampCParams(cParams); /* resulting cPar is necessarily valid (all parameters within range) */ + ZSTD_CCtx_params params; + ZSTD_CCtxParams_init(¶ms, 0); + params.cParams = ZSTD_getCParamsFromPublicCParams(cPar); + params.cParams = ZSTD_clampCParams(params.cParams); /* resulting cPar is necessarily valid (all parameters within range) */ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; - cParams = ZSTD_adjustCParams_internal(cParams, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto); - return ZSTD_getPublicCParamsFromCParams(cParams); + ZSTD_adjustCParams_internal(¶ms, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto); + return ZSTD_getPublicCParamsFromCParams(params.cParams); } ZSTD_CParams ZSTD_getCParamsFromPublicCParams( @@ -1735,22 +1736,27 @@ static void ZSTD_overrideCParams( } ZSTD_CParams ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) + const ZSTD_CCtx_params* cctxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) { - ZSTD_CParams cParams; - if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { - assert(CCtxParams->srcSizeHint>=0); - srcSizeHint = (U64)CCtxParams->srcSizeHint; + ZSTD_CCtx_params params = *cctxParams; + if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && params.srcSizeHint > 0) { + assert(params.srcSizeHint>=0); + srcSizeHint = (U64)params.srcSizeHint; } - cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); - if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) { - cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; - cParams.windowFrac = 0; + { + ZSTD_CParams cParams = ZSTD_getCParams_internal(params.compressionLevel, srcSizeHint, dictSize, mode); + if (params.ldmParams.enableLdm == ZSTD_ps_enable) { + cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; + cParams.windowFrac = 0; + } + ZSTD_overrideCParams(&cParams, ¶ms.cParams); + params.cParams = cParams; + assert(!ZSTD_checkCParams_internal(cParams)); } - ZSTD_overrideCParams(&cParams, &CCtxParams->cParams); - assert(!ZSTD_checkCParams_internal(cParams)); + /* srcSizeHint == 0 means 0 */ - return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode, CCtxParams->useRowMatchFinder); + ZSTD_adjustCParams_internal(¶ms, srcSizeHint, dictSize, mode, params.useRowMatchFinder); + return params.cParams; } static size_t @@ -2444,7 +2450,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, DEBUGLOG(4, "ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu", (unsigned long long)pledgedSrcSize); { - ZSTD_CParams adjusted_cdict_cParams = cdict->params.cParams; + ZSTD_CCtx_params adjusted_cdict_params = cdict->params; unsigned const windowLog = params.cParams.windowLog; unsigned const windowFrac = params.cParams.windowFrac; assert(windowLog != 0); @@ -2453,19 +2459,20 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, /* pledgedSrcSize == 0 means 0! */ if (cdict->matchState.dedicatedDictSearch) { - ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams); + ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_params.cParams); } - params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize, - cdict->dictContentSize, ZSTD_cpm_attachDict, - params.useRowMatchFinder); + ZSTD_adjustCParams_internal(&adjusted_cdict_params, pledgedSrcSize, + cdict->dictContentSize, ZSTD_cpm_attachDict, + params.useRowMatchFinder); + params.cParams = adjusted_cdict_params.cParams; params.cParams.windowLog = windowLog; params.cParams.windowFrac = windowFrac; params.useRowMatchFinder = cdict->params.useRowMatchFinder; /* cdict overrides */ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, /* loadedDictSize */ 0, ZSTDcrp_makeClean, zbuff), ""); - assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy); + assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_params.cParams.strategy); } { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc @@ -7922,15 +7929,18 @@ static ZSTD_CParams ZSTD_getCParams_internal( else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; else row = compressionLevel; - { ZSTD_CParams cp = ZSTD_defaultCParameters[tableID][row]; - DEBUGLOG(5, "ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)cp.strategy); + { ZSTD_CCtx_params params; + ZSTD_CCtxParams_init(¶ms, compressionLevel); + params.cParams = ZSTD_defaultCParameters[tableID][row]; + DEBUGLOG(5, "ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)params.cParams.strategy); /* acceleration factor */ if (compressionLevel < 0) { int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel); - cp.targetLength = (unsigned)(-clampedCompressionLevel); + params.cParams.targetLength = (unsigned)(-clampedCompressionLevel); } /* refine parameters based on srcSize & dictSize */ - return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode, ZSTD_ps_auto); + ZSTD_adjustCParams_internal(¶ms, srcSizeHint, dictSize, mode, ZSTD_ps_auto); + return params.cParams; } } From 8832b956a5f99b95b673915e816687e8b99eb486 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 19 Feb 2025 08:32:45 -0800 Subject: [PATCH 26/36] Convert `ZSTD_estimateCCtxSize_usingCCtxParams_internal()` to Operate on CCtxParams --- lib/compress/zstd_compress.c | 53 +++++++++++++++++------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 725f12d3d45..8651a4a689d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1809,29 +1809,26 @@ static size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useSequence } static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( - const ZSTD_CParams* cParams, - const ldmParams_t* ldmParams, + const ZSTD_CCtx_params* params, const int isStatic, - const ZSTD_ParamSwitch_e useRowMatchFinder, const size_t buffInSize, const size_t buffOutSize, - const U64 pledgedSrcSize, - int useSequenceProducer, - size_t maxBlockSize) + const U64 pledgedSrcSize) { - size_t const windowSize = (size_t) BOUNDED(1ULL, ZSTD_windowSize(cParams), pledgedSrcSize); - size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize); - size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer); + int const useSequenceProducer = ZSTD_hasExtSeqProd(params); + size_t const windowSize = (size_t) BOUNDED(1ULL, ZSTD_windowSize(¶ms->cParams), pledgedSrcSize); + size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), windowSize); + size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, useSequenceProducer); size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(SeqDef)) + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); size_t const tmpWorkSpace = ZSTD_cwksp_alloc_size(TMP_WORKSPACE_SIZE); size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); - size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); + size_t const matchStateSize = ZSTD_sizeof_matchState(¶ms->cParams, params->useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); - size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams); - size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize); - size_t const ldmSeqSpace = ldmParams->enableLdm == ZSTD_ps_enable ? + size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams); + size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize); + size_t const ldmSeqSpace = params->ldmParams.enableLdm == ZSTD_ps_enable ? ZSTD_cwksp_aligned64_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; @@ -1862,17 +1859,16 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) { - ZSTD_CParams const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); - ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, - &cParams); + ZSTD_CCtx_params par = *params; + par.cParams = ZSTD_getCParamsFromCCtxParams(&par, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + par.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(par.useRowMatchFinder, &par.cParams); - RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); + RETURN_ERROR_IF(par.nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); /* estimateCCtxSize is for one-shot compression. So no buffers should * be needed. However, we still allocate two 0-sized buffers, which can * take space under ASAN. */ return ZSTD_estimateCCtxSize_usingCCtxParams_internal( - &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize); + &par, 1, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN); } static size_t ZSTD_estimateCCtxSize_usingCParams_internal(ZSTD_CParams cParams) @@ -1925,10 +1921,11 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel) size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) { - RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); - { ZSTD_CParams const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); - size_t const windowSize = ZSTD_windowSize(&cParams); + ZSTD_CCtx_params par = *params; + RETURN_ERROR_IF(par.nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); + par.cParams = ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + { + size_t const windowSize = ZSTD_windowSize(&par.cParams); size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), windowSize); size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered) ? windowSize + blockSize @@ -1936,11 +1933,11 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered) ? ZSTD_compressBound(blockSize) + 1 : 0; - ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, ¶ms->cParams); + par.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(par.useRowMatchFinder, &par.cParams); return ZSTD_estimateCCtxSize_usingCCtxParams_internal( - &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize, - ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize); + &par, 1, inBuffSize, outBuffSize, + ZSTD_CONTENTSIZE_UNKNOWN); } } @@ -2267,8 +2264,8 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, size_t const neededSpace = ZSTD_estimateCCtxSize_usingCCtxParams_internal( - ¶ms->cParams, ¶ms->ldmParams, zc->staticSize != 0, params->useRowMatchFinder, - buffInSize, buffOutSize, pledgedSrcSize, ZSTD_hasExtSeqProd(params), params->maxBlockSize); + params, zc->staticSize != 0, + buffInSize, buffOutSize, pledgedSrcSize); FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!"); From 4494d0a0a862acbdce4a7a62eef598ea63bb0067 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 19 Feb 2025 08:33:15 -0800 Subject: [PATCH 27/36] Convert Window Size Helper Functions to take CCtxParams --- lib/compress/zstd_compress.c | 65 +++++++++++++-------------- lib/compress/zstd_compress_internal.h | 44 +++++++++--------- lib/compress/zstd_double_fast.c | 2 +- lib/compress/zstd_fast.c | 2 +- lib/compress/zstd_lazy.c | 6 +-- lib/compress/zstdmt_compress.c | 4 +- 6 files changed, 61 insertions(+), 62 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 8651a4a689d..357310be8db 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1471,16 +1471,16 @@ U32 ZSTD_cycleLog(U32 chainLog, ZSTD_strategy strat) * the hashLog and windowLog. * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN. */ -static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSize) +static void ZSTD_dictAndWindowLog(ZSTD_CCtx_params* params, U64 srcSize, U64 dictSize) { /* No dictionary ==> No change */ if (dictSize == 0) { return; } - assert(cParams->windowLog + !!cParams->windowFrac <= ZSTD_WINDOWLOG_MAX); + assert(params->cParams.windowLog + !!params->cParams.windowFrac <= ZSTD_WINDOWLOG_MAX); assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */ { - U64 const windowSize = ZSTD_windowSize(cParams); + U64 const windowSize = ZSTD_windowSize(params); U64 const dictAndWindowSize = dictSize + windowSize; /* If the window size is already large enough to fit both the source and the dictionary * then just use the window size. Otherwise adjust so that it fits the dictionary and @@ -1489,7 +1489,7 @@ static void ZSTD_dictAndWindowLog(ZSTD_CParams* cParams, U64 srcSize, U64 dictSi if (windowSize >= dictSize + srcSize) { /* Window size large enough already */ } else { - ZSTD_setMinimalWindowLogAndFrac(cParams, (U32)dictAndWindowSize, ZSTD_WINDOWLOG_MIN); + ZSTD_setMinimalWindowLogAndFrac(params, (U32)dictAndWindowSize, ZSTD_WINDOWLOG_MIN); } } } @@ -1587,7 +1587,7 @@ ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, && (dictSize <= maxWindowResize) ) { U32 const tSize = (U32)(srcSize + dictSize); static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN; - if (ZSTD_windowSize(cPar) > tSize) { + if (ZSTD_windowSize(params) > tSize) { if (tSize < hashSizeMin) { cPar->windowLog = ZSTD_HASHLOG_MIN; cPar->windowFrac = 0; @@ -1597,27 +1597,27 @@ ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, * selected a fractional window size that is slightly larger than * the src size hint. If we allow picking without this check, we * might end up growing the window to the next power of two. */ - if (ZSTD_windowSize(cPar) > (1u << (ZSTD_highbit32(tSize - 1) + 1))) + if (ZSTD_windowSize(params) > (1u << (ZSTD_highbit32(tSize - 1) + 1))) #endif { const U32 tmpMinWindowLog = ZSTD_HASHLOG_MIN < ZSTD_WINDOWLOG_MIN ? ZSTD_HASHLOG_MIN : ZSTD_WINDOWLOG_MIN; - ZSTD_setMinimalWindowLogAndFrac(cPar, tSize, tmpMinWindowLog); + ZSTD_setMinimalWindowLogAndFrac(params, tSize, tmpMinWindowLog); } } } if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) { - ZSTD_CParams dictWindowCParams = *cPar; + ZSTD_CCtx_params dictWindowParams = *params; U32 const cycleLog = ZSTD_cycleLog(cPar->chainLog, cPar->strategy); - ZSTD_dictAndWindowLog(&dictWindowCParams, (U64)srcSize, (U64)dictSize); - if (dictWindowCParams.windowFrac != 0) { + ZSTD_dictAndWindowLog(&dictWindowParams, (U64)srcSize, (U64)dictSize); + if (dictWindowParams.cParams.windowFrac != 0) { /* Round up to a whole power of two. */ - dictWindowCParams.windowLog++; - dictWindowCParams.windowFrac = 0; + dictWindowParams.cParams.windowLog++; + dictWindowParams.cParams.windowFrac = 0; } - if (cPar->hashLog > dictWindowCParams.windowLog+1) - cPar->hashLog = dictWindowCParams.windowLog+1; - if (cycleLog > dictWindowCParams.windowLog) - cPar->chainLog -= (cycleLog - dictWindowCParams.windowLog); + if (cPar->hashLog > dictWindowParams.cParams.windowLog+1) + cPar->hashLog = dictWindowParams.cParams.windowLog+1; + if (cycleLog > dictWindowParams.cParams.windowLog) + cPar->chainLog -= (cycleLog - dictWindowParams.cParams.windowLog); } if (cPar->windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) { @@ -1816,7 +1816,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( const U64 pledgedSrcSize) { int const useSequenceProducer = ZSTD_hasExtSeqProd(params); - size_t const windowSize = (size_t) BOUNDED(1ULL, ZSTD_windowSize(¶ms->cParams), pledgedSrcSize); + size_t const windowSize = (size_t) BOUNDED(1ULL, ZSTD_windowSize(params), pledgedSrcSize); size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), windowSize); size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, useSequenceProducer); size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) @@ -1925,7 +1925,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) RETURN_ERROR_IF(par.nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); par.cParams = ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); { - size_t const windowSize = ZSTD_windowSize(&par.cParams); + size_t const windowSize = ZSTD_windowSize(&par); size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), windowSize); size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered) ? windowSize + blockSize @@ -2246,7 +2246,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, assert(params->ldmParams.hashRateLog < 32); } - { size_t const windowSize = MAX(1, (size_t)MIN(ZSTD_windowSize(¶ms->cParams), pledgedSrcSize)); + { size_t const windowSize = MAX(1, (size_t)MIN(ZSTD_windowSize(params), pledgedSrcSize)); size_t const blockSize = MIN(params->maxBlockSize, windowSize); size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, ZSTD_hasExtSeqProd(params)); size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered) @@ -3475,7 +3475,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) ); assert(zc->appliedParams.extSeqProdFunc != NULL); - { U32 const windowSize = ZSTD_windowSize(&zc->appliedParams.cParams); + { U32 const windowSize = ZSTD_windowSize(&zc->appliedParams); size_t const nbExternalSeqs = (zc->appliedParams.extSeqProdFunc)( zc->appliedParams.extSeqProdState, @@ -4651,7 +4651,7 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms, void const* iend) { U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy); - U32 const maxDist = ZSTD_windowSize(¶ms->cParams); + U32 const maxDist = ZSTD_windowSize(params); if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) { U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); @@ -4719,7 +4719,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; - U32 const maxDist = ZSTD_windowSize(&cctx->appliedParams.cParams); + U32 const maxDist = ZSTD_windowSize(&cctx->appliedParams); S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; assert(cctx->appliedParams.cParams.windowLog + !!cctx->appliedParams.cParams.windowFrac <= ZSTD_WINDOWLOG_MAX); @@ -4821,7 +4821,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */ U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */ U32 const checksumFlag = params->fParams.checksumFlag>0; - U32 const windowSize = ZSTD_windowSize(¶ms->cParams); + U32 const windowSize = ZSTD_windowSize(params); U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); BYTE const windowByte = (BYTE)(((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3) | (params->cParams.windowFrac & 7)); U32 const fcsCode = params->fParams.contentSizeFlag ? @@ -4989,9 +4989,8 @@ size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, static size_t ZSTD_getBlockSize_deprecated(const ZSTD_CCtx* cctx) { - ZSTD_CParams const cParams = cctx->appliedParams.cParams; - assert(!ZSTD_checkCParams_internal(cParams)); - return MIN(cctx->appliedParams.maxBlockSize, (size_t)ZSTD_windowSize(&cParams)); + assert(!ZSTD_checkCParams_internal(cctx->appliedParams.cParams)); + return MIN(cctx->appliedParams.maxBlockSize, (size_t)ZSTD_windowSize(&cctx->appliedParams)); } /* NOTE: Must just wrap ZSTD_getBlockSize_deprecated() */ @@ -5997,8 +5996,8 @@ static size_t ZSTD_compressBegin_usingCDict_internal( */ if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); - if (limitedSrcSize > 1 && ZSTD_windowSize(&cctxParams.cParams) < limitedSrcSize) { - ZSTD_setMinimalWindowLogAndFrac(&cctxParams.cParams, limitedSrcSize, ZSTD_WINDOWLOG_MIN); + if (limitedSrcSize > 1 && ZSTD_windowSize(&cctxParams) < limitedSrcSize) { + ZSTD_setMinimalWindowLogAndFrac(&cctxParams, limitedSrcSize, ZSTD_WINDOWLOG_MIN); } } return ZSTD_compressBegin_internal(cctx, @@ -6754,17 +6753,17 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, */ static size_t ZSTD_validateSequence( - U32 offBase, U32 matchLength, const ZSTD_CParams* cParams, + U32 offBase, U32 matchLength, const ZSTD_CCtx_params* params, size_t posInSrc, size_t dictSize, int useSequenceProducer) { - U32 const windowSize = ZSTD_windowSize(cParams); + U32 const windowSize = ZSTD_windowSize(params); /* posInSrc represents the amount of data the decoder would decode up to this point. * As long as the amount of data decoded is less than or equal to window size, offsets may be * larger than the total length of output decoded in order to reference the dict, even larger than * window size. After output surpasses windowSize, we're limited to windowSize offsets again. */ size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize; - size_t const matchLenLowerBound = (cParams->minMatch == 3 || useSequenceProducer) ? 3 : 4; + size_t const matchLenLowerBound = (params->cParams.minMatch == 3 || useSequenceProducer) ? 3 : 4; RETURN_ERROR_IF(offBase > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, "Offset too large!"); /* Validate maxNbSeq is large enough for the given matchLength and minMatch */ RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, "Matchlength too small for the minMatch"); @@ -6835,7 +6834,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, if (cctx->appliedParams.validateSequences) { seqPos->posInSrc += litLength + matchLength; FORWARD_IF_ERROR(ZSTD_validateSequence( - offBase, matchLength, &cctx->appliedParams.cParams, + offBase, matchLength, &cctx->appliedParams, seqPos->posInSrc, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), "Sequence validation failed"); } @@ -6989,7 +6988,7 @@ ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx, if (cctx->appliedParams.validateSequences) { seqPos->posInSrc += litLength + matchLength; FORWARD_IF_ERROR(ZSTD_validateSequence( - offBase, matchLength, &cctx->appliedParams.cParams, + offBase, matchLength, &cctx->appliedParams, seqPos->posInSrc, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), "Sequence validation failed"); } diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index e6bcbd6a69f..e6d65f6b1a4 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1119,8 +1119,8 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) * Return the window size described by the windowLog and windowFrac in the * provided CParams. */ -MEM_STATIC U32 ZSTD_windowSize(const ZSTD_CParams* cParams) { - return (U32)(((8ull + cParams->windowFrac) << cParams->windowLog) >> 3); +MEM_STATIC U32 ZSTD_windowSize(const ZSTD_CCtx_params* params) { + return (U32)(((8ull + params->cParams.windowFrac) << params->cParams.windowLog) >> 3); } MEM_STATIC U32 ZSTD_windowSizeLDM(const ldmParams_t* ldmParams) { return (U32)(((8ull + ldmParams->windowFrac) << ldmParams->windowLog) >> 3); @@ -1133,14 +1133,14 @@ MEM_STATIC U32 ZSTD_windowSizeLDM(const ldmParams_t* ldmParams) { * 1.125 or 2, depending on whether we're allowed to pick fractional window * sizes. */ -MEM_STATIC int ZSTD_windowLogAndFracAreMinimal(ZSTD_CParams* cParams, const U32 srcSize) { +MEM_STATIC int ZSTD_windowLogAndFracAreMinimal(const ZSTD_CCtx_params* params, const U32 srcSize) { const U32 lowerBound = MIN(srcSize, 1u << ZSTD_WINDOWLOG_MAX); #if ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES const U32 upperBound = MAX(lowerBound + (lowerBound >> 3), 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN); #else const U32 upperBound = MAX(2 * lowerBound - 1, 1u << ZSTD_WINDOWLOG_ABSOLUTEMIN); #endif - const U32 windowSize = ZSTD_windowSize(cParams); + const U32 windowSize = ZSTD_windowSize(params); if (windowSize < lowerBound) { return 0; } @@ -1154,35 +1154,35 @@ MEM_STATIC int ZSTD_windowLogAndFracAreMinimal(ZSTD_CParams* cParams, const U32 * Calculates the minimum legal window log and fraction that contain the * provided source size. */ -MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CParams* cParams, const U32 srcSize, const U32 minWindowLog) { +MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CCtx_params* params, const U32 srcSize, const U32 minWindowLog) { const U32 minSize = 1u << minWindowLog; #if ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES if (srcSize < minSize) { - cParams->windowLog = minWindowLog; - cParams->windowFrac = 0; + params->cParams.windowLog = minWindowLog; + params->cParams.windowFrac = 0; } else { const U32 srcSizeMinusOne = srcSize - 1; - cParams->windowLog = ZSTD_highbit32(srcSizeMinusOne); - cParams->windowFrac = ((srcSizeMinusOne >> (cParams->windowLog - 3)) & 7) + 1; - if (cParams->windowFrac == 8) { - cParams->windowFrac = 0; - cParams->windowLog++; + params->cParams.windowLog = ZSTD_highbit32(srcSizeMinusOne); + params->cParams.windowFrac = ((srcSizeMinusOne >> (params->cParams.windowLog - 3)) & 7) + 1; + if (params->cParams.windowFrac == 8) { + params->cParams.windowFrac = 0; + params->cParams.windowLog++; } } #else if (srcSize < minSize) { - cParams->windowLog = minWindowLog; - cParams->windowFrac = 0; + params->cParams.windowLog = minWindowLog; + params->cParams.windowFrac = 0; } else { - cParams->windowLog = ZSTD_highbit32(srcSize - 1) + 1; - cParams->windowFrac = 0; + params->cParams.windowLog = ZSTD_highbit32(srcSize - 1) + 1; + params->cParams.windowFrac = 0; } #endif - if (cParams->windowLog + !!cParams->windowFrac > ZSTD_WINDOWLOG_MAX) { - cParams->windowLog = ZSTD_WINDOWLOG_MAX; - cParams->windowFrac = 0; + if (params->cParams.windowLog + !!params->cParams.windowFrac > ZSTD_WINDOWLOG_MAX) { + params->cParams.windowLog = ZSTD_WINDOWLOG_MAX; + params->cParams.windowFrac = 0; } - assert(ZSTD_windowLogAndFracAreMinimal(cParams, srcSize)); + assert(ZSTD_windowLogAndFracAreMinimal(params, srcSize)); } /* Defining this macro to non-zero tells zstd to run the overflow correction @@ -1510,7 +1510,7 @@ U32 ZSTD_window_update(ZSTD_window_t* window, */ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr) { - U32 const maxDistance = ZSTD_windowSize(&ms->cctxParams->cParams); + U32 const maxDistance = ZSTD_windowSize(ms->cctxParams); U32 const lowestValid = ms->window.lowLimit; U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); @@ -1527,7 +1527,7 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr) */ MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_MatchState_t* ms, U32 curr) { - U32 const maxDistance = ZSTD_windowSize(&ms->cctxParams->cParams); + U32 const maxDistance = ZSTD_windowSize(ms->cctxParams); U32 const lowestValid = ms->window.dictLimit; U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index e4214eabd9d..dc76eda9dbc 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -363,7 +363,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_dictMatchState_generic"); /* if a dictionary is attached, it must be within window range */ - assert(ms->window.dictLimit + ZSTD_windowSize(cParams) >= endIndex); + assert(ms->window.dictLimit + ZSTD_windowSize(ms->cctxParams) >= endIndex); if (ms->prefetchCDictTables) { size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32); diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 6681b054319..d2d0d093b6f 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -513,7 +513,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( /* if a dictionary is still attached, it necessarily means that * it is within window size. So we just check it. */ - const U32 maxDistance = ZSTD_windowSize(cParams); + const U32 maxDistance = ZSTD_windowSize(ms->cctxParams); const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); assert(endIndex - prefixStartIndex <= maxDistance); (void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */ diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 1ff05bdfe2b..392a1bad8b9 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -94,7 +94,7 @@ void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */ U32 dummy32; /* to be nullified at the end */ U32 const windowValid = ms->window.lowLimit; - U32 const maxDistance = ZSTD_windowSize(cParams); + U32 const maxDistance = ZSTD_windowSize(ms->cctxParams); U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid; @@ -681,7 +681,7 @@ size_t ZSTD_HcFindBestMatch( const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const U32 curr = (U32)(ip-base); - const U32 maxDistance = ZSTD_windowSize(cParams); + const U32 maxDistance = ZSTD_windowSize(ms->cctxParams); const U32 lowestValid = ms->window.lowLimit; const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; const U32 isDictionary = (ms->loadedDictEnd != 0); @@ -1157,7 +1157,7 @@ size_t ZSTD_RowFindBestMatch( const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const U32 curr = (U32)(ip-base); - const U32 maxDistance = ZSTD_windowSize(cParams); + const U32 maxDistance = ZSTD_windowSize(ms->cctxParams); const U32 lowestValid = ms->window.lowLimit; const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; const U32 isDictionary = (ms->loadedDictEnd != 0); diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 9168fefb7ac..42978f7bb01 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -494,7 +494,7 @@ ZSTDMT_serialState_reset(SerialState* serialState, { /* Adjust parameters */ if (params.ldmParams.enableLdm == ZSTD_ps_enable) { - DEBUGLOG(4, "LDM window size = %u KB", ZSTD_windowSize(¶ms.cParams) >> 10); + DEBUGLOG(4, "LDM window size = %u KB", ZSTD_windowSize(¶ms) >> 10); ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams); assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); assert(params.ldmParams.hashRateLog < 32); @@ -1315,7 +1315,7 @@ size_t ZSTDMT_initCStream_internal( ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize)); { /* If ldm is enabled we need windowSize space. */ - size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? ZSTD_windowSize(&mtctx->params.cParams) : 0; + size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? ZSTD_windowSize(&mtctx->params) : 0; /* Two buffers of slack, plus extra space for the overlap * This is the minimum slack that LDM works with. One extra because * flush might waste up to targetSectionSize-1 bytes. Another extra From 90c0e0aa0c597b736190afbe1cae89dc93fc17f1 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 20 Feb 2025 09:10:39 -0800 Subject: [PATCH 28/36] Split `ZSTD_checkCParams_internal()` into Two Funcs, One of Which Operates on CCtxParams Sometimes this is used to validate user-provided CParams, before they're allowed to affect the CCtxParams. Leave those cases as-is. Otherwise, convert uses of this function to pass in the whole CCtxParams so that, in the next commit, when we pull out the `windowFrac` from the CParams, we can still cross-validate it with the `windowLog` CParam. --- lib/compress/zstd_compress.c | 69 +++++++++++++++++---------- lib/compress/zstd_compress_internal.h | 10 +++- lib/compress/zstdmt_compress.c | 2 +- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 357310be8db..3b94f62e332 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -321,7 +321,7 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( cctxParams.maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams.maxBlockSize); cctxParams.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams.searchForExternalRepcodes, cctxParams.compressionLevel); - assert(!ZSTD_checkCParams_internal(cParams)); + assert(!ZSTD_checkCCtxCParams_internal(&cctxParams)); return cctxParams; } @@ -374,7 +374,7 @@ ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, const ZSTD_Params* params, int compressionLevel) { - assert(!ZSTD_checkCParams_internal(params->cParams)); + assert(!ZSTD_checkCParams_internal(¶ms->cParams)); ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); cctxParams->cParams = params->cParams; cctxParams->fParams = params->fParams; @@ -396,7 +396,7 @@ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_paramete { ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); - FORWARD_IF_ERROR( ZSTD_checkCParams_internal(params.cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams_internal(¶ms.cParams) , ""); ZSTD_CCtxParams_init_internal(cctxParams, ¶ms, ZSTD_NO_CLEVEL); return 0; } @@ -408,7 +408,7 @@ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_paramete static void ZSTD_CCtxParams_setZstdParams( ZSTD_CCtx_params* cctxParams, const ZSTD_Params* params) { - assert(!ZSTD_checkCParams_internal(params->cParams)); + assert(!ZSTD_checkCParams_internal(¶ms->cParams)); cctxParams->cParams = params->cParams; cctxParams->fParams = params->fParams; /* Should not matter, as all cParams are presumed properly defined. @@ -1404,19 +1404,35 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) return 0; } -size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams) +size_t ZSTD_checkCParams_internal(const ZSTD_CParams* cParams) { - BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); - BOUNDCHECK(ZSTD_c_windowFrac, (int)cParams.windowFrac); + BOUNDCHECK(ZSTD_c_windowLog, (int)cParams->windowLog); + BOUNDCHECK(ZSTD_c_windowFrac, (int)cParams->windowFrac); RETURN_ERROR_IF( - cParams.windowLog + !!cParams.windowFrac > ZSTD_WINDOWLOG_MAX, + cParams->windowLog + !!cParams->windowFrac > ZSTD_WINDOWLOG_MAX, parameter_outOfBound, "Param out of bounds"); - BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); - BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); - BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); - BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); - BOUNDCHECK(ZSTD_c_targetLength, (int)cParams.targetLength); - BOUNDCHECK(ZSTD_c_strategy, (int)cParams.strategy); + BOUNDCHECK(ZSTD_c_chainLog, (int)cParams->chainLog); + BOUNDCHECK(ZSTD_c_hashLog, (int)cParams->hashLog); + BOUNDCHECK(ZSTD_c_searchLog, (int)cParams->searchLog); + BOUNDCHECK(ZSTD_c_minMatch, (int)cParams->minMatch); + BOUNDCHECK(ZSTD_c_targetLength, (int)cParams->targetLength); + BOUNDCHECK(ZSTD_c_strategy, (int)cParams->strategy); + return 0; +} + +size_t ZSTD_checkCCtxCParams_internal(const ZSTD_CCtx_params* params) +{ + BOUNDCHECK(ZSTD_c_windowLog, (int)params->cParams.windowLog); + BOUNDCHECK(ZSTD_c_windowFrac, (int)params->cParams.windowFrac); + RETURN_ERROR_IF( + params->cParams.windowLog + !!params->cParams.windowFrac > ZSTD_WINDOWLOG_MAX, + parameter_outOfBound, "Param out of bounds"); + BOUNDCHECK(ZSTD_c_chainLog, (int)params->cParams.chainLog); + BOUNDCHECK(ZSTD_c_hashLog, (int)params->cParams.hashLog); + BOUNDCHECK(ZSTD_c_searchLog, (int)params->cParams.searchLog); + BOUNDCHECK(ZSTD_c_minMatch, (int)params->cParams.minMatch); + BOUNDCHECK(ZSTD_c_targetLength, (int)params->cParams.targetLength); + BOUNDCHECK(ZSTD_c_strategy, (int)params->cParams.strategy); return 0; } @@ -1425,7 +1441,8 @@ size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams) @return : 0, or an error code if one value is beyond authorized range */ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) { - return ZSTD_checkCParams_internal(ZSTD_getCParamsFromPublicCParams(cParams)); + ZSTD_CParams cPar = ZSTD_getCParamsFromPublicCParams(cParams); + return ZSTD_checkCParams_internal(&cPar); } /** ZSTD_clampCParams() : @@ -1511,7 +1528,7 @@ ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, ZSTD_CParams* cPar = ¶ms->cParams; const U64 minSrcSize = 513; /* (1<<9) + 1 */ const U64 maxWindowResize = 15ULL << (ZSTD_WINDOWLOG_MAX-4); - assert(ZSTD_checkCParams_internal(*cPar)==0); + assert(ZSTD_checkCCtxCParams_internal(params)==0); /* Cascade the selected strategy down to the next-highest one built into * this binary. */ @@ -1751,7 +1768,7 @@ ZSTD_CParams ZSTD_getCParamsFromCCtxParams( } ZSTD_overrideCParams(&cParams, ¶ms.cParams); params.cParams = cParams; - assert(!ZSTD_checkCParams_internal(cParams)); + assert(!ZSTD_checkCCtxCParams_internal(¶ms)); } /* srcSizeHint == 0 means 0 */ @@ -2225,7 +2242,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, ZSTD_cwksp* const ws = &zc->workspace; DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d useBlockSplitter=%d", (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->postBlockSplitter); - assert(!ZSTD_isError(ZSTD_checkCParams_internal(params->cParams))); + assert(!ZSTD_isError(ZSTD_checkCCtxCParams_internal(params))); zc->isFirstBlock = 1; @@ -4989,7 +5006,7 @@ size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, static size_t ZSTD_getBlockSize_deprecated(const ZSTD_CCtx* cctx) { - assert(!ZSTD_checkCParams_internal(cctx->appliedParams.cParams)); + assert(!ZSTD_checkCCtxCParams_internal(&cctx->appliedParams)); return MIN(cctx->appliedParams.maxBlockSize, (size_t)ZSTD_windowSize(&cctx->appliedParams)); } @@ -5368,7 +5385,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, #endif DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog); /* params are supposed to be fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams_internal(params->cParams))); + assert(!ZSTD_isError(ZSTD_checkCCtxCParams_internal(params))); assert(!((dict) && (cdict))); /* either dict or cdict, not both */ if ( (cdict) && (cdict->dictContentSize > 0) @@ -5411,7 +5428,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, { DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog); /* compression parameters verification and optimization */ - FORWARD_IF_ERROR( ZSTD_checkCParams_internal(params->cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCCtxCParams_internal(params) , ""); return ZSTD_compressBegin_internal(cctx, dict, dictSize, dictContentType, dtlm, cdict, @@ -5567,7 +5584,7 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, { ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); DEBUGLOG(4, "ZSTD_compress_advanced"); - FORWARD_IF_ERROR(ZSTD_checkCParams_internal(params.cParams), ""); + FORWARD_IF_ERROR(ZSTD_checkCParams_internal(¶ms.cParams), ""); ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, ZSTD_NO_CLEVEL); return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, @@ -5687,7 +5704,7 @@ static size_t ZSTD_initCDict_internal( { DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType); - assert(!ZSTD_checkCParams_internal(params.cParams)); + assert(!ZSTD_checkCCtxCParams_internal(¶ms)); cdict->params = params; cdict->matchState.cctxParams = &cdict->params; cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch; @@ -6141,7 +6158,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, DEBUGLOG(4, "ZSTD_initCStream_internal"); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - assert(!ZSTD_isError(ZSTD_checkCParams_internal(params->cParams))); + assert(!ZSTD_isError(ZSTD_checkCCtxCParams_internal(params))); zcs->requestedParams = *params; assert(!((dict) && (cdict))); /* either dict or cdict, not both */ if (dict) { @@ -6195,7 +6212,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, DEBUGLOG(4, "ZSTD_initCStream_advanced"); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - FORWARD_IF_ERROR( ZSTD_checkCParams_internal(params.cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams_internal(¶ms.cParams) , ""); ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, ¶ms); FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); return 0; @@ -6569,7 +6586,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, } else #endif /* ZSTD_MULTITHREAD */ { U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1; - assert(!ZSTD_isError(ZSTD_checkCParams_internal(params.cParams))); + assert(!ZSTD_isError(ZSTD_checkCCtxCParams_internal(¶ms))); FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast, cctx->cdict, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index e6d65f6b1a4..4f9deafef2e 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1698,7 +1698,15 @@ void ZSTD_resetSeqStore(SeqStore_t* ssPtr); * as the name implies */ ZSTD_CParams ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict); -size_t ZSTD_checkCParams_internal(ZSTD_CParams cParams); +/*! ZSTD_checkCParams_internal() : + * Only used for cparams coming from the user. Checks are limited compared to + * checking the whole CCtxParams via the below. */ +size_t ZSTD_checkCParams_internal(const ZSTD_CParams* cParams); + +/*! ZSTD_checkCCtxCParams_internal() : + * Checks the CParams in the CCtxParams (including related parameters not + * *actually* stored in the CParams struct). */ +size_t ZSTD_checkCCtxCParams_internal(const ZSTD_CCtx_params* params); /* ZSTD_createCDict_internal() : * Private use only. To be called from zstdmt_compress.c. */ diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 42978f7bb01..e1b6ce41fd5 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1258,7 +1258,7 @@ size_t ZSTDMT_initCStream_internal( (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx); /* params supposed partially fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams_internal(params.cParams))); + assert(!ZSTD_isError(ZSTD_checkCCtxCParams_internal(¶ms))); assert(!((dict) && (cdict))); /* either dict or cdict, not both */ /* init */ From 004f3444db2956aaf00b32ae68d2cdf67c106ba6 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 20 Feb 2025 09:18:22 -0800 Subject: [PATCH 29/36] Convert `ZSTD_clampCParams()` to Operate on CCtxParams --- lib/compress/zstd_compress.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3b94f62e332..56486a82f82 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1446,10 +1446,9 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) } /** ZSTD_clampCParams() : - * make CParam values within valid range. - * @return : valid CParams */ -static ZSTD_CParams -ZSTD_clampCParams(ZSTD_CParams cParams) + * make CParam values within valid range. */ +static void +ZSTD_clampCParams(ZSTD_CCtx_params* params) { # define CLAMP_TYPE(cParam, val, type) \ do { \ @@ -1458,18 +1457,17 @@ ZSTD_clampCParams(ZSTD_CParams cParams) else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \ } while (0) # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) - CLAMP(ZSTD_c_windowLog, cParams.windowLog); + CLAMP(ZSTD_c_windowLog, params->cParams.windowLog); if (ZSTD_c_windowLog == ZSTD_WINDOWLOG_MAX) { - cParams.windowFrac = 0; - } - CLAMP(ZSTD_c_windowFrac, cParams.windowFrac); - CLAMP(ZSTD_c_chainLog, cParams.chainLog); - CLAMP(ZSTD_c_hashLog, cParams.hashLog); - CLAMP(ZSTD_c_searchLog, cParams.searchLog); - CLAMP(ZSTD_c_minMatch, cParams.minMatch); - CLAMP(ZSTD_c_targetLength, cParams.targetLength); - CLAMP_TYPE(ZSTD_c_strategy, cParams.strategy, ZSTD_strategy); - return cParams; + params->cParams.windowFrac = 0; + } + CLAMP(ZSTD_c_windowFrac, params->cParams.windowFrac); + CLAMP(ZSTD_c_chainLog, params->cParams.chainLog); + CLAMP(ZSTD_c_hashLog, params->cParams.hashLog); + CLAMP(ZSTD_c_searchLog, params->cParams.searchLog); + CLAMP(ZSTD_c_minMatch, params->cParams.minMatch); + CLAMP(ZSTD_c_targetLength, params->cParams.targetLength); + CLAMP_TYPE(ZSTD_c_strategy, params->cParams.strategy, ZSTD_strategy); } /** ZSTD_cycleLog() : @@ -1687,7 +1685,7 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, ZSTD_CCtx_params params; ZSTD_CCtxParams_init(¶ms, 0); params.cParams = ZSTD_getCParamsFromPublicCParams(cPar); - params.cParams = ZSTD_clampCParams(params.cParams); /* resulting cPar is necessarily valid (all parameters within range) */ + ZSTD_clampCParams(¶ms); /* resulting cPar is necessarily valid (all parameters within range) */ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; ZSTD_adjustCParams_internal(¶ms, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto); return ZSTD_getPublicCParamsFromCParams(params.cParams); From c5950775ba0ccf179cb68cc5e46d3a9bddeed500 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 20 Feb 2025 09:32:24 -0800 Subject: [PATCH 30/36] Convert `ZSTD_ldm_adjustParameters()` to take CCtxParams --- lib/compress/zstd_compress.c | 4 ++-- lib/compress/zstd_ldm.c | 16 ++++++++-------- lib/compress/zstd_ldm.h | 2 +- lib/compress/zstdmt_compress.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 56486a82f82..10dfe94b225 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -311,7 +311,7 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( /* Adjust advanced params according to cParams */ cctxParams.ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams.ldmParams.enableLdm, &cParams); if (cctxParams.ldmParams.enableLdm == ZSTD_ps_enable) { - ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams); + ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cctxParams); assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog); assert(cctxParams.ldmParams.hashRateLog < 32); } @@ -2256,7 +2256,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, assert(params->maxBlockSize != 0); if (params->ldmParams.enableLdm == ZSTD_ps_enable) { /* Adjust long distance matching parameters */ - ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, ¶ms->cParams); + ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, params); assert(params->ldmParams.hashLog >= params->ldmParams.bucketSizeLog); assert(params->ldmParams.hashRateLog < 32); } diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 8301058820d..b6a47cc9f55 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -133,10 +133,10 @@ static size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state, } void ZSTD_ldm_adjustParameters(ldmParams_t* params, - const ZSTD_CParams* cParams) + const ZSTD_CCtx_params* cctxParams) { - params->windowLog = cParams->windowLog; - params->windowFrac = cParams->windowFrac; + params->windowLog = cctxParams->cParams.windowLog; + params->windowFrac = cctxParams->cParams.windowFrac; ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX); DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (params->hashRateLog == 0) { @@ -147,9 +147,9 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, params->hashRateLog = params->windowLog - params->hashLog; } } else { - assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); + assert(1 <= (int)cctxParams->cParams.strategy && (int)cctxParams->cParams.strategy <= 9); /* mapping from [fast, rate7] to [btultra2, rate4] */ - params->hashRateLog = 7 - (cParams->strategy/3); + params->hashRateLog = 7 - (cctxParams->cParams.strategy/3); } } if (params->hashLog == 0) { @@ -157,12 +157,12 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, } if (params->minMatchLength == 0) { params->minMatchLength = LDM_MIN_MATCH_LENGTH; - if (cParams->strategy >= ZSTD_btultra) + if (cctxParams->cParams.strategy >= ZSTD_btultra) params->minMatchLength /= 2; } if (params->bucketSizeLog==0) { - assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); - params->bucketSizeLog = BOUNDED(LDM_BUCKET_SIZE_LOG, (U32)cParams->strategy, ZSTD_LDM_BUCKETSIZELOG_MAX); + assert(1 <= (int)cctxParams->cParams.strategy && (int)cctxParams->cParams.strategy <= 9); + params->bucketSizeLog = BOUNDED(LDM_BUCKET_SIZE_LOG, (U32)cctxParams->cParams.strategy, ZSTD_LDM_BUCKETSIZELOG_MAX); } params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog); } diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index 11f36d6d17e..f06b537866d 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -104,6 +104,6 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize); * Ensures that the minMatchLength >= targetLength during optimal parsing. */ void ZSTD_ldm_adjustParameters(ldmParams_t* params, - ZSTD_CParams const* cParams); + const ZSTD_CCtx_params* cctxParams); #endif /* ZSTD_FAST_H */ diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index e1b6ce41fd5..5c4f6609c4c 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -495,7 +495,7 @@ ZSTDMT_serialState_reset(SerialState* serialState, /* Adjust parameters */ if (params.ldmParams.enableLdm == ZSTD_ps_enable) { DEBUGLOG(4, "LDM window size = %u KB", ZSTD_windowSize(¶ms) >> 10); - ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams); + ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms); assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); assert(params.ldmParams.hashRateLog < 32); } else { From 4fad13e771c03e3870582d2d323ef9c775429374 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 20 Feb 2025 09:47:42 -0800 Subject: [PATCH 31/36] Move `windowFrac` Field out of CParams into CCtxParams --- lib/compress/clevels.h | 192 +++++++++++++------------- lib/compress/zstd_compress.c | 53 +++---- lib/compress/zstd_compress_internal.h | 22 +-- lib/compress/zstd_ldm.c | 2 +- lib/compress/zstdmt_compress.c | 2 - 5 files changed, 130 insertions(+), 141 deletions(-) diff --git a/lib/compress/clevels.h b/lib/compress/clevels.h index 0ff8875fdb3..4c8d12fabfe 100644 --- a/lib/compress/clevels.h +++ b/lib/compress/clevels.h @@ -24,108 +24,108 @@ __attribute__((__unused__)) static const ZSTD_CParams ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { { /* "default" - for any srcSize > 256 KB */ - /* W, WF, C, H, S, L, TL, strat */ - { 19, 0, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ - { 19, 0, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ - { 20, 0, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ - { 21, 0, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ - { 21, 0, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ - { 21, 0, 18, 19, 3, 5, 2, ZSTD_greedy }, /* level 5 */ - { 21, 0, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6 */ - { 21, 0, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */ - { 21, 0, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 8 */ - { 22, 0, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ - { 22, 0, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 10 */ - { 22, 0, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 11 */ - { 22, 0, 22, 23, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */ - { 22, 0, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */ - { 22, 0, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ - { 22, 0, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ - { 22, 0, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ - { 23, 0, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ - { 23, 0, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ - { 23, 0, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ - { 25, 0, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ - { 26, 0, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ - { 27, 0, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ + /* W, C, H, S, L, TL, strat */ + { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ + { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ + { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ + { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ + { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ + { 21, 18, 19, 3, 5, 2, ZSTD_greedy }, /* level 5 */ + { 21, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6 */ + { 21, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */ + { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 8 */ + { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ + { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 10 */ + { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 11 */ + { 22, 22, 23, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */ + { 22, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */ + { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ + { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ + { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ + { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ + { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ + { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ + { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ + { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ + { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ }, { /* for srcSize <= 256 KB */ - /* W, WF, C, H, S, L, T, strat */ - { 18, 0, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 18, 0, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 18, 0, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ - { 18, 0, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ - { 18, 0, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/ - { 18, 0, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/ - { 18, 0, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ - { 18, 0, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ - { 18, 0, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 18, 0, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 18, 0, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 18, 0, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ - { 18, 0, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ - { 18, 0, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ - { 18, 0, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 18, 0, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ - { 18, 0, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 18, 0, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 18, 0, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ - { 18, 0, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 18, 0, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 18, 0, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 18, 0, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ + /* W, C, H, S, L, T, strat */ + { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ + { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ + { 18, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/ + { 18, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/ + { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ + { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ + { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ + { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ + { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ + { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ }, { /* for srcSize <= 128 KB */ - /* W, WF, C, H, S, L, T, strat */ - { 17, 0, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 17, 0, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 17, 0, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ - { 17, 0, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ - { 17, 0, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ - { 17, 0, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ - { 17, 0, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ - { 17, 0, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 17, 0, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 17, 0, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 17, 0, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 17, 0, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ - { 17, 0, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ - { 17, 0, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ - { 17, 0, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 17, 0, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ - { 17, 0, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 17, 0, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 17, 0, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ - { 17, 0, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 17, 0, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 17, 0, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 17, 0, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ + /* W, C, H, S, L, T, strat */ + { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ + { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ + { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ + { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ + { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ + { 17, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 17, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 17, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 17, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ + { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ + { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ + { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ + { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ + { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ }, { /* for srcSize <= 16 KB */ - /* W, WF, C, H, S, L, T, strat */ - { 14, 0, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 14, 0, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ - { 14, 0, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ - { 14, 0, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ - { 14, 0, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ - { 14, 0, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ - { 14, 0, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ - { 14, 0, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 14, 0, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ - { 14, 0, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ - { 14, 0, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ - { 14, 0, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ - { 14, 0, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ - { 14, 0, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ - { 14, 0, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ - { 14, 0, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ - { 14, 0, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ - { 14, 0, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ - { 14, 0, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ - { 14, 0, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 14, 0, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 14, 0, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 14, 0, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ + /* W, C, H, S, L, T, strat */ + { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ + { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ + { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ + { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ + { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ + { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ + { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ + { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ + { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ + { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ + { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ + { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ + { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ + { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ + { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ + { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ }, }; diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 10dfe94b225..a4bdcfe437e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -801,18 +801,18 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, BOUNDCHECK(ZSTD_c_windowLog, value); CCtxParams->cParams.windowLog = (U32)value; if (value == ZSTD_WINDOWLOG_MAX) { - CCtxParams->cParams.windowFrac = 0; + CCtxParams->windowFrac = 0; } return CCtxParams->cParams.windowLog; case ZSTD_c_windowFrac : BOUNDCHECK(ZSTD_c_windowFrac, value); if (CCtxParams->cParams.windowLog != ZSTD_WINDOWLOG_MAX) { - CCtxParams->cParams.windowFrac = (U32)value; + CCtxParams->windowFrac = (U32)value; } else { - CCtxParams->cParams.windowFrac = 0; + CCtxParams->windowFrac = 0; } - return CCtxParams->cParams.windowFrac; + return CCtxParams->windowFrac; case ZSTD_c_hashLog : if (value!=0) /* 0 => use default */ @@ -1060,7 +1060,7 @@ size_t ZSTD_CCtxParams_getParameter( *value = (int)CCtxParams->cParams.windowLog; break; case ZSTD_c_windowFrac : - *value = (int)CCtxParams->cParams.windowFrac; + *value = (int)CCtxParams->windowFrac; break; case ZSTD_c_hashLog : *value = (int)CCtxParams->cParams.hashLog; @@ -1407,10 +1407,6 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) size_t ZSTD_checkCParams_internal(const ZSTD_CParams* cParams) { BOUNDCHECK(ZSTD_c_windowLog, (int)cParams->windowLog); - BOUNDCHECK(ZSTD_c_windowFrac, (int)cParams->windowFrac); - RETURN_ERROR_IF( - cParams->windowLog + !!cParams->windowFrac > ZSTD_WINDOWLOG_MAX, - parameter_outOfBound, "Param out of bounds"); BOUNDCHECK(ZSTD_c_chainLog, (int)cParams->chainLog); BOUNDCHECK(ZSTD_c_hashLog, (int)cParams->hashLog); BOUNDCHECK(ZSTD_c_searchLog, (int)cParams->searchLog); @@ -1423,9 +1419,9 @@ size_t ZSTD_checkCParams_internal(const ZSTD_CParams* cParams) size_t ZSTD_checkCCtxCParams_internal(const ZSTD_CCtx_params* params) { BOUNDCHECK(ZSTD_c_windowLog, (int)params->cParams.windowLog); - BOUNDCHECK(ZSTD_c_windowFrac, (int)params->cParams.windowFrac); + BOUNDCHECK(ZSTD_c_windowFrac, (int)params->windowFrac); RETURN_ERROR_IF( - params->cParams.windowLog + !!params->cParams.windowFrac > ZSTD_WINDOWLOG_MAX, + params->cParams.windowLog + !!params->windowFrac > ZSTD_WINDOWLOG_MAX, parameter_outOfBound, "Param out of bounds"); BOUNDCHECK(ZSTD_c_chainLog, (int)params->cParams.chainLog); BOUNDCHECK(ZSTD_c_hashLog, (int)params->cParams.hashLog); @@ -1458,10 +1454,10 @@ ZSTD_clampCParams(ZSTD_CCtx_params* params) } while (0) # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) CLAMP(ZSTD_c_windowLog, params->cParams.windowLog); - if (ZSTD_c_windowLog == ZSTD_WINDOWLOG_MAX) { - params->cParams.windowFrac = 0; + if (params->cParams.windowLog == ZSTD_WINDOWLOG_MAX) { + params->windowFrac = 0; } - CLAMP(ZSTD_c_windowFrac, params->cParams.windowFrac); + CLAMP(ZSTD_c_windowFrac, params->windowFrac); CLAMP(ZSTD_c_chainLog, params->cParams.chainLog); CLAMP(ZSTD_c_hashLog, params->cParams.hashLog); CLAMP(ZSTD_c_searchLog, params->cParams.searchLog); @@ -1492,7 +1488,7 @@ static void ZSTD_dictAndWindowLog(ZSTD_CCtx_params* params, U64 srcSize, U64 dic if (dictSize == 0) { return; } - assert(params->cParams.windowLog + !!params->cParams.windowFrac <= ZSTD_WINDOWLOG_MAX); + assert(params->cParams.windowLog + !!params->windowFrac <= ZSTD_WINDOWLOG_MAX); assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */ { U64 const windowSize = ZSTD_windowSize(params); @@ -1605,7 +1601,7 @@ ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, if (ZSTD_windowSize(params) > tSize) { if (tSize < hashSizeMin) { cPar->windowLog = ZSTD_HASHLOG_MIN; - cPar->windowFrac = 0; + params->windowFrac = 0; } else #if !ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES /* Prevents adjustment in the scenario where we have explicitly @@ -1624,10 +1620,10 @@ ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, ZSTD_CCtx_params dictWindowParams = *params; U32 const cycleLog = ZSTD_cycleLog(cPar->chainLog, cPar->strategy); ZSTD_dictAndWindowLog(&dictWindowParams, (U64)srcSize, (U64)dictSize); - if (dictWindowParams.cParams.windowFrac != 0) { + if (dictWindowParams.windowFrac != 0) { /* Round up to a whole power of two. */ dictWindowParams.cParams.windowLog++; - dictWindowParams.cParams.windowFrac = 0; + dictWindowParams.windowFrac = 0; } if (cPar->hashLog > dictWindowParams.cParams.windowLog+1) cPar->hashLog = dictWindowParams.cParams.windowLog+1; @@ -1637,7 +1633,7 @@ ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, if (cPar->windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) { cPar->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */ - cPar->windowFrac = 0; + params->windowFrac = 0; } /* We can't use more than 32 bits of hash in total, so that means that we require: @@ -1695,7 +1691,6 @@ ZSTD_CParams ZSTD_getCParamsFromPublicCParams( ZSTD_compressionParameters cParams) { ZSTD_CParams ret; ret.windowLog = cParams.windowLog; - ret.windowFrac = 0; ret.chainLog = cParams.chainLog; ret.hashLog = cParams.hashLog; ret.searchLog = cParams.searchLog; @@ -1740,8 +1735,6 @@ static void ZSTD_overrideCParams( const ZSTD_CParams* overrides) { if (overrides->windowLog) cParams->windowLog = overrides->windowLog; - /* An explicit windowFrac only applies if windowLog is set explicitly. */ - if (overrides->windowLog) cParams->windowFrac = overrides->windowFrac; if (overrides->hashLog) cParams->hashLog = overrides->hashLog; if (overrides->chainLog) cParams->chainLog = overrides->chainLog; if (overrides->searchLog) cParams->searchLog = overrides->searchLog; @@ -1762,7 +1755,6 @@ ZSTD_CParams ZSTD_getCParamsFromCCtxParams( ZSTD_CParams cParams = ZSTD_getCParams_internal(params.compressionLevel, srcSizeHint, dictSize, mode); if (params.ldmParams.enableLdm == ZSTD_ps_enable) { cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; - cParams.windowFrac = 0; } ZSTD_overrideCParams(&cParams, ¶ms.cParams); params.cParams = cParams; @@ -2041,7 +2033,6 @@ static void ZSTD_assertEqualCParams(ZSTD_CParams cParams1, (void)cParams1; (void)cParams2; assert(cParams1.windowLog == cParams2.windowLog); - assert(cParams1.windowFrac == cParams2.windowFrac); assert(cParams1.chainLog == cParams2.chainLog); assert(cParams1.hashLog == cParams2.hashLog); assert(cParams1.searchLog == cParams2.searchLog); @@ -2464,7 +2455,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, { ZSTD_CCtx_params adjusted_cdict_params = cdict->params; unsigned const windowLog = params.cParams.windowLog; - unsigned const windowFrac = params.cParams.windowFrac; + unsigned const windowFrac = params.windowFrac; assert(windowLog != 0); /* Resize working context table params for input only, since the dict * has its own tables. */ @@ -2479,7 +2470,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, params.useRowMatchFinder); params.cParams = adjusted_cdict_params.cParams; params.cParams.windowLog = windowLog; - params.cParams.windowFrac = windowFrac; + params.windowFrac = windowFrac; params.useRowMatchFinder = cdict->params.useRowMatchFinder; /* cdict overrides */ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, /* loadedDictSize */ 0, @@ -2546,12 +2537,12 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, (unsigned long long)pledgedSrcSize); { unsigned const windowLog = params.cParams.windowLog; - unsigned const windowFrac = params.cParams.windowFrac; + unsigned const windowFrac = params.windowFrac; assert(windowLog != 0); /* Copy only compression parameters related to tables. */ params.cParams = *cdict_cParams; params.cParams.windowLog = windowLog; - params.cParams.windowFrac = windowFrac; + params.windowFrac = windowFrac; params.useRowMatchFinder = cdict->params.useRowMatchFinder; FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, /* loadedDictSize */ 0, @@ -2671,7 +2662,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, /* loadedDictSize */ 0, ZSTDcrp_leaveDirty, zbuff); assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog); - assert(dstCCtx->appliedParams.cParams.windowFrac == srcCCtx->appliedParams.cParams.windowFrac); + assert(dstCCtx->appliedParams.windowFrac == srcCCtx->appliedParams.windowFrac); assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy); assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog); assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog); @@ -4737,7 +4728,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, U32 const maxDist = ZSTD_windowSize(&cctx->appliedParams); S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; - assert(cctx->appliedParams.cParams.windowLog + !!cctx->appliedParams.cParams.windowFrac <= ZSTD_WINDOWLOG_MAX); + assert(cctx->appliedParams.cParams.windowLog + !!cctx->appliedParams.windowFrac <= ZSTD_WINDOWLOG_MAX); DEBUGLOG(5, "ZSTD_compress_frameChunk (srcSize=%u, blockSizeMax=%u)", (unsigned)srcSize, (unsigned)blockSizeMax); if (cctx->appliedParams.fParams.checksumFlag && srcSize) @@ -4838,7 +4829,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, U32 const checksumFlag = params->fParams.checksumFlag>0; U32 const windowSize = ZSTD_windowSize(params); U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); - BYTE const windowByte = (BYTE)(((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3) | (params->cParams.windowFrac & 7)); + BYTE const windowByte = (BYTE)(((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3) | (params->windowFrac & 7)); U32 const fcsCode = params->fParams.contentSizeFlag ? (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */ BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 4f9deafef2e..cdd7ca749d9 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -195,8 +195,7 @@ size_t ZSTD_buildBlockEntropyStats( * Internal equivalent of public ZSTD_compressionParameters struct. */ typedef struct { - unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ - unsigned windowFrac; /**< fractional component of window size representation */ + unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression, see also `windowFrac` in CCtxParams */ unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ unsigned hashLog; /**< dispatch table : larger == faster, more memory */ unsigned searchLog; /**< nb of searches : larger == more compression, slower */ @@ -388,6 +387,7 @@ typedef struct { struct ZSTD_CCtx_params_s { ZSTD_format_e format; ZSTD_CParams cParams; + unsigned windowFrac; /* Additional CParam controlling sub-power-of-two window sizing. */ ZSTD_frameParameters fParams; int compressionLevel; @@ -1120,7 +1120,7 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) * provided CParams. */ MEM_STATIC U32 ZSTD_windowSize(const ZSTD_CCtx_params* params) { - return (U32)(((8ull + params->cParams.windowFrac) << params->cParams.windowLog) >> 3); + return (U32)(((8ull + params->windowFrac) << params->cParams.windowLog) >> 3); } MEM_STATIC U32 ZSTD_windowSizeLDM(const ldmParams_t* ldmParams) { return (U32)(((8ull + ldmParams->windowFrac) << ldmParams->windowLog) >> 3); @@ -1159,28 +1159,28 @@ MEM_STATIC void ZSTD_setMinimalWindowLogAndFrac(ZSTD_CCtx_params* params, const #if ZSTD_WINDOW_ALLOW_PICKING_FRACTIONAL_SIZES if (srcSize < minSize) { params->cParams.windowLog = minWindowLog; - params->cParams.windowFrac = 0; + params->windowFrac = 0; } else { const U32 srcSizeMinusOne = srcSize - 1; params->cParams.windowLog = ZSTD_highbit32(srcSizeMinusOne); - params->cParams.windowFrac = ((srcSizeMinusOne >> (params->cParams.windowLog - 3)) & 7) + 1; - if (params->cParams.windowFrac == 8) { - params->cParams.windowFrac = 0; + params->windowFrac = ((srcSizeMinusOne >> (params->cParams.windowLog - 3)) & 7) + 1; + if (params->windowFrac == 8) { + params->windowFrac = 0; params->cParams.windowLog++; } } #else if (srcSize < minSize) { params->cParams.windowLog = minWindowLog; - params->cParams.windowFrac = 0; + params->windowFrac = 0; } else { params->cParams.windowLog = ZSTD_highbit32(srcSize - 1) + 1; - params->cParams.windowFrac = 0; + params->windowFrac = 0; } #endif - if (params->cParams.windowLog + !!params->cParams.windowFrac > ZSTD_WINDOWLOG_MAX) { + if (params->cParams.windowLog + !!params->windowFrac > ZSTD_WINDOWLOG_MAX) { params->cParams.windowLog = ZSTD_WINDOWLOG_MAX; - params->cParams.windowFrac = 0; + params->windowFrac = 0; } assert(ZSTD_windowLogAndFracAreMinimal(params, srcSize)); } diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index b6a47cc9f55..dedb81e86fb 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -136,7 +136,7 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, const ZSTD_CCtx_params* cctxParams) { params->windowLog = cctxParams->cParams.windowLog; - params->windowFrac = cctxParams->cParams.windowFrac; + params->windowFrac = cctxParams->windowFrac; ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX); DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (params->hashRateLog == 0) { diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 5c4f6609c4c..f7f3fce5283 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1096,14 +1096,12 @@ static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers) void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams) { U32 const saved_wlog = mtctx->params.cParams.windowLog; /* Do not modify windowLog while compressing */ - U32 const saved_wfrac = mtctx->params.cParams.windowFrac; /* Do not modify windowFrac while compressing */ int const compressionLevel = cctxParams->compressionLevel; DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; { ZSTD_CParams cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); cParams.windowLog = saved_wlog; - cParams.windowFrac = saved_wfrac; mtctx->params.cParams = cParams; } } From 196ac9d3cc0e77850938c92b436ba7c22851a85d Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 20 Feb 2025 10:11:28 -0800 Subject: [PATCH 32/36] Unify CParams / Params Structs Unwind the public/private distinction. --- lib/compress/clevels.h | 4 +- lib/compress/zstd_compress.c | 248 +++++++++----------------- lib/compress/zstd_compress_internal.h | 61 +------ lib/compress/zstd_double_fast.c | 12 +- lib/compress/zstd_fast.c | 12 +- lib/compress/zstd_lazy.c | 18 +- lib/compress/zstd_ldm.c | 2 +- lib/compress/zstd_opt.c | 8 +- lib/compress/zstdmt_compress.c | 11 +- 9 files changed, 120 insertions(+), 256 deletions(-) diff --git a/lib/compress/clevels.h b/lib/compress/clevels.h index 4c8d12fabfe..c18da465f32 100644 --- a/lib/compress/clevels.h +++ b/lib/compress/clevels.h @@ -11,7 +11,7 @@ #ifndef ZSTD_CLEVELS_H #define ZSTD_CLEVELS_H -#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_CParams */ +#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */ #include "../zstd.h" /*-===== Pre-defined compression levels =====-*/ @@ -22,7 +22,7 @@ __attribute__((__unused__)) #endif -static const ZSTD_CParams ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { +static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { { /* "default" - for any srcSize > 256 KB */ /* W, C, H, S, L, TL, strat */ { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a4bdcfe437e..77d7960702f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -235,7 +235,7 @@ static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_Para /* Returns row matchfinder usage given an initial mode and cParams */ static ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode, - const ZSTD_CParams* const cParams) { + const ZSTD_compressionParameters* const cParams) { if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */ mode = ZSTD_ps_disable; if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode; @@ -245,7 +245,7 @@ static ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode /* Returns block splitter usage (generally speaking, when using slower/stronger compression modes) */ static ZSTD_ParamSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_ParamSwitch_e mode, - const ZSTD_CParams* const cParams) { + const ZSTD_compressionParameters* const cParams) { if (mode != ZSTD_ps_auto) return mode; return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17) ? ZSTD_ps_enable : ZSTD_ps_disable; } @@ -267,7 +267,7 @@ static int ZSTD_allocateChainTable(const ZSTD_strategy strategy, */ static ZSTD_ParamSwitch_e ZSTD_resolveEnableLdm( ZSTD_ParamSwitch_e mode, - const ZSTD_CParams* const cParams) { + const ZSTD_compressionParameters* const cParams) { if (mode != ZSTD_ps_auto) return mode; return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable; } @@ -296,12 +296,12 @@ static ZSTD_ParamSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_ParamSwitch_e v /* Returns 1 if compression parameters are such that CDict hashtable and chaintable indices are tagged. * If so, the tags need to be removed in ZSTD_resetCCtx_byCopyingCDict. */ -static int ZSTD_CDictIndicesAreTagged(const ZSTD_CParams* const cParams) { +static int ZSTD_CDictIndicesAreTagged(const ZSTD_compressionParameters* const cParams) { return cParams->strategy == ZSTD_fast || cParams->strategy == ZSTD_dfast; } static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( - ZSTD_CParams cParams) + ZSTD_compressionParameters cParams) { ZSTD_CCtx_params cctxParams; /* should not matter, as all cParams are presumed properly defined */ @@ -371,10 +371,10 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) */ static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, - const ZSTD_Params* params, + const ZSTD_parameters* params, int compressionLevel) { - assert(!ZSTD_checkCParams_internal(¶ms->cParams)); + assert(!ZSTD_checkCParams(params->cParams)); ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); cctxParams->cParams = params->cParams; cctxParams->fParams = params->fParams; @@ -392,11 +392,10 @@ ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, cctxParams->useRowMatchFinder, cctxParams->postBlockSplitter, cctxParams->ldmParams.enableLdm); } -size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters publicParams) +size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) { - ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); - FORWARD_IF_ERROR( ZSTD_checkCParams_internal(¶ms.cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); ZSTD_CCtxParams_init_internal(cctxParams, ¶ms, ZSTD_NO_CLEVEL); return 0; } @@ -406,9 +405,9 @@ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_paramete * @param params Validated zstd parameters. */ static void ZSTD_CCtxParams_setZstdParams( - ZSTD_CCtx_params* cctxParams, const ZSTD_Params* params) + ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) { - assert(!ZSTD_checkCParams_internal(¶ms->cParams)); + assert(!ZSTD_checkCParams(params->cParams)); cctxParams->cParams = params->cParams; cctxParams->fParams = params->fParams; /* Should not matter, as all cParams are presumed properly defined. @@ -1259,13 +1258,13 @@ size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSr return 0; } -static ZSTD_CParams ZSTD_dedicatedDictSearch_getCParams( +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams( int const compressionLevel, size_t const dictSize); static int ZSTD_dedicatedDictSearch_isSupported( - const ZSTD_CParams* cParams); + const ZSTD_compressionParameters* cParams); static void ZSTD_dedicatedDictSearch_revertCParams( - ZSTD_CParams* cParams); + ZSTD_compressionParameters* cParams); /** * Initializes the local dictionary using requested parameters. @@ -1404,18 +1403,6 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) return 0; } -size_t ZSTD_checkCParams_internal(const ZSTD_CParams* cParams) -{ - BOUNDCHECK(ZSTD_c_windowLog, (int)cParams->windowLog); - BOUNDCHECK(ZSTD_c_chainLog, (int)cParams->chainLog); - BOUNDCHECK(ZSTD_c_hashLog, (int)cParams->hashLog); - BOUNDCHECK(ZSTD_c_searchLog, (int)cParams->searchLog); - BOUNDCHECK(ZSTD_c_minMatch, (int)cParams->minMatch); - BOUNDCHECK(ZSTD_c_targetLength, (int)cParams->targetLength); - BOUNDCHECK(ZSTD_c_strategy, (int)cParams->strategy); - return 0; -} - size_t ZSTD_checkCCtxCParams_internal(const ZSTD_CCtx_params* params) { BOUNDCHECK(ZSTD_c_windowLog, (int)params->cParams.windowLog); @@ -1433,12 +1420,20 @@ size_t ZSTD_checkCCtxCParams_internal(const ZSTD_CCtx_params* params) } /** ZSTD_checkCParams() : - control CParam values remain within authorized range. + Control CParam values remain within authorized range. Only used for + cparams coming from the user. Checks are limited compared to checking the + whole CCtxParams via the `ZSTD_checkCCtxCParams_internal()`. @return : 0, or an error code if one value is beyond authorized range */ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) { - ZSTD_CParams cPar = ZSTD_getCParamsFromPublicCParams(cParams); - return ZSTD_checkCParams_internal(&cPar); + BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); + BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); + BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); + BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); + BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); + BOUNDCHECK(ZSTD_c_targetLength, (int)cParams.targetLength); + BOUNDCHECK(ZSTD_c_strategy, (int)cParams.strategy); + return 0; } /** ZSTD_clampCParams() : @@ -1519,7 +1514,7 @@ ZSTD_adjustCParams_internal(ZSTD_CCtx_params* params, ZSTD_CParamMode_e mode, ZSTD_ParamSwitch_e useRowMatchFinder) { - ZSTD_CParams* cPar = ¶ms->cParams; + ZSTD_compressionParameters* cPar = ¶ms->cParams; const U64 minSrcSize = 513; /* (1<<9) + 1 */ const U64 maxWindowResize = 15ULL << (ZSTD_WINDOWLOG_MAX-4); assert(ZSTD_checkCCtxCParams_internal(params)==0); @@ -1680,59 +1675,19 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, { ZSTD_CCtx_params params; ZSTD_CCtxParams_init(¶ms, 0); - params.cParams = ZSTD_getCParamsFromPublicCParams(cPar); + params.cParams = cPar; ZSTD_clampCParams(¶ms); /* resulting cPar is necessarily valid (all parameters within range) */ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; ZSTD_adjustCParams_internal(¶ms, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto); - return ZSTD_getPublicCParamsFromCParams(params.cParams); -} - -ZSTD_CParams ZSTD_getCParamsFromPublicCParams( - ZSTD_compressionParameters cParams) { - ZSTD_CParams ret; - ret.windowLog = cParams.windowLog; - ret.chainLog = cParams.chainLog; - ret.hashLog = cParams.hashLog; - ret.searchLog = cParams.searchLog; - ret.minMatch = cParams.minMatch; - ret.targetLength = cParams.targetLength; - ret.strategy = cParams.strategy; - return ret; -} - -ZSTD_compressionParameters ZSTD_getPublicCParamsFromCParams( - ZSTD_CParams cParams) { - ZSTD_compressionParameters ret; - ret.windowLog = cParams.windowLog; - ret.chainLog = cParams.chainLog; - ret.hashLog = cParams.hashLog; - ret.searchLog = cParams.searchLog; - ret.minMatch = cParams.minMatch; - ret.targetLength = cParams.targetLength; - ret.strategy = cParams.strategy; - return ret; -} - -ZSTD_Params ZSTD_getParamsFromPublicParams(ZSTD_parameters params) { - ZSTD_Params ret; - ret.cParams = ZSTD_getCParamsFromPublicCParams(params.cParams); - ret.fParams = params.fParams; - return ret; -} - -ZSTD_parameters ZSTD_getPublicParamsFromParams(ZSTD_Params params) { - ZSTD_parameters ret; - ret.cParams = ZSTD_getPublicCParamsFromCParams(params.cParams); - ret.fParams = params.fParams; - return ret; + return params.cParams; } -static ZSTD_CParams ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); -static ZSTD_Params ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); static void ZSTD_overrideCParams( - ZSTD_CParams* cParams, - const ZSTD_CParams* overrides) + ZSTD_compressionParameters* cParams, + const ZSTD_compressionParameters* overrides) { if (overrides->windowLog) cParams->windowLog = overrides->windowLog; if (overrides->hashLog) cParams->hashLog = overrides->hashLog; @@ -1743,7 +1698,7 @@ static void ZSTD_overrideCParams( if (overrides->strategy) cParams->strategy = overrides->strategy; } -ZSTD_CParams ZSTD_getCParamsFromCCtxParams( +ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( const ZSTD_CCtx_params* cctxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) { ZSTD_CCtx_params params = *cctxParams; @@ -1752,7 +1707,7 @@ ZSTD_CParams ZSTD_getCParamsFromCCtxParams( srcSizeHint = (U64)params.srcSizeHint; } { - ZSTD_CParams cParams = ZSTD_getCParams_internal(params.compressionLevel, srcSizeHint, dictSize, mode); + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(params.compressionLevel, srcSizeHint, dictSize, mode); if (params.ldmParams.enableLdm == ZSTD_ps_enable) { cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; } @@ -1767,7 +1722,7 @@ ZSTD_CParams ZSTD_getCParamsFromCCtxParams( } static size_t -ZSTD_sizeof_matchState(const ZSTD_CParams* const cParams, +ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, const ZSTD_ParamSwitch_e useRowMatchFinder, const int enableDedicatedDictSearch, const U32 forCCtx) @@ -1878,7 +1833,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) &par, 1, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN); } -static size_t ZSTD_estimateCCtxSize_usingCParams_internal(ZSTD_CParams cParams) +size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) { ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { @@ -1895,12 +1850,6 @@ static size_t ZSTD_estimateCCtxSize_usingCParams_internal(ZSTD_CParams cParams) } } -size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters publicParams) -{ - ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); - return ZSTD_estimateCCtxSize_usingCParams_internal(cParams); -} - static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) { int tier = 0; @@ -1908,8 +1857,8 @@ static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN}; for (; tier < 4; ++tier) { /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */ - ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); - largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams_internal(cParams), largestSize); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); + largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize); } return largestSize; } @@ -1948,7 +1897,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) } } -static size_t ZSTD_estimateCStreamSize_usingCParams_internal(ZSTD_CParams cParams) +size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) { ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { @@ -1965,16 +1914,10 @@ static size_t ZSTD_estimateCStreamSize_usingCParams_internal(ZSTD_CParams cParam } } -size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters publicParams) -{ - ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); - return ZSTD_estimateCStreamSize_usingCParams_internal(cParams); -} - static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) { - ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); - return ZSTD_estimateCStreamSize_usingCParams_internal(cParams); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + return ZSTD_estimateCStreamSize_usingCParams(cParams); } size_t ZSTD_estimateCStreamSize(int compressionLevel) @@ -2027,8 +1970,8 @@ size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx) return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */ } -static void ZSTD_assertEqualCParams(ZSTD_CParams cParams1, - ZSTD_CParams cParams2) +static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1, + ZSTD_compressionParameters cParams2) { (void)cParams1; (void)cParams2; @@ -2114,7 +2057,7 @@ ZSTD_reset_matchState(ZSTD_MatchState_t* ms, const ZSTD_indexResetPolicy_e forceResetIndex, const ZSTD_resetTarget_e forWho) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; const ZSTD_ParamSwitch_e useRowMatchFinder = ms->cctxParams->useRowMatchFinder; /* disable chain table allocation for fast or row-based strategies */ size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, @@ -2509,7 +2452,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, } static void ZSTD_copyCDictTableIntoCCtx(U32* dst, U32 const* src, size_t tableSize, - ZSTD_CParams const* cParams) { + ZSTD_compressionParameters const* cParams) { if (ZSTD_CDictIndicesAreTagged(cParams)){ /* Remove tags from the CDict table if they are present. * See docs on "short cache" in zstd_compress_internal.h for context. */ @@ -2530,7 +2473,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { - const ZSTD_CParams *cdict_cParams = &cdict->params.cParams; + const ZSTD_compressionParameters *cdict_cParams = &cdict->params.cParams; assert(!cdict->matchState.dedicatedDictSearch); DEBUGLOG(4, "ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu", @@ -3362,7 +3305,7 @@ static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seq /** * Function to validate sequences produced by a block compressor. */ -static void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_CParams* cParams) +static void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_compressionParameters* cParams) { #if DEBUGLEVEL >= 1 const SeqDef* seq = seqStore->sequencesStart; @@ -5429,11 +5372,10 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, * @return : 0, or an error code */ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, - ZSTD_parameters publicParams, + ZSTD_parameters params, unsigned long long pledgedSrcSize) { ZSTD_CCtx_params cctxParams; - ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL); return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, @@ -5445,7 +5387,7 @@ static size_t ZSTD_compressBegin_usingDict_deprecated(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { ZSTD_CCtx_params cctxParams; - { ZSTD_Params const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); + { ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel); } DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); @@ -5569,11 +5511,10 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict,size_t dictSize, - ZSTD_parameters publicParams) + ZSTD_parameters params) { - ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); DEBUGLOG(4, "ZSTD_compress_advanced"); - FORWARD_IF_ERROR(ZSTD_checkCParams_internal(¶ms.cParams), ""); + FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, ZSTD_NO_CLEVEL); return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, @@ -5604,7 +5545,7 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, int compressionLevel) { { - ZSTD_Params const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); assert(params.fParams.contentSizeFlag == 1); ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel); } @@ -5644,8 +5585,10 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, /* ===== Dictionary API ===== */ -static size_t ZSTD_estimateCDictSize_internal( - size_t dictSize, ZSTD_CParams cParams, +/*! ZSTD_estimateCDictSize_advanced() : + * Estimate amount of memory that will be needed to create a dictionary with following arguments */ +size_t ZSTD_estimateCDictSize_advanced( + size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod) { DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict)); @@ -5659,20 +5602,10 @@ static size_t ZSTD_estimateCDictSize_internal( : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *)))); } -/*! ZSTD_estimateCDictSize_advanced() : - * Estimate amount of memory that will be needed to create a dictionary with following arguments */ -size_t ZSTD_estimateCDictSize_advanced( - size_t dictSize, ZSTD_compressionParameters publicParams, - ZSTD_dictLoadMethod_e dictLoadMethod) -{ - ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); - return ZSTD_estimateCDictSize_internal(dictSize, cParams, dictLoadMethod); -} - size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) { - ZSTD_CParams const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - return ZSTD_estimateCDictSize_internal(dictSize, cParams, ZSTD_dlm_byCopy); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); } size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) @@ -5740,7 +5673,7 @@ static size_t ZSTD_initCDict_internal( static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_CParams cParams, + ZSTD_compressionParameters cParams, ZSTD_ParamSwitch_e useRowMatchFinder, int enableDedicatedDictSearch, ZSTD_customMem customMem) @@ -5775,10 +5708,10 @@ ZSTD_createCDict_advanced_internal(size_t dictSize, } } -ZSTD_CDict* ZSTD_createCDict_internal(const void* dictBuffer, size_t dictSize, +ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, - ZSTD_CParams cParams, + ZSTD_compressionParameters cParams, ZSTD_customMem customMem) { ZSTD_CCtx_params cctxParams; @@ -5793,19 +5726,6 @@ ZSTD_CDict* ZSTD_createCDict_internal(const void* dictBuffer, size_t dictSize, &cctxParams, customMem); } -ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters publicParams, - ZSTD_customMem customMem) -{ - ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); - return ZSTD_createCDict_internal( - dictBuffer, dictSize, - dictLoadMethod, dictContentType, - cParams, customMem); -} - ZSTD_CDict* ZSTD_createCDict_advanced2( const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, @@ -5814,7 +5734,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_customMem customMem) { ZSTD_CCtx_params cctxParams = *originalCctxParams; - ZSTD_CParams cParams; + ZSTD_compressionParameters cParams; ZSTD_CDict* cdict; DEBUGLOG(3, "ZSTD_createCDict_advanced2, dictSize=%u, mode=%u", (unsigned)dictSize, (unsigned)dictContentType); @@ -5858,8 +5778,8 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_CParams cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - ZSTD_CDict* const cdict = ZSTD_createCDict_internal( + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); @@ -5870,8 +5790,8 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_CParams cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - ZSTD_CDict* const cdict = ZSTD_createCDict_internal( + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); @@ -5911,9 +5831,8 @@ const ZSTD_CDict* ZSTD_initStaticCDict( const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters publicParams) + ZSTD_compressionParameters cParams) { - ZSTD_CParams cParams = ZSTD_getCParamsFromPublicCParams(publicParams); ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams); /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */ size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0); @@ -5952,7 +5871,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict( return cdict; } -ZSTD_CParams ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) +ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) { assert(cdict != NULL); return cdict->params.cParams; @@ -5980,7 +5899,7 @@ static size_t ZSTD_compressBegin_usingCDict_internal( RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!"); /* Initialize the cctxParams from the cdict */ { - ZSTD_Params params; + ZSTD_parameters params; params.fParams = fParams; if ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER @@ -6190,9 +6109,8 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict) * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, - ZSTD_parameters publicParams, unsigned long long pss) + ZSTD_parameters params, unsigned long long pss) { - ZSTD_Params params = ZSTD_getParamsFromPublicParams(publicParams); /* for compatibility with older programs relying on this behavior. * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. * This line will be removed in the future. @@ -6201,7 +6119,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, DEBUGLOG(4, "ZSTD_initCStream_advanced"); FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - FORWARD_IF_ERROR( ZSTD_checkCParams_internal(¶ms.cParams) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, ¶ms); FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); return 0; @@ -7832,9 +7750,9 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; } -static ZSTD_CParams ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) { - ZSTD_CParams cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); switch (cParams.strategy) { case ZSTD_fast: case ZSTD_dfast: @@ -7854,7 +7772,7 @@ static ZSTD_CParams ZSTD_dedicatedDictSearch_getCParams(int const compressionLev } static int ZSTD_dedicatedDictSearch_isSupported( - ZSTD_CParams const* cParams) + ZSTD_compressionParameters const* cParams) { return (cParams->strategy >= ZSTD_greedy) && (cParams->strategy <= ZSTD_lazy2) @@ -7868,7 +7786,7 @@ static int ZSTD_dedicatedDictSearch_isSupported( * context. (Otherwise, those tables would also grow.) */ static void ZSTD_dedicatedDictSearch_revertCParams( - ZSTD_CParams* cParams) { + ZSTD_compressionParameters* cParams) { switch (cParams->strategy) { case ZSTD_fast: case ZSTD_dfast: @@ -7910,11 +7828,11 @@ static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_CParamMo } /*! ZSTD_getCParams_internal() : - * @return ZSTD_CParams structure for a selected compression level, srcSize and dictSize. + * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. * Use dictSize == 0 for unknown or unused. * Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_CParamMode_e`. */ -static ZSTD_CParams ZSTD_getCParams_internal( +static ZSTD_compressionParameters ZSTD_getCParams_internal( int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, @@ -7947,22 +7865,22 @@ static ZSTD_CParams ZSTD_getCParams_internal( } /*! ZSTD_getCParams() : - * @return ZSTD_CParams structure for a selected compression level, srcSize and dictSize. + * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * Size values are optional, provide 0 if not known or unused */ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getPublicCParamsFromCParams(ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown)); + return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); } /*! ZSTD_getParams_internal() : * same idea as ZSTD_getCParams() - * @return a `ZSTD_Params` structure (instead of `ZSTD_CParams`). + * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). * Fields of `ZSTD_frameParameters` are set to default values */ -static ZSTD_Params +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) { - ZSTD_Params params; + ZSTD_parameters params; DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); ZSTD_memset(¶ms, 0, sizeof(params)); params.cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); @@ -7977,7 +7895,7 @@ ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, si ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getPublicParamsFromParams(ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown)); + return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); } void ZSTD_registerSequenceProducer( diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index cdd7ca749d9..f713601f5c7 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -191,28 +191,6 @@ size_t ZSTD_buildBlockEntropyStats( * Compression internals structs * *********************************/ -/** - * Internal equivalent of public ZSTD_compressionParameters struct. - */ -typedef struct { - unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression, see also `windowFrac` in CCtxParams */ - unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ - unsigned hashLog; /**< dispatch table : larger == faster, more memory */ - unsigned searchLog; /**< nb of searches : larger == more compression, slower */ - unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */ - unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ - ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ -} ZSTD_CParams; - -/** - * Internal equivalent of public ZSTD_Params struct, wrapping the internal - * ZSTD_CParams struct rather than the public ZSTD_compressionParameters. - */ -typedef struct { - ZSTD_CParams cParams; - ZSTD_frameParameters fParams; -} ZSTD_Params; - typedef struct { U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */ U32 len; /* Raw length of match */ @@ -386,7 +364,7 @@ typedef struct { struct ZSTD_CCtx_params_s { ZSTD_format_e format; - ZSTD_CParams cParams; + ZSTD_compressionParameters cParams; unsigned windowFrac; /* Additional CParam controlling sub-power-of-two window sizing. */ ZSTD_frameParameters fParams; @@ -1654,32 +1632,12 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs); * These prototypes shall only be called from within lib/compress * ============================================================== */ -/* ZSTD_getCParamsFromPublicCParams(), ZSTD_getPublicCParamsFromCParams() : - * Translates between the public and internal structs. - * - * Note: as these structs diverge, this may increasingly become a lossy - * translation. The only long-term justified use of these should be at the - * User API. - */ -ZSTD_CParams ZSTD_getCParamsFromPublicCParams(ZSTD_compressionParameters cParams); -ZSTD_compressionParameters ZSTD_getPublicCParamsFromCParams(ZSTD_CParams cParams); - -/* ZSTD_getParamsFromPublicParams(), ZSTD_getPublicParamsFromParams() : - * Translates between the public and internal structs. - * - * Note: as these structs diverge, this may increasingly become a lossy - * translation. The only long-term justified use of these should be at the - * User API. - */ -ZSTD_Params ZSTD_getParamsFromPublicParams(ZSTD_parameters params); -ZSTD_parameters ZSTD_getPublicParamsFromParams(ZSTD_Params params); - /* ZSTD_getCParamsFromCCtxParams() : * cParams are built depending on compressionLevel, src size hints, * LDM and manually set compression parameters. * Note: srcSizeHint == 0 means 0! */ -ZSTD_CParams ZSTD_getCParamsFromCCtxParams( +ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); /*! ZSTD_initCStream_internal() : @@ -1696,26 +1654,13 @@ void ZSTD_resetSeqStore(SeqStore_t* ssPtr); /*! ZSTD_getCParamsFromCDict() : * as the name implies */ -ZSTD_CParams ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict); - -/*! ZSTD_checkCParams_internal() : - * Only used for cparams coming from the user. Checks are limited compared to - * checking the whole CCtxParams via the below. */ -size_t ZSTD_checkCParams_internal(const ZSTD_CParams* cParams); +ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict); /*! ZSTD_checkCCtxCParams_internal() : * Checks the CParams in the CCtxParams (including related parameters not * *actually* stored in the CParams struct). */ size_t ZSTD_checkCCtxCParams_internal(const ZSTD_CCtx_params* params); -/* ZSTD_createCDict_internal() : - * Private use only. To be called from zstdmt_compress.c. */ -ZSTD_CDict* ZSTD_createCDict_internal(const void* dictBuffer, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_CParams cParams, - ZSTD_customMem customMem); - /* ZSTD_compressBegin_advanced_internal() : * Private use only. To be called from zstdmt_compress.c. */ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index dc76eda9dbc..51b55afaf82 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -18,7 +18,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_fillDoubleHashTableForCDict(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashLarge = ms->hashTable; U32 const hBitsL = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; U32 const mls = cParams->minMatch; @@ -56,7 +56,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_fillDoubleHashTableForCCtx(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashLarge = ms->hashTable; U32 const hBitsL = cParams->hashLog; U32 const mls = cParams->minMatch; @@ -106,7 +106,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashLong = ms->hashTable; const U32 hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; @@ -330,7 +330,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( void const* src, size_t srcSize, U32 const mls /* template */) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashLong = ms->hashTable; const U32 hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; @@ -348,7 +348,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( U32 offset_1=rep[0], offset_2=rep[1]; const ZSTD_MatchState_t* const dms = ms->dictMatchState; - const ZSTD_CParams* const dictCParams = &dms->cctxParams->cParams; + const ZSTD_compressionParameters* const dictCParams = &dms->cctxParams->cParams; const U32* const dictHashLong = dms->hashTable; const U32* const dictHashSmall = dms->chainTable; const U32 dictStartIndex = dms->window.dictLimit; @@ -612,7 +612,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict_generic( void const* src, size_t srcSize, U32 const mls /* template */) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashLong = ms->hashTable; U32 const hBitsL = cParams->hashLog; U32* const hashSmall = ms->chainTable; diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index d2d0d093b6f..82cc40886b4 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -17,7 +17,7 @@ void ZSTD_fillHashTableForCDict(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hBits = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; U32 const mls = cParams->minMatch; @@ -54,7 +54,7 @@ void ZSTD_fillHashTableForCCtx(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hBits = cParams->hashLog; U32 const mls = cParams->minMatch; @@ -194,7 +194,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( void const* src, size_t srcSize, U32 const mls, int useCmov) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; /* min 2 */ @@ -484,7 +484,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; /* support stepSize of 0 */ @@ -501,7 +501,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( U32 offset_1=rep[0], offset_2=rep[1]; const ZSTD_MatchState_t* const dms = ms->dictMatchState; - const ZSTD_CParams* const dictCParams = &dms->cctxParams->cParams; + const ZSTD_compressionParameters* const dictCParams = &dms->cctxParams->cParams; const U32* const dictHashTable = dms->hashTable; const U32 dictStartIndex = dms->window.dictLimit; const BYTE* const dictBase = dms->window.base; @@ -710,7 +710,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; /* support stepSize of 0 */ diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 392a1bad8b9..d08afff79cf 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -30,7 +30,7 @@ void ZSTD_updateDUBT(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend, U32 mls) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; @@ -76,7 +76,7 @@ void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 nbCompares, U32 btLow, const ZSTD_dictMode_e dictMode) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const bt = ms->chainTable; U32 const btLog = cParams->chainLog - 1; U32 const btMask = (1 << btLog) - 1; @@ -171,7 +171,7 @@ size_t ZSTD_DUBT_findBetterDictMatch ( const ZSTD_dictMode_e dictMode) { const ZSTD_MatchState_t * const dms = ms->dictMatchState; - const ZSTD_CParams* const dmsCParams = &dms->cctxParams->cParams; + const ZSTD_compressionParameters* const dmsCParams = &dms->cctxParams->cParams; const U32 * const dictHashTable = dms->hashTable; U32 const hashLog = dmsCParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -246,7 +246,7 @@ size_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms, U32 const mls, const ZSTD_dictMode_e dictMode) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -410,7 +410,7 @@ size_t ZSTD_BtFindBestMatch( ZSTD_MatchState_t* ms, void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; const BYTE* const base = ms->window.base; U32 const target = (U32)(ip - base); U32* const hashTable = ms->hashTable; @@ -632,7 +632,7 @@ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR U32 ZSTD_insertAndFindFirstIndex_internal( ZSTD_MatchState_t* ms, - const ZSTD_CParams* const cParams, + const ZSTD_compressionParameters* const cParams, const BYTE* ip, U32 const mls, U32 const lazySkipping) { U32* const hashTable = ms->hashTable; @@ -658,7 +658,7 @@ U32 ZSTD_insertAndFindFirstIndex_internal( } U32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, cParams->minMatch, /* lazySkipping*/ 0); } @@ -671,7 +671,7 @@ size_t ZSTD_HcFindBestMatch( size_t* offsetPtr, const U32 mls, const ZSTD_dictMode_e dictMode) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const chainTable = ms->chainTable; const U32 chainSize = (1 << cParams->chainLog); const U32 chainMask = chainSize-1; @@ -1150,7 +1150,7 @@ size_t ZSTD_RowFindBestMatch( BYTE* const tagTable = ms->tagTable; U32* const hashCache = ms->hashCache; const U32 hashLog = ms->rowHashLog; - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; const BYTE* const base = ms->window.base; const BYTE* const dictBase = ms->window.dictBase; const U32 dictLimit = ms->window.dictLimit; diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index dedb81e86fb..ad9aadb5c7c 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -684,7 +684,7 @@ size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore, ZSTD_ParamSwitch_e useRowMatchFinder, void const* src, size_t srcSize) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; unsigned const minMatch = cParams->minMatch; ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms)); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index a02373ba18f..8485accfb5e 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -445,7 +445,7 @@ U32 ZSTD_insertBt1( U32 const target, U32 const mls, const int extDict) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32* const hashTable = ms->hashTable; U32 const hashLog = cParams->hashLog; size_t const h = ZSTD_hashPtr(ip, hashLog, mls); @@ -598,7 +598,7 @@ ZSTD_insertBtAndGetAllMatches ( const U32 lengthToBeat, const U32 mls /* template */) { - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); const BYTE* const base = ms->window.base; U32 const curr = (U32)(ip-base); @@ -626,7 +626,7 @@ ZSTD_insertBtAndGetAllMatches ( U32 nbCompares = 1U << cParams->searchLog; const ZSTD_MatchState_t* dms = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL; - const ZSTD_CParams* const dmsCParams = + const ZSTD_compressionParameters* const dmsCParams = dictMode == ZSTD_dictMatchState ? &dms->cctxParams->cParams : NULL; const BYTE* const dmsBase = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL; const BYTE* const dmsEnd = dictMode == ZSTD_dictMatchState ? dms->window.nextSrc : NULL; @@ -1089,7 +1089,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, const BYTE* const ilimit = iend - 8; const BYTE* const base = ms->window.base; const BYTE* const prefixStart = base + ms->window.dictLimit; - const ZSTD_CParams* const cParams = &ms->cctxParams->cParams; + const ZSTD_compressionParameters* const cParams = &ms->cctxParams->cParams; ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode); diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index f7f3fce5283..bf527c92f7d 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1100,7 +1100,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; - { ZSTD_CParams cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); cParams.windowLog = saved_wlog; mtctx->params.cParams = cParams; } @@ -1276,7 +1276,7 @@ size_t ZSTDMT_initCStream_internal( mtctx->frameContentSize = pledgedSrcSize; ZSTD_freeCDict(mtctx->cdictLocal); if (dict) { - mtctx->cdictLocal = ZSTD_createCDict_internal( + mtctx->cdictLocal = ZSTD_createCDict_advanced( dict, dictSize, ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */ params.cParams, mtctx->cMem); @@ -1359,9 +1359,10 @@ size_t ZSTDMT_initCStream_internal( mtctx->inBuff.prefix.size = dictSize; } else { /* note : a loadPrefix becomes an internal CDict */ - mtctx->cdictLocal = ZSTD_createCDict_internal(dict, dictSize, - ZSTD_dlm_byRef, dictContentType, - params.cParams, mtctx->cMem); + mtctx->cdictLocal = ZSTD_createCDict_advanced( + dict, dictSize, + ZSTD_dlm_byRef, dictContentType, + params.cParams, mtctx->cMem); mtctx->cdict = mtctx->cdictLocal; if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); } From cbbf3b21f2eae9eac4d64e7e846ae75643f12f6a Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 24 Feb 2025 13:14:59 -0800 Subject: [PATCH 33/36] Further Transport CCtxParams Rather than CParams in Various Param Resolution Components --- lib/compress/zstd_compress.c | 190 ++++++++++++++++---------- lib/compress/zstd_compress_internal.h | 6 +- lib/compress/zstdmt_compress.c | 13 +- 3 files changed, 131 insertions(+), 78 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 77d7960702f..d45cd1242b9 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1258,7 +1258,7 @@ size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSr return 0; } -static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams( +static ZSTD_CCtx_params ZSTD_dedicatedDictSearch_getCParams( int const compressionLevel, size_t const dictSize); static int ZSTD_dedicatedDictSearch_isSupported( @@ -1682,43 +1682,62 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, return params.cParams; } -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); +static ZSTD_CCtx_params ZSTD_getCCtxParams_internal( + int compressionLevel, + unsigned long long srcSizeHint, + size_t dictSize, + ZSTD_CParamMode_e mode); -static void ZSTD_overrideCParams( - ZSTD_compressionParameters* cParams, - const ZSTD_compressionParameters* overrides) -{ - if (overrides->windowLog) cParams->windowLog = overrides->windowLog; - if (overrides->hashLog) cParams->hashLog = overrides->hashLog; - if (overrides->chainLog) cParams->chainLog = overrides->chainLog; - if (overrides->searchLog) cParams->searchLog = overrides->searchLog; - if (overrides->minMatch) cParams->minMatch = overrides->minMatch; - if (overrides->targetLength) cParams->targetLength = overrides->targetLength; - if (overrides->strategy) cParams->strategy = overrides->strategy; +/* Prefer ZSTD_getCCtxParams_internal() unless you're sure you *only* need + * the CParams actually stored in the ZSTD_compressionParameters struct. + * (i.e., not the window size!) */ +static ZSTD_compressionParameters ZSTD_getCParams_internal( + int compressionLevel, + unsigned long long srcSizeHint, + size_t dictSize, + ZSTD_CParamMode_e mode); +static ZSTD_parameters ZSTD_getParams_internal( + int compressionLevel, + unsigned long long srcSizeHint, + size_t dictSize, ZSTD_CParamMode_e + mode); + +/* fills unset fields in `dst` with values from `defaults` */ +static void ZSTD_fillCParams( + ZSTD_CCtx_params* dst, + const ZSTD_CCtx_params* defaults) { + if (!dst->cParams.windowLog) { + dst->cParams.windowLog = defaults->cParams.windowLog; + /* windowFrac only has effect if windowLog is explicitly set */ + dst->windowFrac = defaults->windowFrac; + } + if (!dst->cParams.hashLog) dst->cParams.hashLog = defaults->cParams.hashLog; + if (!dst->cParams.chainLog) dst->cParams.chainLog = defaults->cParams.chainLog; + if (!dst->cParams.searchLog) dst->cParams.searchLog = defaults->cParams.searchLog; + if (!dst->cParams.minMatch) dst->cParams.minMatch = defaults->cParams.minMatch; + if (!dst->cParams.targetLength) dst->cParams.targetLength = defaults->cParams.targetLength; + if (!dst->cParams.strategy) dst->cParams.strategy = defaults->cParams.strategy; } -ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* cctxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) +void ZSTD_fillCParamsInCCtxParams( + ZSTD_CCtx_params* params, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode) { - ZSTD_CCtx_params params = *cctxParams; - if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && params.srcSizeHint > 0) { - assert(params.srcSizeHint>=0); - srcSizeHint = (U64)params.srcSizeHint; + if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && params->srcSizeHint > 0) { + assert(params->srcSizeHint>=0); + srcSizeHint = (U64)params->srcSizeHint; } { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(params.compressionLevel, srcSizeHint, dictSize, mode); - if (params.ldmParams.enableLdm == ZSTD_ps_enable) { - cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; + ZSTD_CCtx_params tmpParams = ZSTD_getCCtxParams_internal(params->compressionLevel, srcSizeHint, dictSize, mode); + if (params->ldmParams.enableLdm == ZSTD_ps_enable) { + tmpParams.cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; + tmpParams.windowFrac = 0; } - ZSTD_overrideCParams(&cParams, ¶ms.cParams); - params.cParams = cParams; - assert(!ZSTD_checkCCtxCParams_internal(¶ms)); + ZSTD_fillCParams(params, &tmpParams); + assert(!ZSTD_checkCCtxCParams_internal(params)); } /* srcSizeHint == 0 means 0 */ - ZSTD_adjustCParams_internal(¶ms, srcSizeHint, dictSize, mode, params.useRowMatchFinder); - return params.cParams; + ZSTD_adjustCParams_internal(params, srcSizeHint, dictSize, mode, params->useRowMatchFinder); } static size_t @@ -1822,7 +1841,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) { ZSTD_CCtx_params par = *params; - par.cParams = ZSTD_getCParamsFromCCtxParams(&par, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + ZSTD_fillCParamsInCCtxParams(&par, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); par.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(par.useRowMatchFinder, &par.cParams); RETURN_ERROR_IF(par.nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); @@ -1833,10 +1852,10 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) &par, 1, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN); } -size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) +static size_t ZSTD_estimateCCtxSize_usingCCtxParamsCParams(const ZSTD_CCtx_params* params) { - ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); - if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { + ZSTD_CCtx_params initialParams = *params; + if (ZSTD_rowMatchFinderSupported(initialParams.cParams.strategy)) { /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */ size_t noRowCCtxSize; size_t rowCCtxSize; @@ -1850,6 +1869,12 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) } } +size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) +{ + ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); + return ZSTD_estimateCCtxSize_usingCCtxParamsCParams(&initialParams); +} + static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) { int tier = 0; @@ -1857,8 +1882,8 @@ static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN}; for (; tier < 4; ++tier) { /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */ - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); - largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize); + ZSTD_CCtx_params const params = ZSTD_getCCtxParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); + largestSize = MAX(ZSTD_estimateCCtxSize_usingCCtxParamsCParams(¶ms), largestSize); } return largestSize; } @@ -1879,7 +1904,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) { ZSTD_CCtx_params par = *params; RETURN_ERROR_IF(par.nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); - par.cParams = ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + ZSTD_fillCParamsInCCtxParams(&par, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); { size_t const windowSize = ZSTD_windowSize(&par); size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), windowSize); @@ -1897,10 +1922,10 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) } } -size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) +static size_t ZSTD_estimateCStreamSize_usingCCtxParamsCParams(const ZSTD_CCtx_params* params) { - ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); - if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { + ZSTD_CCtx_params initialParams = *params; + if (ZSTD_rowMatchFinderSupported(initialParams.cParams.strategy)) { /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */ size_t noRowCCtxSize; size_t rowCCtxSize; @@ -1914,10 +1939,16 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) } } +size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) +{ + ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); + return ZSTD_estimateCStreamSize_usingCCtxParamsCParams(&initialParams); +} + static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); - return ZSTD_estimateCStreamSize_usingCParams(cParams); + ZSTD_CCtx_params params = ZSTD_getCCtxParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + return ZSTD_estimateCStreamSize_usingCCtxParamsCParams(¶ms); } size_t ZSTD_estimateCStreamSize(int compressionLevel) @@ -2593,6 +2624,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, { ZSTD_CCtx_params params = dstCCtx->requestedParams; /* Copy only compression parameters related to tables. */ params.cParams = srcCCtx->appliedParams.cParams; + params.windowFrac = srcCCtx->appliedParams.windowFrac; assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_ps_auto); assert(srcCCtx->appliedParams.postBlockSplitter != ZSTD_ps_auto); assert(srcCCtx->appliedParams.ldmParams.enableLdm != ZSTD_ps_auto); @@ -5604,8 +5636,8 @@ size_t ZSTD_estimateCDictSize_advanced( size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); + ZSTD_CCtx_params const params = ZSTD_getCCtxParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + return ZSTD_estimateCDictSize_advanced(dictSize, params.cParams, ZSTD_dlm_byCopy); } size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) @@ -5734,31 +5766,30 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_customMem customMem) { ZSTD_CCtx_params cctxParams = *originalCctxParams; - ZSTD_compressionParameters cParams; ZSTD_CDict* cdict; DEBUGLOG(3, "ZSTD_createCDict_advanced2, dictSize=%u, mode=%u", (unsigned)dictSize, (unsigned)dictContentType); if (!customMem.customAlloc ^ !customMem.customFree) return NULL; if (cctxParams.enableDedicatedDictSearch) { - cParams = ZSTD_dedicatedDictSearch_getCParams( + ZSTD_CCtx_params tmpParams = ZSTD_dedicatedDictSearch_getCParams( cctxParams.compressionLevel, dictSize); - ZSTD_overrideCParams(&cParams, &cctxParams.cParams); + ZSTD_fillCParams(&cctxParams, &tmpParams); } else { - cParams = ZSTD_getCParamsFromCCtxParams( + ZSTD_fillCParamsInCCtxParams( &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); } - if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) { + if (!ZSTD_dedicatedDictSearch_isSupported(&cctxParams.cParams)) { /* Fall back to non-DDSS params */ + cctxParams = *originalCctxParams; cctxParams.enableDedicatedDictSearch = 0; - cParams = ZSTD_getCParamsFromCCtxParams( + ZSTD_fillCParamsInCCtxParams( &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); } DEBUGLOG(3, "ZSTD_createCDict_advanced2: DedicatedDictSearch=%u", cctxParams.enableDedicatedDictSearch); - cctxParams.cParams = cParams; - cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams); + cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cctxParams.cParams); cdict = ZSTD_createCDict_advanced_internal(dictSize, dictLoadMethod, cctxParams.cParams, @@ -5778,11 +5809,11 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( + ZSTD_CCtx_params params = ZSTD_getCCtxParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced2( dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, - cParams, ZSTD_defaultCMem); + ¶ms, ZSTD_defaultCMem); if (cdict) cdict->params.compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; @@ -5790,11 +5821,11 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); - ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( + ZSTD_CCtx_params params = ZSTD_getCCtxParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced2( dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, - cParams, ZSTD_defaultCMem); + ¶ms, ZSTD_defaultCMem); if (cdict) cdict->params.compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; @@ -5906,14 +5937,18 @@ static size_t ZSTD_compressBegin_usingCDict_internal( || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN || cdict->params.compressionLevel == 0 ) { params.cParams = ZSTD_getCParamsFromCDict(cdict); + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->params.compressionLevel); } else { - params.cParams = ZSTD_getCParams_internal( + /* I'm pretty sure this incorrectly discards the windowFrac... */ + ZSTD_CCtx_params const tmpParams = ZSTD_getCCtxParams_internal( cdict->params.compressionLevel, pledgedSrcSize, cdict->dictContentSize, ZSTD_cpm_unknown); + params.cParams = tmpParams.cParams; + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->params.compressionLevel); + cctxParams.windowFrac = tmpParams.windowFrac; } - ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->params.compressionLevel); } /* Increase window log to fit the entire dictionary and source if the * source size is known. Limit the increase to 19, which is the @@ -6440,11 +6475,12 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, DEBUGLOG(4, "ZSTD_CCtx_init_compressStream2 : transparent init stage"); if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-determine pledgedSrcSize */ - { size_t const dictSize = prefixDict.dict + { + size_t const dictSize = prefixDict.dict ? prefixDict.dictSize : (cctx->cdict ? cctx->cdict->dictContentSize : 0); ZSTD_CParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1); - params.cParams = ZSTD_getCParamsFromCCtxParams( + ZSTD_fillCParamsInCCtxParams( ¶ms, cctx->pledgedSrcSizePlusOne-1, dictSize, mode); } @@ -7750,17 +7786,17 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; } -static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) +static ZSTD_CCtx_params ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); - switch (cParams.strategy) { + ZSTD_CCtx_params params = ZSTD_getCCtxParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); + switch (params.cParams.strategy) { case ZSTD_fast: case ZSTD_dfast: break; case ZSTD_greedy: case ZSTD_lazy: case ZSTD_lazy2: - cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG; + params.cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG; break; case ZSTD_btlazy2: case ZSTD_btopt: @@ -7768,7 +7804,7 @@ static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const case ZSTD_btultra2: break; } - return cParams; + return params; } static int ZSTD_dedicatedDictSearch_isSupported( @@ -7827,12 +7863,14 @@ static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_CParamMo } } -/*! ZSTD_getCParams_internal() : - * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. +/*! ZSTD_getCCtxParams_internal() : + * @return a ZSTD_CCtx_params with the ZSTD_compressionParameters structure + * (and select other fields) populated for the selected compression level, + * srcSize and dictSize. * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. * Use dictSize == 0 for unknown or unused. * Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_CParamMode_e`. */ -static ZSTD_compressionParameters ZSTD_getCParams_internal( +static ZSTD_CCtx_params ZSTD_getCCtxParams_internal( int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, @@ -7841,7 +7879,7 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal( U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode); U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); int row; - DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel); + DEBUGLOG(5, "ZSTD_getCCtxParams_internal (cLevel=%i)", compressionLevel); /* row */ if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ @@ -7852,7 +7890,7 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal( { ZSTD_CCtx_params params; ZSTD_CCtxParams_init(¶ms, compressionLevel); params.cParams = ZSTD_defaultCParameters[tableID][row]; - DEBUGLOG(5, "ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)params.cParams.strategy); + DEBUGLOG(5, "ZSTD_getCCtxParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)params.cParams.strategy); /* acceleration factor */ if (compressionLevel < 0) { int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel); @@ -7860,10 +7898,20 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal( } /* refine parameters based on srcSize & dictSize */ ZSTD_adjustCParams_internal(¶ms, srcSizeHint, dictSize, mode, ZSTD_ps_auto); - return params.cParams; + return params; } } +static ZSTD_compressionParameters ZSTD_getCParams_internal( + int compressionLevel, + unsigned long long srcSizeHint, + size_t dictSize, + ZSTD_CParamMode_e mode) +{ + ZSTD_CCtx_params const params = ZSTD_getCCtxParams_internal(compressionLevel, srcSizeHint, dictSize, mode); + return params.cParams; +} + /*! ZSTD_getCParams() : * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * Size values are optional, provide 0 if not known or unused */ diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index f713601f5c7..6c1c81fd108 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1632,13 +1632,13 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs); * These prototypes shall only be called from within lib/compress * ============================================================== */ -/* ZSTD_getCParamsFromCCtxParams() : +/* ZSTD_fillCParamsInCCtxParams() : * cParams are built depending on compressionLevel, src size hints, * LDM and manually set compression parameters. * Note: srcSizeHint == 0 means 0! */ -ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); +void ZSTD_fillCParamsInCCtxParams( + ZSTD_CCtx_params* cctxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode); /*! ZSTD_initCStream_internal() : * Private use only. Init streaming operation. diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index bf527c92f7d..19b26c02e73 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1095,14 +1095,19 @@ static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers) * New parameters will be applied to next compression job. */ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams) { - U32 const saved_wlog = mtctx->params.cParams.windowLog; /* Do not modify windowLog while compressing */ + U32 const saved_wlog = mtctx->params.cParams.windowLog; /* Do not modify windowLog while compressing */ + U32 const saved_wfrac = mtctx->params.windowFrac; /* Do not modify windowFrac while compressing */ int const compressionLevel = cctxParams->compressionLevel; DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; - { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); - cParams.windowLog = saved_wlog; - mtctx->params.cParams = cParams; + { + ZSTD_CCtx_params params = *cctxParams; + ZSTD_fillCParamsInCCtxParams(¶ms, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + params.cParams.windowLog = saved_wlog; + params.windowFrac = saved_wfrac; + mtctx->params.cParams = params.cParams; + mtctx->params.windowFrac = params.windowFrac; } } From af60a976ddd2229bbb8be646295a0122b009ccff Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 24 Feb 2025 14:47:29 -0800 Subject: [PATCH 34/36] Init CCtxParams from (CParam-like) CCtxParams in Entry-Points --- lib/compress/zstd_compress.c | 62 ++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d45cd1242b9..3a140e6e318 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -365,33 +365,46 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) #define ZSTD_NO_CLEVEL 0 -/** - * Initializes `cctxParams` from `params` and `compressionLevel`. - * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL. - */ -static void -ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, - const ZSTD_parameters* params, - int compressionLevel) +static void ZSTD_CCtxParams_init_fromCCtxParams( + ZSTD_CCtx_params* cctxParams, + const ZSTD_CCtx_params* srcParams) { - assert(!ZSTD_checkCParams(params->cParams)); + assert(!ZSTD_checkCCtxCParams_internal(srcParams)); ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); - cctxParams->cParams = params->cParams; - cctxParams->fParams = params->fParams; + cctxParams->cParams = srcParams->cParams; + cctxParams->windowFrac = srcParams->windowFrac; + cctxParams->fParams = srcParams->fParams; /* Should not matter, as all cParams are presumed properly defined. * But, set it for tracing anyway. */ - cctxParams->compressionLevel = compressionLevel; + cctxParams->compressionLevel = srcParams->compressionLevel; cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, &cctxParams->cParams); cctxParams->postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->postBlockSplitter, &cctxParams->cParams); cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, &cctxParams->cParams); cctxParams->validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams->validateSequences); cctxParams->maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams->maxBlockSize); - cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, compressionLevel); + cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, cctxParams->compressionLevel); DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d, useBlockSplitter=%d ldm=%d", cctxParams->useRowMatchFinder, cctxParams->postBlockSplitter, cctxParams->ldmParams.enableLdm); } +/** + * Initializes `cctxParams` from `params` and `compressionLevel`. + * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL. + */ +static void +ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, + const ZSTD_parameters* params, + int compressionLevel) +{ + ZSTD_CCtx_params tmpParams; + ZSTD_memset(&tmpParams, 0, sizeof(tmpParams)); + tmpParams.cParams = params->cParams; + tmpParams.fParams = params->fParams; + tmpParams.compressionLevel = compressionLevel; + return ZSTD_CCtxParams_init_fromCCtxParams(cctxParams, &tmpParams); +} + size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) { RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); @@ -5419,8 +5432,8 @@ static size_t ZSTD_compressBegin_usingDict_deprecated(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { ZSTD_CCtx_params cctxParams; - { ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); - ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel); + { ZSTD_CCtx_params const tmpParams = ZSTD_getCCtxParams_internal((compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); + ZSTD_CCtxParams_init_fromCCtxParams(&cctxParams, &tmpParams); } DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, @@ -5577,9 +5590,9 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, int compressionLevel) { { - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); - assert(params.fParams.contentSizeFlag == 1); - ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel); + ZSTD_CCtx_params const tmpParams = ZSTD_getCCtxParams_internal((compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); + assert(tmpParams.fParams.contentSizeFlag == 1); + ZSTD_CCtxParams_init_fromCCtxParams(&cctx->simpleApiParams, &tmpParams); } DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize); return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctx->simpleApiParams); @@ -5930,24 +5943,19 @@ static size_t ZSTD_compressBegin_usingCDict_internal( RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!"); /* Initialize the cctxParams from the cdict */ { - ZSTD_parameters params; - params.fParams = fParams; if ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN || cdict->params.compressionLevel == 0 ) { - params.cParams = ZSTD_getCParamsFromCDict(cdict); - ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->params.compressionLevel); + ZSTD_CCtxParams_init_fromCCtxParams(&cctxParams, &cdict->params); } else { - /* I'm pretty sure this incorrectly discards the windowFrac... */ - ZSTD_CCtx_params const tmpParams = ZSTD_getCCtxParams_internal( + ZSTD_CCtx_params tmpParams = ZSTD_getCCtxParams_internal( cdict->params.compressionLevel, pledgedSrcSize, cdict->dictContentSize, ZSTD_cpm_unknown); - params.cParams = tmpParams.cParams; - ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->params.compressionLevel); - cctxParams.windowFrac = tmpParams.windowFrac; + tmpParams.fParams = fParams; + ZSTD_CCtxParams_init_fromCCtxParams(&cctxParams, &tmpParams); } } /* Increase window log to fit the entire dictionary and source if the From 67a2b3c791c50e100b168ad7626a5459f892cc25 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 24 Feb 2025 14:56:19 -0800 Subject: [PATCH 35/36] Fix Transporting FParams in `ZSTD_compressBegin_usingCDict_internal()` --- 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 3a140e6e318..d6bc9963a7c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -5954,9 +5954,9 @@ static size_t ZSTD_compressBegin_usingCDict_internal( pledgedSrcSize, cdict->dictContentSize, ZSTD_cpm_unknown); - tmpParams.fParams = fParams; ZSTD_CCtxParams_init_fromCCtxParams(&cctxParams, &tmpParams); } + cctxParams.fParams = fParams; } /* Increase window log to fit the entire dictionary and source if the * source size is known. Limit the increase to 19, which is the From b5fabd74f56b6b6fb142fe523b9572213b3d7627 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 24 Feb 2025 15:07:32 -0800 Subject: [PATCH 36/36] Fix Build --- 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 d6bc9963a7c..51483bc5791 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -402,7 +402,7 @@ ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, tmpParams.cParams = params->cParams; tmpParams.fParams = params->fParams; tmpParams.compressionLevel = compressionLevel; - return ZSTD_CCtxParams_init_fromCCtxParams(cctxParams, &tmpParams); + ZSTD_CCtxParams_init_fromCCtxParams(cctxParams, &tmpParams); } size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)