0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */
0015 #include "../common/cpu.h"
0016 #include "../common/mem.h"
0017 #include "hist.h" /* HIST_countFast_wksp */
0018 #define FSE_STATIC_LINKING_ONLY
0019 #include "../common/fse.h"
0020 #define HUF_STATIC_LINKING_ONLY
0021 #include "../common/huf.h"
0022 #include "zstd_compress_internal.h"
0023 #include "zstd_compress_sequences.h"
0024 #include "zstd_compress_literals.h"
0025 #include "zstd_fast.h"
0026 #include "zstd_double_fast.h"
0027 #include "zstd_lazy.h"
0028 #include "zstd_opt.h"
0029 #include "zstd_ldm.h"
0030 #include "zstd_compress_superblock.h"
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 size_t ZSTD_compressBound(size_t srcSize) {
0054 return ZSTD_COMPRESSBOUND(srcSize);
0055 }
0056
0057
0058
0059
0060
0061 struct ZSTD_CDict_s {
0062 const void* dictContent;
0063 size_t dictContentSize;
0064 ZSTD_dictContentType_e dictContentType;
0065 U32* entropyWorkspace;
0066 ZSTD_cwksp workspace;
0067 ZSTD_matchState_t matchState;
0068 ZSTD_compressedBlockState_t cBlockState;
0069 ZSTD_customMem customMem;
0070 U32 dictID;
0071 int compressionLevel;
0072 };
0073
0074 ZSTD_CCtx* ZSTD_createCCtx(void)
0075 {
0076 return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
0077 }
0078
0079 static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
0080 {
0081 assert(cctx != NULL);
0082 ZSTD_memset(cctx, 0, sizeof(*cctx));
0083 cctx->customMem = memManager;
0084 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
0085 { size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
0086 assert(!ZSTD_isError(err));
0087 (void)err;
0088 }
0089 }
0090
0091 ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
0092 {
0093 ZSTD_STATIC_ASSERT(zcss_init==0);
0094 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
0095 if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
0096 { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem);
0097 if (!cctx) return NULL;
0098 ZSTD_initCCtx(cctx, customMem);
0099 return cctx;
0100 }
0101 }
0102
0103 ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
0104 {
0105 ZSTD_cwksp ws;
0106 ZSTD_CCtx* cctx;
0107 if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL;
0108 if ((size_t)workspace & 7) return NULL;
0109 ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
0110
0111 cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));
0112 if (cctx == NULL) return NULL;
0113
0114 ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx));
0115 ZSTD_cwksp_move(&cctx->workspace, &ws);
0116 cctx->staticSize = workspaceSize;
0117
0118
0119 if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;
0120 cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
0121 cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
0122 cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE);
0123 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
0124 return cctx;
0125 }
0126
0127
0128
0129
0130 static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
0131 {
0132 ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem);
0133 ZSTD_freeCDict(cctx->localDict.cdict);
0134 ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict));
0135 ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
0136 cctx->cdict = NULL;
0137 }
0138
0139 static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
0140 {
0141 size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
0142 size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
0143 return bufferSize + cdictSize;
0144 }
0145
0146 static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
0147 {
0148 assert(cctx != NULL);
0149 assert(cctx->staticSize == 0);
0150 ZSTD_clearAllDicts(cctx);
0151 ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);
0152 }
0153
0154 size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
0155 {
0156 if (cctx==NULL) return 0;
0157 RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
0158 "not compatible with static CCtx");
0159 {
0160 int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);
0161 ZSTD_freeCCtxContent(cctx);
0162 if (!cctxInWorkspace) {
0163 ZSTD_customFree(cctx, cctx->customMem);
0164 }
0165 }
0166 return 0;
0167 }
0168
0169
0170 static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
0171 {
0172 (void)cctx;
0173 return 0;
0174 }
0175
0176
0177 size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
0178 {
0179 if (cctx==NULL) return 0;
0180
0181 return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))
0182 + ZSTD_cwksp_sizeof(&cctx->workspace)
0183 + ZSTD_sizeof_localDict(cctx->localDict)
0184 + ZSTD_sizeof_mtctx(cctx);
0185 }
0186
0187 size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
0188 {
0189 return ZSTD_sizeof_CCtx(zcs);
0190 }
0191
0192
0193 const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
0194
0195
0196
0197
0198
0199 static U32 ZSTD_CParams_shouldEnableLdm(const ZSTD_compressionParameters* const cParams) {
0200 return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27;
0201 }
0202
0203 static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
0204 ZSTD_compressionParameters cParams)
0205 {
0206 ZSTD_CCtx_params cctxParams;
0207
0208 ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT);
0209 cctxParams.cParams = cParams;
0210
0211 if (ZSTD_CParams_shouldEnableLdm(&cParams)) {
0212 DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including LDM into cctx params");
0213 cctxParams.ldmParams.enableLdm = 1;
0214
0215 ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams);
0216 assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog);
0217 assert(cctxParams.ldmParams.hashRateLog < 32);
0218 }
0219
0220 assert(!ZSTD_checkCParams(cParams));
0221 return cctxParams;
0222 }
0223
0224 static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
0225 ZSTD_customMem customMem)
0226 {
0227 ZSTD_CCtx_params* params;
0228 if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
0229 params = (ZSTD_CCtx_params*)ZSTD_customCalloc(
0230 sizeof(ZSTD_CCtx_params), customMem);
0231 if (!params) { return NULL; }
0232 ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
0233 params->customMem = customMem;
0234 return params;
0235 }
0236
0237 ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
0238 {
0239 return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);
0240 }
0241
0242 size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
0243 {
0244 if (params == NULL) { return 0; }
0245 ZSTD_customFree(params, params->customMem);
0246 return 0;
0247 }
0248
0249 size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
0250 {
0251 return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
0252 }
0253
0254 size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
0255 RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
0256 ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
0257 cctxParams->compressionLevel = compressionLevel;
0258 cctxParams->fParams.contentSizeFlag = 1;
0259 return 0;
0260 }
0261
0262 #define ZSTD_NO_CLEVEL 0
0263
0264
0265
0266
0267
0268 static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_parameters const* params, int compressionLevel)
0269 {
0270 assert(!ZSTD_checkCParams(params->cParams));
0271 ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
0272 cctxParams->cParams = params->cParams;
0273 cctxParams->fParams = params->fParams;
0274
0275
0276
0277 cctxParams->compressionLevel = compressionLevel;
0278 }
0279
0280 size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
0281 {
0282 RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
0283 FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
0284 ZSTD_CCtxParams_init_internal(cctxParams, ¶ms, ZSTD_NO_CLEVEL);
0285 return 0;
0286 }
0287
0288
0289
0290
0291
0292 static void ZSTD_CCtxParams_setZstdParams(
0293 ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
0294 {
0295 assert(!ZSTD_checkCParams(params->cParams));
0296 cctxParams->cParams = params->cParams;
0297 cctxParams->fParams = params->fParams;
0298
0299
0300
0301 cctxParams->compressionLevel = ZSTD_NO_CLEVEL;
0302 }
0303
0304 ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
0305 {
0306 ZSTD_bounds bounds = { 0, 0, 0 };
0307
0308 switch(param)
0309 {
0310 case ZSTD_c_compressionLevel:
0311 bounds.lowerBound = ZSTD_minCLevel();
0312 bounds.upperBound = ZSTD_maxCLevel();
0313 return bounds;
0314
0315 case ZSTD_c_windowLog:
0316 bounds.lowerBound = ZSTD_WINDOWLOG_MIN;
0317 bounds.upperBound = ZSTD_WINDOWLOG_MAX;
0318 return bounds;
0319
0320 case ZSTD_c_hashLog:
0321 bounds.lowerBound = ZSTD_HASHLOG_MIN;
0322 bounds.upperBound = ZSTD_HASHLOG_MAX;
0323 return bounds;
0324
0325 case ZSTD_c_chainLog:
0326 bounds.lowerBound = ZSTD_CHAINLOG_MIN;
0327 bounds.upperBound = ZSTD_CHAINLOG_MAX;
0328 return bounds;
0329
0330 case ZSTD_c_searchLog:
0331 bounds.lowerBound = ZSTD_SEARCHLOG_MIN;
0332 bounds.upperBound = ZSTD_SEARCHLOG_MAX;
0333 return bounds;
0334
0335 case ZSTD_c_minMatch:
0336 bounds.lowerBound = ZSTD_MINMATCH_MIN;
0337 bounds.upperBound = ZSTD_MINMATCH_MAX;
0338 return bounds;
0339
0340 case ZSTD_c_targetLength:
0341 bounds.lowerBound = ZSTD_TARGETLENGTH_MIN;
0342 bounds.upperBound = ZSTD_TARGETLENGTH_MAX;
0343 return bounds;
0344
0345 case ZSTD_c_strategy:
0346 bounds.lowerBound = ZSTD_STRATEGY_MIN;
0347 bounds.upperBound = ZSTD_STRATEGY_MAX;
0348 return bounds;
0349
0350 case ZSTD_c_contentSizeFlag:
0351 bounds.lowerBound = 0;
0352 bounds.upperBound = 1;
0353 return bounds;
0354
0355 case ZSTD_c_checksumFlag:
0356 bounds.lowerBound = 0;
0357 bounds.upperBound = 1;
0358 return bounds;
0359
0360 case ZSTD_c_dictIDFlag:
0361 bounds.lowerBound = 0;
0362 bounds.upperBound = 1;
0363 return bounds;
0364
0365 case ZSTD_c_nbWorkers:
0366 bounds.lowerBound = 0;
0367 bounds.upperBound = 0;
0368 return bounds;
0369
0370 case ZSTD_c_jobSize:
0371 bounds.lowerBound = 0;
0372 bounds.upperBound = 0;
0373 return bounds;
0374
0375 case ZSTD_c_overlapLog:
0376 bounds.lowerBound = 0;
0377 bounds.upperBound = 0;
0378 return bounds;
0379
0380 case ZSTD_c_enableDedicatedDictSearch:
0381 bounds.lowerBound = 0;
0382 bounds.upperBound = 1;
0383 return bounds;
0384
0385 case ZSTD_c_enableLongDistanceMatching:
0386 bounds.lowerBound = 0;
0387 bounds.upperBound = 1;
0388 return bounds;
0389
0390 case ZSTD_c_ldmHashLog:
0391 bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN;
0392 bounds.upperBound = ZSTD_LDM_HASHLOG_MAX;
0393 return bounds;
0394
0395 case ZSTD_c_ldmMinMatch:
0396 bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN;
0397 bounds.upperBound = ZSTD_LDM_MINMATCH_MAX;
0398 return bounds;
0399
0400 case ZSTD_c_ldmBucketSizeLog:
0401 bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN;
0402 bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX;
0403 return bounds;
0404
0405 case ZSTD_c_ldmHashRateLog:
0406 bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN;
0407 bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX;
0408 return bounds;
0409
0410
0411 case ZSTD_c_rsyncable:
0412 bounds.lowerBound = 0;
0413 bounds.upperBound = 1;
0414 return bounds;
0415
0416 case ZSTD_c_forceMaxWindow :
0417 bounds.lowerBound = 0;
0418 bounds.upperBound = 1;
0419 return bounds;
0420
0421 case ZSTD_c_format:
0422 ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
0423 bounds.lowerBound = ZSTD_f_zstd1;
0424 bounds.upperBound = ZSTD_f_zstd1_magicless;
0425 return bounds;
0426
0427 case ZSTD_c_forceAttachDict:
0428 ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad);
0429 bounds.lowerBound = ZSTD_dictDefaultAttach;
0430 bounds.upperBound = ZSTD_dictForceLoad;
0431 return bounds;
0432
0433 case ZSTD_c_literalCompressionMode:
0434 ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
0435 bounds.lowerBound = ZSTD_lcm_auto;
0436 bounds.upperBound = ZSTD_lcm_uncompressed;
0437 return bounds;
0438
0439 case ZSTD_c_targetCBlockSize:
0440 bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;
0441 bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;
0442 return bounds;
0443
0444 case ZSTD_c_srcSizeHint:
0445 bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN;
0446 bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;
0447 return bounds;
0448
0449 case ZSTD_c_stableInBuffer:
0450 case ZSTD_c_stableOutBuffer:
0451 bounds.lowerBound = (int)ZSTD_bm_buffered;
0452 bounds.upperBound = (int)ZSTD_bm_stable;
0453 return bounds;
0454
0455 case ZSTD_c_blockDelimiters:
0456 bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters;
0457 bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters;
0458 return bounds;
0459
0460 case ZSTD_c_validateSequences:
0461 bounds.lowerBound = 0;
0462 bounds.upperBound = 1;
0463 return bounds;
0464
0465 default:
0466 bounds.error = ERROR(parameter_unsupported);
0467 return bounds;
0468 }
0469 }
0470
0471
0472
0473
0474 static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
0475 {
0476 ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
0477 if (ZSTD_isError(bounds.error)) return bounds.error;
0478 if (*value < bounds.lowerBound) *value = bounds.lowerBound;
0479 if (*value > bounds.upperBound) *value = bounds.upperBound;
0480 return 0;
0481 }
0482
0483 #define BOUNDCHECK(cParam, val) { \
0484 RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
0485 parameter_outOfBound, "Param out of bounds"); \
0486 }
0487
0488
0489 static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
0490 {
0491 switch(param)
0492 {
0493 case ZSTD_c_compressionLevel:
0494 case ZSTD_c_hashLog:
0495 case ZSTD_c_chainLog:
0496 case ZSTD_c_searchLog:
0497 case ZSTD_c_minMatch:
0498 case ZSTD_c_targetLength:
0499 case ZSTD_c_strategy:
0500 return 1;
0501
0502 case ZSTD_c_format:
0503 case ZSTD_c_windowLog:
0504 case ZSTD_c_contentSizeFlag:
0505 case ZSTD_c_checksumFlag:
0506 case ZSTD_c_dictIDFlag:
0507 case ZSTD_c_forceMaxWindow :
0508 case ZSTD_c_nbWorkers:
0509 case ZSTD_c_jobSize:
0510 case ZSTD_c_overlapLog:
0511 case ZSTD_c_rsyncable:
0512 case ZSTD_c_enableDedicatedDictSearch:
0513 case ZSTD_c_enableLongDistanceMatching:
0514 case ZSTD_c_ldmHashLog:
0515 case ZSTD_c_ldmMinMatch:
0516 case ZSTD_c_ldmBucketSizeLog:
0517 case ZSTD_c_ldmHashRateLog:
0518 case ZSTD_c_forceAttachDict:
0519 case ZSTD_c_literalCompressionMode:
0520 case ZSTD_c_targetCBlockSize:
0521 case ZSTD_c_srcSizeHint:
0522 case ZSTD_c_stableInBuffer:
0523 case ZSTD_c_stableOutBuffer:
0524 case ZSTD_c_blockDelimiters:
0525 case ZSTD_c_validateSequences:
0526 default:
0527 return 0;
0528 }
0529 }
0530
0531 size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
0532 {
0533 DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value);
0534 if (cctx->streamStage != zcss_init) {
0535 if (ZSTD_isUpdateAuthorized(param)) {
0536 cctx->cParamsChanged = 1;
0537 } else {
0538 RETURN_ERROR(stage_wrong, "can only set params in ctx init stage");
0539 } }
0540
0541 switch(param)
0542 {
0543 case ZSTD_c_nbWorkers:
0544 RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
0545 "MT not compatible with static alloc");
0546 break;
0547
0548 case ZSTD_c_compressionLevel:
0549 case ZSTD_c_windowLog:
0550 case ZSTD_c_hashLog:
0551 case ZSTD_c_chainLog:
0552 case ZSTD_c_searchLog:
0553 case ZSTD_c_minMatch:
0554 case ZSTD_c_targetLength:
0555 case ZSTD_c_strategy:
0556 case ZSTD_c_ldmHashRateLog:
0557 case ZSTD_c_format:
0558 case ZSTD_c_contentSizeFlag:
0559 case ZSTD_c_checksumFlag:
0560 case ZSTD_c_dictIDFlag:
0561 case ZSTD_c_forceMaxWindow:
0562 case ZSTD_c_forceAttachDict:
0563 case ZSTD_c_literalCompressionMode:
0564 case ZSTD_c_jobSize:
0565 case ZSTD_c_overlapLog:
0566 case ZSTD_c_rsyncable:
0567 case ZSTD_c_enableDedicatedDictSearch:
0568 case ZSTD_c_enableLongDistanceMatching:
0569 case ZSTD_c_ldmHashLog:
0570 case ZSTD_c_ldmMinMatch:
0571 case ZSTD_c_ldmBucketSizeLog:
0572 case ZSTD_c_targetCBlockSize:
0573 case ZSTD_c_srcSizeHint:
0574 case ZSTD_c_stableInBuffer:
0575 case ZSTD_c_stableOutBuffer:
0576 case ZSTD_c_blockDelimiters:
0577 case ZSTD_c_validateSequences:
0578 break;
0579
0580 default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
0581 }
0582 return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
0583 }
0584
0585 size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
0586 ZSTD_cParameter param, int value)
0587 {
0588 DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
0589 switch(param)
0590 {
0591 case ZSTD_c_format :
0592 BOUNDCHECK(ZSTD_c_format, value);
0593 CCtxParams->format = (ZSTD_format_e)value;
0594 return (size_t)CCtxParams->format;
0595
0596 case ZSTD_c_compressionLevel : {
0597 FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
0598 if (value == 0)
0599 CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT;
0600 else
0601 CCtxParams->compressionLevel = value;
0602 if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
0603 return 0;
0604 }
0605
0606 case ZSTD_c_windowLog :
0607 if (value!=0)
0608 BOUNDCHECK(ZSTD_c_windowLog, value);
0609 CCtxParams->cParams.windowLog = (U32)value;
0610 return CCtxParams->cParams.windowLog;
0611
0612 case ZSTD_c_hashLog :
0613 if (value!=0)
0614 BOUNDCHECK(ZSTD_c_hashLog, value);
0615 CCtxParams->cParams.hashLog = (U32)value;
0616 return CCtxParams->cParams.hashLog;
0617
0618 case ZSTD_c_chainLog :
0619 if (value!=0)
0620 BOUNDCHECK(ZSTD_c_chainLog, value);
0621 CCtxParams->cParams.chainLog = (U32)value;
0622 return CCtxParams->cParams.chainLog;
0623
0624 case ZSTD_c_searchLog :
0625 if (value!=0)
0626 BOUNDCHECK(ZSTD_c_searchLog, value);
0627 CCtxParams->cParams.searchLog = (U32)value;
0628 return (size_t)value;
0629
0630 case ZSTD_c_minMatch :
0631 if (value!=0)
0632 BOUNDCHECK(ZSTD_c_minMatch, value);
0633 CCtxParams->cParams.minMatch = value;
0634 return CCtxParams->cParams.minMatch;
0635
0636 case ZSTD_c_targetLength :
0637 BOUNDCHECK(ZSTD_c_targetLength, value);
0638 CCtxParams->cParams.targetLength = value;
0639 return CCtxParams->cParams.targetLength;
0640
0641 case ZSTD_c_strategy :
0642 if (value!=0)
0643 BOUNDCHECK(ZSTD_c_strategy, value);
0644 CCtxParams->cParams.strategy = (ZSTD_strategy)value;
0645 return (size_t)CCtxParams->cParams.strategy;
0646
0647 case ZSTD_c_contentSizeFlag :
0648
0649 DEBUGLOG(4, "set content size flag = %u", (value!=0));
0650 CCtxParams->fParams.contentSizeFlag = value != 0;
0651 return CCtxParams->fParams.contentSizeFlag;
0652
0653 case ZSTD_c_checksumFlag :
0654
0655 CCtxParams->fParams.checksumFlag = value != 0;
0656 return CCtxParams->fParams.checksumFlag;
0657
0658 case ZSTD_c_dictIDFlag :
0659 DEBUGLOG(4, "set dictIDFlag = %u", (value!=0));
0660 CCtxParams->fParams.noDictIDFlag = !value;
0661 return !CCtxParams->fParams.noDictIDFlag;
0662
0663 case ZSTD_c_forceMaxWindow :
0664 CCtxParams->forceWindow = (value != 0);
0665 return CCtxParams->forceWindow;
0666
0667 case ZSTD_c_forceAttachDict : {
0668 const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value;
0669 BOUNDCHECK(ZSTD_c_forceAttachDict, pref);
0670 CCtxParams->attachDictPref = pref;
0671 return CCtxParams->attachDictPref;
0672 }
0673
0674 case ZSTD_c_literalCompressionMode : {
0675 const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
0676 BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
0677 CCtxParams->literalCompressionMode = lcm;
0678 return CCtxParams->literalCompressionMode;
0679 }
0680
0681 case ZSTD_c_nbWorkers :
0682 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
0683 return 0;
0684
0685 case ZSTD_c_jobSize :
0686 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
0687 return 0;
0688
0689 case ZSTD_c_overlapLog :
0690 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
0691 return 0;
0692
0693 case ZSTD_c_rsyncable :
0694 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
0695 return 0;
0696
0697 case ZSTD_c_enableDedicatedDictSearch :
0698 CCtxParams->enableDedicatedDictSearch = (value!=0);
0699 return CCtxParams->enableDedicatedDictSearch;
0700
0701 case ZSTD_c_enableLongDistanceMatching :
0702 CCtxParams->ldmParams.enableLdm = (value!=0);
0703 return CCtxParams->ldmParams.enableLdm;
0704
0705 case ZSTD_c_ldmHashLog :
0706 if (value!=0)
0707 BOUNDCHECK(ZSTD_c_ldmHashLog, value);
0708 CCtxParams->ldmParams.hashLog = value;
0709 return CCtxParams->ldmParams.hashLog;
0710
0711 case ZSTD_c_ldmMinMatch :
0712 if (value!=0)
0713 BOUNDCHECK(ZSTD_c_ldmMinMatch, value);
0714 CCtxParams->ldmParams.minMatchLength = value;
0715 return CCtxParams->ldmParams.minMatchLength;
0716
0717 case ZSTD_c_ldmBucketSizeLog :
0718 if (value!=0)
0719 BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value);
0720 CCtxParams->ldmParams.bucketSizeLog = value;
0721 return CCtxParams->ldmParams.bucketSizeLog;
0722
0723 case ZSTD_c_ldmHashRateLog :
0724 if (value!=0)
0725 BOUNDCHECK(ZSTD_c_ldmHashRateLog, value);
0726 CCtxParams->ldmParams.hashRateLog = value;
0727 return CCtxParams->ldmParams.hashRateLog;
0728
0729 case ZSTD_c_targetCBlockSize :
0730 if (value!=0)
0731 BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
0732 CCtxParams->targetCBlockSize = value;
0733 return CCtxParams->targetCBlockSize;
0734
0735 case ZSTD_c_srcSizeHint :
0736 if (value!=0)
0737 BOUNDCHECK(ZSTD_c_srcSizeHint, value);
0738 CCtxParams->srcSizeHint = value;
0739 return CCtxParams->srcSizeHint;
0740
0741 case ZSTD_c_stableInBuffer:
0742 BOUNDCHECK(ZSTD_c_stableInBuffer, value);
0743 CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value;
0744 return CCtxParams->inBufferMode;
0745
0746 case ZSTD_c_stableOutBuffer:
0747 BOUNDCHECK(ZSTD_c_stableOutBuffer, value);
0748 CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value;
0749 return CCtxParams->outBufferMode;
0750
0751 case ZSTD_c_blockDelimiters:
0752 BOUNDCHECK(ZSTD_c_blockDelimiters, value);
0753 CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value;
0754 return CCtxParams->blockDelimiters;
0755
0756 case ZSTD_c_validateSequences:
0757 BOUNDCHECK(ZSTD_c_validateSequences, value);
0758 CCtxParams->validateSequences = value;
0759 return CCtxParams->validateSequences;
0760
0761 default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
0762 }
0763 }
0764
0765 size_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value)
0766 {
0767 return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
0768 }
0769
0770 size_t ZSTD_CCtxParams_getParameter(
0771 ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value)
0772 {
0773 switch(param)
0774 {
0775 case ZSTD_c_format :
0776 *value = CCtxParams->format;
0777 break;
0778 case ZSTD_c_compressionLevel :
0779 *value = CCtxParams->compressionLevel;
0780 break;
0781 case ZSTD_c_windowLog :
0782 *value = (int)CCtxParams->cParams.windowLog;
0783 break;
0784 case ZSTD_c_hashLog :
0785 *value = (int)CCtxParams->cParams.hashLog;
0786 break;
0787 case ZSTD_c_chainLog :
0788 *value = (int)CCtxParams->cParams.chainLog;
0789 break;
0790 case ZSTD_c_searchLog :
0791 *value = CCtxParams->cParams.searchLog;
0792 break;
0793 case ZSTD_c_minMatch :
0794 *value = CCtxParams->cParams.minMatch;
0795 break;
0796 case ZSTD_c_targetLength :
0797 *value = CCtxParams->cParams.targetLength;
0798 break;
0799 case ZSTD_c_strategy :
0800 *value = (unsigned)CCtxParams->cParams.strategy;
0801 break;
0802 case ZSTD_c_contentSizeFlag :
0803 *value = CCtxParams->fParams.contentSizeFlag;
0804 break;
0805 case ZSTD_c_checksumFlag :
0806 *value = CCtxParams->fParams.checksumFlag;
0807 break;
0808 case ZSTD_c_dictIDFlag :
0809 *value = !CCtxParams->fParams.noDictIDFlag;
0810 break;
0811 case ZSTD_c_forceMaxWindow :
0812 *value = CCtxParams->forceWindow;
0813 break;
0814 case ZSTD_c_forceAttachDict :
0815 *value = CCtxParams->attachDictPref;
0816 break;
0817 case ZSTD_c_literalCompressionMode :
0818 *value = CCtxParams->literalCompressionMode;
0819 break;
0820 case ZSTD_c_nbWorkers :
0821 assert(CCtxParams->nbWorkers == 0);
0822 *value = CCtxParams->nbWorkers;
0823 break;
0824 case ZSTD_c_jobSize :
0825 RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
0826 case ZSTD_c_overlapLog :
0827 RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
0828 case ZSTD_c_rsyncable :
0829 RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
0830 case ZSTD_c_enableDedicatedDictSearch :
0831 *value = CCtxParams->enableDedicatedDictSearch;
0832 break;
0833 case ZSTD_c_enableLongDistanceMatching :
0834 *value = CCtxParams->ldmParams.enableLdm;
0835 break;
0836 case ZSTD_c_ldmHashLog :
0837 *value = CCtxParams->ldmParams.hashLog;
0838 break;
0839 case ZSTD_c_ldmMinMatch :
0840 *value = CCtxParams->ldmParams.minMatchLength;
0841 break;
0842 case ZSTD_c_ldmBucketSizeLog :
0843 *value = CCtxParams->ldmParams.bucketSizeLog;
0844 break;
0845 case ZSTD_c_ldmHashRateLog :
0846 *value = CCtxParams->ldmParams.hashRateLog;
0847 break;
0848 case ZSTD_c_targetCBlockSize :
0849 *value = (int)CCtxParams->targetCBlockSize;
0850 break;
0851 case ZSTD_c_srcSizeHint :
0852 *value = (int)CCtxParams->srcSizeHint;
0853 break;
0854 case ZSTD_c_stableInBuffer :
0855 *value = (int)CCtxParams->inBufferMode;
0856 break;
0857 case ZSTD_c_stableOutBuffer :
0858 *value = (int)CCtxParams->outBufferMode;
0859 break;
0860 case ZSTD_c_blockDelimiters :
0861 *value = (int)CCtxParams->blockDelimiters;
0862 break;
0863 case ZSTD_c_validateSequences :
0864 *value = (int)CCtxParams->validateSequences;
0865 break;
0866 default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
0867 }
0868 return 0;
0869 }
0870
0871
0872
0873
0874
0875
0876
0877
0878 size_t ZSTD_CCtx_setParametersUsingCCtxParams(
0879 ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
0880 {
0881 DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
0882 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
0883 "The context is in the wrong stage!");
0884 RETURN_ERROR_IF(cctx->cdict, stage_wrong,
0885 "Can't override parameters with cdict attached (some must "
0886 "be inherited from the cdict).");
0887
0888 cctx->requestedParams = *params;
0889 return 0;
0890 }
0891
0892 ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
0893 {
0894 DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
0895 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
0896 "Can't set pledgedSrcSize when not in init stage.");
0897 cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
0898 return 0;
0899 }
0900
0901 static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(
0902 int const compressionLevel,
0903 size_t const dictSize);
0904 static int ZSTD_dedicatedDictSearch_isSupported(
0905 const ZSTD_compressionParameters* cParams);
0906 static void ZSTD_dedicatedDictSearch_revertCParams(
0907 ZSTD_compressionParameters* cParams);
0908
0909
0910
0911
0912
0913
0914 static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
0915 {
0916 ZSTD_localDict* const dl = &cctx->localDict;
0917 if (dl->dict == NULL) {
0918
0919 assert(dl->dictBuffer == NULL);
0920 assert(dl->cdict == NULL);
0921 assert(dl->dictSize == 0);
0922 return 0;
0923 }
0924 if (dl->cdict != NULL) {
0925 assert(cctx->cdict == dl->cdict);
0926
0927 return 0;
0928 }
0929 assert(dl->dictSize > 0);
0930 assert(cctx->cdict == NULL);
0931 assert(cctx->prefixDict.dict == NULL);
0932
0933 dl->cdict = ZSTD_createCDict_advanced2(
0934 dl->dict,
0935 dl->dictSize,
0936 ZSTD_dlm_byRef,
0937 dl->dictContentType,
0938 &cctx->requestedParams,
0939 cctx->customMem);
0940 RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
0941 cctx->cdict = dl->cdict;
0942 return 0;
0943 }
0944
0945 size_t ZSTD_CCtx_loadDictionary_advanced(
0946 ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
0947 ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
0948 {
0949 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
0950 "Can't load a dictionary when ctx is not in init stage.");
0951 DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
0952 ZSTD_clearAllDicts(cctx);
0953 if (dict == NULL || dictSize == 0)
0954 return 0;
0955 if (dictLoadMethod == ZSTD_dlm_byRef) {
0956 cctx->localDict.dict = dict;
0957 } else {
0958 void* dictBuffer;
0959 RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
0960 "no malloc for static CCtx");
0961 dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem);
0962 RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
0963 ZSTD_memcpy(dictBuffer, dict, dictSize);
0964 cctx->localDict.dictBuffer = dictBuffer;
0965 cctx->localDict.dict = dictBuffer;
0966 }
0967 cctx->localDict.dictSize = dictSize;
0968 cctx->localDict.dictContentType = dictContentType;
0969 return 0;
0970 }
0971
0972 ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
0973 ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
0974 {
0975 return ZSTD_CCtx_loadDictionary_advanced(
0976 cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
0977 }
0978
0979 ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
0980 {
0981 return ZSTD_CCtx_loadDictionary_advanced(
0982 cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
0983 }
0984
0985
0986 size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
0987 {
0988 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
0989 "Can't ref a dict when ctx not in init stage.");
0990
0991 ZSTD_clearAllDicts(cctx);
0992 cctx->cdict = cdict;
0993 return 0;
0994 }
0995
0996 size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool)
0997 {
0998 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
0999 "Can't ref a pool when ctx not in init stage.");
1000 cctx->pool = pool;
1001 return 0;
1002 }
1003
1004 size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
1005 {
1006 return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);
1007 }
1008
1009 size_t ZSTD_CCtx_refPrefix_advanced(
1010 ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1011 {
1012 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
1013 "Can't ref a prefix when ctx not in init stage.");
1014 ZSTD_clearAllDicts(cctx);
1015 if (prefix != NULL && prefixSize > 0) {
1016 cctx->prefixDict.dict = prefix;
1017 cctx->prefixDict.dictSize = prefixSize;
1018 cctx->prefixDict.dictContentType = dictContentType;
1019 }
1020 return 0;
1021 }
1022
1023
1024
1025 size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
1026 {
1027 if ( (reset == ZSTD_reset_session_only)
1028 || (reset == ZSTD_reset_session_and_parameters) ) {
1029 cctx->streamStage = zcss_init;
1030 cctx->pledgedSrcSizePlusOne = 0;
1031 }
1032 if ( (reset == ZSTD_reset_parameters)
1033 || (reset == ZSTD_reset_session_and_parameters) ) {
1034 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
1035 "Can't reset parameters only when not in init stage.");
1036 ZSTD_clearAllDicts(cctx);
1037 return ZSTD_CCtxParams_reset(&cctx->requestedParams);
1038 }
1039 return 0;
1040 }
1041
1042
1043
1044
1045
1046 size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
1047 {
1048 BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);
1049 BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog);
1050 BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog);
1051 BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);
1052 BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch);
1053 BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);
1054 BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
1055 return 0;
1056 }
1057
1058
1059
1060
1061 static ZSTD_compressionParameters
1062 ZSTD_clampCParams(ZSTD_compressionParameters cParams)
1063 {
1064 # define CLAMP_TYPE(cParam, val, type) { \
1065 ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \
1066 if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
1067 else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
1068 }
1069 # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
1070 CLAMP(ZSTD_c_windowLog, cParams.windowLog);
1071 CLAMP(ZSTD_c_chainLog, cParams.chainLog);
1072 CLAMP(ZSTD_c_hashLog, cParams.hashLog);
1073 CLAMP(ZSTD_c_searchLog, cParams.searchLog);
1074 CLAMP(ZSTD_c_minMatch, cParams.minMatch);
1075 CLAMP(ZSTD_c_targetLength,cParams.targetLength);
1076 CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy);
1077 return cParams;
1078 }
1079
1080
1081
1082 U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
1083 {
1084 U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
1085 return hashLog - btScale;
1086 }
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096 static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize)
1097 {
1098 const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX;
1099
1100 if (dictSize == 0) {
1101 return windowLog;
1102 }
1103 assert(windowLog <= ZSTD_WINDOWLOG_MAX);
1104 assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN);
1105 {
1106 U64 const windowSize = 1ULL << windowLog;
1107 U64 const dictAndWindowSize = dictSize + windowSize;
1108
1109
1110
1111
1112 if (windowSize >= dictSize + srcSize) {
1113 return windowLog;
1114 } else if (dictAndWindowSize >= maxWindowSize) {
1115 return ZSTD_WINDOWLOG_MAX;
1116 } else {
1117 return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1;
1118 }
1119 }
1120 }
1121
1122
1123
1124
1125
1126
1127
1128
1129 static ZSTD_compressionParameters
1130 ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
1131 unsigned long long srcSize,
1132 size_t dictSize,
1133 ZSTD_cParamMode_e mode)
1134 {
1135 const U64 minSrcSize = 513;
1136 const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
1137 assert(ZSTD_checkCParams(cPar)==0);
1138
1139 switch (mode) {
1140 case ZSTD_cpm_unknown:
1141 case ZSTD_cpm_noAttachDict:
1142
1143
1144
1145
1146 break;
1147 case ZSTD_cpm_createCDict:
1148
1149
1150
1151 if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
1152 srcSize = minSrcSize;
1153 break;
1154 case ZSTD_cpm_attachDict:
1155
1156
1157
1158
1159 dictSize = 0;
1160 break;
1161 default:
1162 assert(0);
1163 break;
1164 }
1165
1166
1167 if ( (srcSize < maxWindowResize)
1168 && (dictSize < maxWindowResize) ) {
1169 U32 const tSize = (U32)(srcSize + dictSize);
1170 static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;
1171 U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :
1172 ZSTD_highbit32(tSize-1) + 1;
1173 if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
1174 }
1175 if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
1176 U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize);
1177 U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
1178 if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1;
1179 if (cycleLog > dictAndWindowLog)
1180 cPar.chainLog -= (cycleLog - dictAndWindowLog);
1181 }
1182
1183 if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
1184 cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN;
1185
1186 return cPar;
1187 }
1188
1189 ZSTD_compressionParameters
1190 ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
1191 unsigned long long srcSize,
1192 size_t dictSize)
1193 {
1194 cPar = ZSTD_clampCParams(cPar);
1195 if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
1196 return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown);
1197 }
1198
1199 static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
1200 static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
1201
1202 static void ZSTD_overrideCParams(
1203 ZSTD_compressionParameters* cParams,
1204 const ZSTD_compressionParameters* overrides)
1205 {
1206 if (overrides->windowLog) cParams->windowLog = overrides->windowLog;
1207 if (overrides->hashLog) cParams->hashLog = overrides->hashLog;
1208 if (overrides->chainLog) cParams->chainLog = overrides->chainLog;
1209 if (overrides->searchLog) cParams->searchLog = overrides->searchLog;
1210 if (overrides->minMatch) cParams->minMatch = overrides->minMatch;
1211 if (overrides->targetLength) cParams->targetLength = overrides->targetLength;
1212 if (overrides->strategy) cParams->strategy = overrides->strategy;
1213 }
1214
1215 ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
1216 const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
1217 {
1218 ZSTD_compressionParameters cParams;
1219 if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {
1220 srcSizeHint = CCtxParams->srcSizeHint;
1221 }
1222 cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode);
1223 if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
1224 ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);
1225 assert(!ZSTD_checkCParams(cParams));
1226
1227 return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode);
1228 }
1229
1230 static size_t
1231 ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
1232 const U32 forCCtx)
1233 {
1234 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
1235 size_t const hSize = ((size_t)1) << cParams->hashLog;
1236 U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
1237 size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
1238
1239
1240 size_t const tableSpace = chainSize * sizeof(U32)
1241 + hSize * sizeof(U32)
1242 + h3Size * sizeof(U32);
1243 size_t const optPotentialSpace =
1244 ZSTD_cwksp_alloc_size((MaxML+1) * sizeof(U32))
1245 + ZSTD_cwksp_alloc_size((MaxLL+1) * sizeof(U32))
1246 + ZSTD_cwksp_alloc_size((MaxOff+1) * sizeof(U32))
1247 + ZSTD_cwksp_alloc_size((1<<Litbits) * sizeof(U32))
1248 + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
1249 + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
1250 size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
1251 ? optPotentialSpace
1252 : 0;
1253 DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u",
1254 (U32)chainSize, (U32)hSize, (U32)h3Size);
1255 return tableSpace + optSpace;
1256 }
1257
1258 static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
1259 const ZSTD_compressionParameters* cParams,
1260 const ldmParams_t* ldmParams,
1261 const int isStatic,
1262 const size_t buffInSize,
1263 const size_t buffOutSize,
1264 const U64 pledgedSrcSize)
1265 {
1266 size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize));
1267 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
1268 U32 const divider = (cParams->minMatch==3) ? 3 : 4;
1269 size_t const maxNbSeq = blockSize / divider;
1270 size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
1271 + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
1272 + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
1273 size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE);
1274 size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
1275 size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, 1);
1276
1277 size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams);
1278 size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize);
1279 size_t const ldmSeqSpace = ldmParams->enableLdm ?
1280 ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0;
1281
1282
1283 size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize)
1284 + ZSTD_cwksp_alloc_size(buffOutSize);
1285
1286 size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
1287
1288 size_t const neededSpace =
1289 cctxSpace +
1290 entropySpace +
1291 blockStateSpace +
1292 ldmSpace +
1293 ldmSeqSpace +
1294 matchStateSize +
1295 tokenSpace +
1296 bufferSpace;
1297
1298 DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
1299 return neededSpace;
1300 }
1301
1302 size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1303 {
1304 ZSTD_compressionParameters const cParams =
1305 ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
1306
1307 RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
1308
1309
1310
1311 return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
1312 &cParams, ¶ms->ldmParams, 1, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN);
1313 }
1314
1315 size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
1316 {
1317 ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
1318 return ZSTD_estimateCCtxSize_usingCCtxParams(¶ms);
1319 }
1320
1321 static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
1322 {
1323 int tier = 0;
1324 size_t largestSize = 0;
1325 static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN};
1326 for (; tier < 4; ++tier) {
1327
1328 ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict);
1329 largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize);
1330 }
1331 return largestSize;
1332 }
1333
1334 size_t ZSTD_estimateCCtxSize(int compressionLevel)
1335 {
1336 int level;
1337 size_t memBudget = 0;
1338 for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {
1339
1340 size_t const newMB = ZSTD_estimateCCtxSize_internal(level);
1341 if (newMB > memBudget) memBudget = newMB;
1342 }
1343 return memBudget;
1344 }
1345
1346 size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1347 {
1348 RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
1349 { ZSTD_compressionParameters const cParams =
1350 ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
1351 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
1352 size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)
1353 ? ((size_t)1 << cParams.windowLog) + blockSize
1354 : 0;
1355 size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)
1356 ? ZSTD_compressBound(blockSize) + 1
1357 : 0;
1358
1359 return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
1360 &cParams, ¶ms->ldmParams, 1, inBuffSize, outBuffSize,
1361 ZSTD_CONTENTSIZE_UNKNOWN);
1362 }
1363 }
1364
1365 size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
1366 {
1367 ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
1368 return ZSTD_estimateCStreamSize_usingCCtxParams(¶ms);
1369 }
1370
1371 static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
1372 {
1373 ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
1374 return ZSTD_estimateCStreamSize_usingCParams(cParams);
1375 }
1376
1377 size_t ZSTD_estimateCStreamSize(int compressionLevel)
1378 {
1379 int level;
1380 size_t memBudget = 0;
1381 for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {
1382 size_t const newMB = ZSTD_estimateCStreamSize_internal(level);
1383 if (newMB > memBudget) memBudget = newMB;
1384 }
1385 return memBudget;
1386 }
1387
1388
1389
1390
1391
1392 ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)
1393 {
1394 { ZSTD_frameProgression fp;
1395 size_t const buffered = (cctx->inBuff == NULL) ? 0 :
1396 cctx->inBuffPos - cctx->inToCompress;
1397 if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress);
1398 assert(buffered <= ZSTD_BLOCKSIZE_MAX);
1399 fp.ingested = cctx->consumedSrcSize + buffered;
1400 fp.consumed = cctx->consumedSrcSize;
1401 fp.produced = cctx->producedCSize;
1402 fp.flushed = cctx->producedCSize;
1403 fp.currentJobID = 0;
1404 fp.nbActiveWorkers = 0;
1405 return fp;
1406 } }
1407
1408
1409
1410
1411 size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
1412 {
1413 (void)cctx;
1414 return 0;
1415 }
1416
1417 static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
1418 ZSTD_compressionParameters cParams2)
1419 {
1420 (void)cParams1;
1421 (void)cParams2;
1422 assert(cParams1.windowLog == cParams2.windowLog);
1423 assert(cParams1.chainLog == cParams2.chainLog);
1424 assert(cParams1.hashLog == cParams2.hashLog);
1425 assert(cParams1.searchLog == cParams2.searchLog);
1426 assert(cParams1.minMatch == cParams2.minMatch);
1427 assert(cParams1.targetLength == cParams2.targetLength);
1428 assert(cParams1.strategy == cParams2.strategy);
1429 }
1430
1431 void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
1432 {
1433 int i;
1434 for (i = 0; i < ZSTD_REP_NUM; ++i)
1435 bs->rep[i] = repStartValue[i];
1436 bs->entropy.huf.repeatMode = HUF_repeat_none;
1437 bs->entropy.fse.offcode_repeatMode = FSE_repeat_none;
1438 bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;
1439 bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;
1440 }
1441
1442
1443
1444
1445
1446 static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
1447 {
1448 ZSTD_window_clear(&ms->window);
1449
1450 ms->nextToUpdate = ms->window.dictLimit;
1451 ms->loadedDictEnd = 0;
1452 ms->opt.litLengthSum = 0;
1453 ms->dictMatchState = NULL;
1454 }
1455
1456
1457
1458
1459
1460
1461
1462
1463 typedef enum {
1464 ZSTDcrp_makeClean,
1465 ZSTDcrp_leaveDirty
1466 } ZSTD_compResetPolicy_e;
1467
1468
1469
1470
1471
1472
1473 typedef enum {
1474 ZSTDirp_continue,
1475 ZSTDirp_reset
1476 } ZSTD_indexResetPolicy_e;
1477
1478 typedef enum {
1479 ZSTD_resetTarget_CDict,
1480 ZSTD_resetTarget_CCtx
1481 } ZSTD_resetTarget_e;
1482
1483 static size_t
1484 ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1485 ZSTD_cwksp* ws,
1486 const ZSTD_compressionParameters* cParams,
1487 const ZSTD_compResetPolicy_e crp,
1488 const ZSTD_indexResetPolicy_e forceResetIndex,
1489 const ZSTD_resetTarget_e forWho)
1490 {
1491 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
1492 size_t const hSize = ((size_t)1) << cParams->hashLog;
1493 U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
1494 size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
1495
1496 DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset);
1497 if (forceResetIndex == ZSTDirp_reset) {
1498 ZSTD_window_init(&ms->window);
1499 ZSTD_cwksp_mark_tables_dirty(ws);
1500 }
1501
1502 ms->hashLog3 = hashLog3;
1503
1504 ZSTD_invalidateMatchState(ms);
1505
1506 assert(!ZSTD_cwksp_reserve_failed(ws));
1507
1508 ZSTD_cwksp_clear_tables(ws);
1509
1510 DEBUGLOG(5, "reserving table space");
1511
1512 ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32));
1513 ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32));
1514 ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32));
1515 RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
1516 "failed a workspace allocation in ZSTD_reset_matchState");
1517
1518 DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_leaveDirty);
1519 if (crp!=ZSTDcrp_leaveDirty) {
1520
1521 ZSTD_cwksp_clean_tables(ws);
1522 }
1523
1524
1525 if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
1526 DEBUGLOG(4, "reserving optimal parser space");
1527 ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<<Litbits) * sizeof(unsigned));
1528 ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned));
1529 ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned));
1530 ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned));
1531 ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t));
1532 ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
1533 }
1534
1535 ms->cParams = *cParams;
1536
1537 RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
1538 "failed a workspace allocation in ZSTD_reset_matchState");
1539
1540 return 0;
1541 }
1542
1543
1544
1545
1546
1547
1548
1549
1550 #define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)
1551 static int ZSTD_indexTooCloseToMax(ZSTD_window_t w)
1552 {
1553 return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
1554 }
1555
1556
1557
1558 static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1559 ZSTD_CCtx_params params,
1560 U64 const pledgedSrcSize,
1561 ZSTD_compResetPolicy_e const crp,
1562 ZSTD_buffered_policy_e const zbuff)
1563 {
1564 ZSTD_cwksp* const ws = &zc->workspace;
1565 DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
1566 (U32)pledgedSrcSize, params.cParams.windowLog);
1567 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
1568
1569 zc->isFirstBlock = 1;
1570
1571 if (params.ldmParams.enableLdm) {
1572
1573 ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams);
1574 assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
1575 assert(params.ldmParams.hashRateLog < 32);
1576 }
1577
1578 { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
1579 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
1580 U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
1581 size_t const maxNbSeq = blockSize / divider;
1582 size_t const buffOutSize = (zbuff == ZSTDb_buffered && params.outBufferMode == ZSTD_bm_buffered)
1583 ? ZSTD_compressBound(blockSize) + 1
1584 : 0;
1585 size_t const buffInSize = (zbuff == ZSTDb_buffered && params.inBufferMode == ZSTD_bm_buffered)
1586 ? windowSize + blockSize
1587 : 0;
1588 size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
1589
1590 int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window);
1591 ZSTD_indexResetPolicy_e needsIndexReset =
1592 (!indexTooClose && zc->initialized) ? ZSTDirp_continue : ZSTDirp_reset;
1593
1594 size_t const neededSpace =
1595 ZSTD_estimateCCtxSize_usingCCtxParams_internal(
1596 ¶ms.cParams, ¶ms.ldmParams, zc->staticSize != 0,
1597 buffInSize, buffOutSize, pledgedSrcSize);
1598 FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
1599
1600 if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
1601
1602
1603 {
1604 int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
1605 int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
1606
1607 DEBUGLOG(4, "Need %zu B workspace", neededSpace);
1608 DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
1609
1610 if (workspaceTooSmall || workspaceWasteful) {
1611 DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
1612 ZSTD_cwksp_sizeof(ws) >> 10,
1613 neededSpace >> 10);
1614
1615 RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
1616
1617 needsIndexReset = ZSTDirp_reset;
1618
1619 ZSTD_cwksp_free(ws, zc->customMem);
1620 FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), "");
1621
1622 DEBUGLOG(5, "reserving object space");
1623
1624
1625
1626 assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t)));
1627 zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
1628 RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
1629 zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
1630 RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
1631 zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE);
1632 RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
1633 } }
1634
1635 ZSTD_cwksp_clear(ws);
1636
1637
1638 zc->appliedParams = params;
1639 zc->blockState.matchState.cParams = params.cParams;
1640 zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
1641 zc->consumedSrcSize = 0;
1642 zc->producedCSize = 0;
1643 if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
1644 zc->appliedParams.fParams.contentSizeFlag = 0;
1645 DEBUGLOG(4, "pledged content size : %u ; flag : %u",
1646 (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);
1647 zc->blockSize = blockSize;
1648
1649 xxh64_reset(&zc->xxhState, 0);
1650 zc->stage = ZSTDcs_init;
1651 zc->dictID = 0;
1652 zc->dictContentSize = 0;
1653
1654 ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
1655
1656
1657
1658
1659 zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);
1660 zc->seqStore.maxNbLit = blockSize;
1661
1662
1663 zc->bufferedPolicy = zbuff;
1664 zc->inBuffSize = buffInSize;
1665 zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);
1666 zc->outBuffSize = buffOutSize;
1667 zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);
1668
1669
1670 if (params.ldmParams.enableLdm) {
1671
1672 size_t const numBuckets =
1673 ((size_t)1) << (params.ldmParams.hashLog -
1674 params.ldmParams.bucketSizeLog);
1675 zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets);
1676 ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets);
1677 }
1678
1679
1680 ZSTD_referenceExternalSequences(zc, NULL, 0);
1681 zc->seqStore.maxNbSeq = maxNbSeq;
1682 zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
1683 zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
1684 zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
1685 zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef));
1686
1687 FORWARD_IF_ERROR(ZSTD_reset_matchState(
1688 &zc->blockState.matchState,
1689 ws,
1690 ¶ms.cParams,
1691 crp,
1692 needsIndexReset,
1693 ZSTD_resetTarget_CCtx), "");
1694
1695
1696 if (params.ldmParams.enableLdm) {
1697
1698 size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
1699 zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t));
1700 ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));
1701 zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq));
1702 zc->maxNbLdmSequences = maxNbLdmSeq;
1703
1704 ZSTD_window_init(&zc->ldmState.window);
1705 ZSTD_window_clear(&zc->ldmState.window);
1706 zc->ldmState.loadedDictEnd = 0;
1707 }
1708
1709
1710
1711
1712 assert(ZSTD_cwksp_used(ws) >= neededSpace &&
1713 ZSTD_cwksp_used(ws) <= neededSpace + 3);
1714
1715 DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
1716 zc->initialized = 1;
1717
1718 return 0;
1719 }
1720 }
1721
1722
1723
1724
1725
1726 void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
1727 int i;
1728 for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;
1729 assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
1730 }
1731
1732
1733
1734
1735
1736 static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {
1737 8 KB,
1738 8 KB,
1739 16 KB,
1740 32 KB,
1741 32 KB,
1742 32 KB,
1743 32 KB,
1744 32 KB,
1745 8 KB,
1746 8 KB
1747 };
1748
1749 static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
1750 const ZSTD_CCtx_params* params,
1751 U64 pledgedSrcSize)
1752 {
1753 size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
1754 int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch;
1755 return dedicatedDictSearch
1756 || ( ( pledgedSrcSize <= cutoff
1757 || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
1758 || params->attachDictPref == ZSTD_dictForceAttach )
1759 && params->attachDictPref != ZSTD_dictForceCopy
1760 && !params->forceWindow );
1761
1762 }
1763
1764 static size_t
1765 ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
1766 const ZSTD_CDict* cdict,
1767 ZSTD_CCtx_params params,
1768 U64 pledgedSrcSize,
1769 ZSTD_buffered_policy_e zbuff)
1770 {
1771 {
1772 ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams;
1773 unsigned const windowLog = params.cParams.windowLog;
1774 assert(windowLog != 0);
1775
1776
1777
1778
1779 if (cdict->matchState.dedicatedDictSearch) {
1780 ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams);
1781 }
1782
1783 params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize,
1784 cdict->dictContentSize, ZSTD_cpm_attachDict);
1785 params.cParams.windowLog = windowLog;
1786 FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1787 ZSTDcrp_makeClean, zbuff), "");
1788 assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy);
1789 }
1790
1791 { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1792 - cdict->matchState.window.base);
1793 const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
1794 if (cdictLen == 0) {
1795
1796 DEBUGLOG(4, "skipping attaching empty dictionary");
1797 } else {
1798 DEBUGLOG(4, "attaching dictionary into context");
1799 cctx->blockState.matchState.dictMatchState = &cdict->matchState;
1800
1801
1802
1803 if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {
1804 cctx->blockState.matchState.window.nextSrc =
1805 cctx->blockState.matchState.window.base + cdictEnd;
1806 ZSTD_window_clear(&cctx->blockState.matchState.window);
1807 }
1808
1809 cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
1810 } }
1811
1812 cctx->dictID = cdict->dictID;
1813 cctx->dictContentSize = cdict->dictContentSize;
1814
1815
1816 ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
1817
1818 return 0;
1819 }
1820
1821 static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
1822 const ZSTD_CDict* cdict,
1823 ZSTD_CCtx_params params,
1824 U64 pledgedSrcSize,
1825 ZSTD_buffered_policy_e zbuff)
1826 {
1827 const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1828
1829 assert(!cdict->matchState.dedicatedDictSearch);
1830
1831 DEBUGLOG(4, "copying dictionary into context");
1832
1833 { unsigned const windowLog = params.cParams.windowLog;
1834 assert(windowLog != 0);
1835
1836 params.cParams = *cdict_cParams;
1837 params.cParams.windowLog = windowLog;
1838 FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1839 ZSTDcrp_leaveDirty, zbuff), "");
1840 assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1841 assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
1842 assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
1843 }
1844
1845 ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
1846
1847
1848 { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
1849 size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
1850
1851 ZSTD_memcpy(cctx->blockState.matchState.hashTable,
1852 cdict->matchState.hashTable,
1853 hSize * sizeof(U32));
1854 ZSTD_memcpy(cctx->blockState.matchState.chainTable,
1855 cdict->matchState.chainTable,
1856 chainSize * sizeof(U32));
1857 }
1858
1859
1860 { int const h3log = cctx->blockState.matchState.hashLog3;
1861 size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
1862 assert(cdict->matchState.hashLog3 == 0);
1863 ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1864 }
1865
1866 ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
1867
1868
1869 { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1870 ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1871 dstMatchState->window = srcMatchState->window;
1872 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1873 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1874 }
1875
1876 cctx->dictID = cdict->dictID;
1877 cctx->dictContentSize = cdict->dictContentSize;
1878
1879
1880 ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
1881
1882 return 0;
1883 }
1884
1885
1886
1887
1888 static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1889 const ZSTD_CDict* cdict,
1890 const ZSTD_CCtx_params* params,
1891 U64 pledgedSrcSize,
1892 ZSTD_buffered_policy_e zbuff)
1893 {
1894
1895 DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)",
1896 (unsigned)pledgedSrcSize);
1897
1898 if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
1899 return ZSTD_resetCCtx_byAttachingCDict(
1900 cctx, cdict, *params, pledgedSrcSize, zbuff);
1901 } else {
1902 return ZSTD_resetCCtx_byCopyingCDict(
1903 cctx, cdict, *params, pledgedSrcSize, zbuff);
1904 }
1905 }
1906
1907
1908
1909
1910
1911
1912
1913
1914 static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1915 const ZSTD_CCtx* srcCCtx,
1916 ZSTD_frameParameters fParams,
1917 U64 pledgedSrcSize,
1918 ZSTD_buffered_policy_e zbuff)
1919 {
1920 DEBUGLOG(5, "ZSTD_copyCCtx_internal");
1921 RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
1922 "Can't copy a ctx that's not in init stage.");
1923
1924 ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
1925 { ZSTD_CCtx_params params = dstCCtx->requestedParams;
1926
1927 params.cParams = srcCCtx->appliedParams.cParams;
1928 params.fParams = fParams;
1929 ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
1930 ZSTDcrp_leaveDirty, zbuff);
1931 assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
1932 assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
1933 assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
1934 assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog);
1935 assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
1936 }
1937
1938 ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);
1939
1940
1941 { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
1942 size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
1943 int const h3log = srcCCtx->blockState.matchState.hashLog3;
1944 size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
1945
1946 ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable,
1947 srcCCtx->blockState.matchState.hashTable,
1948 hSize * sizeof(U32));
1949 ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable,
1950 srcCCtx->blockState.matchState.chainTable,
1951 chainSize * sizeof(U32));
1952 ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3,
1953 srcCCtx->blockState.matchState.hashTable3,
1954 h3Size * sizeof(U32));
1955 }
1956
1957 ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);
1958
1959
1960 {
1961 const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
1962 ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
1963 dstMatchState->window = srcMatchState->window;
1964 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1965 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1966 }
1967 dstCCtx->dictID = srcCCtx->dictID;
1968 dstCCtx->dictContentSize = srcCCtx->dictContentSize;
1969
1970
1971 ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));
1972
1973 return 0;
1974 }
1975
1976
1977
1978
1979
1980
1981 size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
1982 {
1983 ZSTD_frameParameters fParams = { 1 , 0 , 0 };
1984 ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy;
1985 ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);
1986 if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
1987 fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);
1988
1989 return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx,
1990 fParams, pledgedSrcSize,
1991 zbuff);
1992 }
1993
1994
1995 #define ZSTD_ROWSIZE 16
1996
1997
1998
1999
2000
2001
2002 FORCE_INLINE_TEMPLATE void
2003 ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark)
2004 {
2005 int const nbRows = (int)size / ZSTD_ROWSIZE;
2006 int cellNb = 0;
2007 int rowNb;
2008 assert((size & (ZSTD_ROWSIZE-1)) == 0);
2009 assert(size < (1U<<31));
2010
2011
2012 for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
2013 int column;
2014 for (column=0; column<ZSTD_ROWSIZE; column++) {
2015 if (preserveMark) {
2016 U32 const adder = (table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) ? reducerValue : 0;
2017 table[cellNb] += adder;
2018 }
2019 if (table[cellNb] < reducerValue) table[cellNb] = 0;
2020 else table[cellNb] -= reducerValue;
2021 cellNb++;
2022 } }
2023 }
2024
2025 static void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)
2026 {
2027 ZSTD_reduceTable_internal(table, size, reducerValue, 0);
2028 }
2029
2030 static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)
2031 {
2032 ZSTD_reduceTable_internal(table, size, reducerValue, 1);
2033 }
2034
2035
2036
2037 static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
2038 {
2039 { U32 const hSize = (U32)1 << params->cParams.hashLog;
2040 ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
2041 }
2042
2043 if (params->cParams.strategy != ZSTD_fast) {
2044 U32 const chainSize = (U32)1 << params->cParams.chainLog;
2045 if (params->cParams.strategy == ZSTD_btlazy2)
2046 ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
2047 else
2048 ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
2049 }
2050
2051 if (ms->hashLog3) {
2052 U32 const h3Size = (U32)1 << ms->hashLog3;
2053 ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue);
2054 }
2055 }
2056
2057
2058
2059
2060
2061
2062
2063
2064 void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
2065 {
2066 const seqDef* const sequences = seqStorePtr->sequencesStart;
2067 BYTE* const llCodeTable = seqStorePtr->llCode;
2068 BYTE* const ofCodeTable = seqStorePtr->ofCode;
2069 BYTE* const mlCodeTable = seqStorePtr->mlCode;
2070 U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
2071 U32 u;
2072 assert(nbSeq <= seqStorePtr->maxNbSeq);
2073 for (u=0; u<nbSeq; u++) {
2074 U32 const llv = sequences[u].litLength;
2075 U32 const mlv = sequences[u].matchLength;
2076 llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
2077 ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
2078 mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
2079 }
2080 if (seqStorePtr->longLengthID==1)
2081 llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
2082 if (seqStorePtr->longLengthID==2)
2083 mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
2084 }
2085
2086
2087
2088
2089
2090 static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
2091 {
2092 DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize);
2093 return (cctxParams->targetCBlockSize != 0);
2094 }
2095
2096
2097
2098 MEM_STATIC size_t
2099 ZSTD_entropyCompressSequences_internal(seqStore_t* seqStorePtr,
2100 const ZSTD_entropyCTables_t* prevEntropy,
2101 ZSTD_entropyCTables_t* nextEntropy,
2102 const ZSTD_CCtx_params* cctxParams,
2103 void* dst, size_t dstCapacity,
2104 void* entropyWorkspace, size_t entropyWkspSize,
2105 const int bmi2)
2106 {
2107 const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
2108 ZSTD_strategy const strategy = cctxParams->cParams.strategy;
2109 unsigned* count = (unsigned*)entropyWorkspace;
2110 FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
2111 FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
2112 FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
2113 U32 LLtype, Offtype, MLtype;
2114 const seqDef* const sequences = seqStorePtr->sequencesStart;
2115 const BYTE* const ofCodeTable = seqStorePtr->ofCode;
2116 const BYTE* const llCodeTable = seqStorePtr->llCode;
2117 const BYTE* const mlCodeTable = seqStorePtr->mlCode;
2118 BYTE* const ostart = (BYTE*)dst;
2119 BYTE* const oend = ostart + dstCapacity;
2120 BYTE* op = ostart;
2121 size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
2122 BYTE* seqHead;
2123 BYTE* lastNCount = NULL;
2124
2125 entropyWorkspace = count + (MaxSeq + 1);
2126 entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);
2127
2128 DEBUGLOG(4, "ZSTD_entropyCompressSequences_internal (nbSeq=%zu)", nbSeq);
2129 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
2130 assert(entropyWkspSize >= HUF_WORKSPACE_SIZE);
2131
2132
2133 { const BYTE* const literals = seqStorePtr->litStart;
2134 size_t const litSize = (size_t)(seqStorePtr->lit - literals);
2135 size_t const cSize = ZSTD_compressLiterals(
2136 &prevEntropy->huf, &nextEntropy->huf,
2137 cctxParams->cParams.strategy,
2138 ZSTD_disableLiteralsCompression(cctxParams),
2139 op, dstCapacity,
2140 literals, litSize,
2141 entropyWorkspace, entropyWkspSize,
2142 bmi2);
2143 FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
2144 assert(cSize <= dstCapacity);
2145 op += cSize;
2146 }
2147
2148
2149 RETURN_ERROR_IF((oend-op) < 3 + 1 ,
2150 dstSize_tooSmall, "Can't fit seq hdr in output buf!");
2151 if (nbSeq < 128) {
2152 *op++ = (BYTE)nbSeq;
2153 } else if (nbSeq < LONGNBSEQ) {
2154 op[0] = (BYTE)((nbSeq>>8) + 0x80);
2155 op[1] = (BYTE)nbSeq;
2156 op+=2;
2157 } else {
2158 op[0]=0xFF;
2159 MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ));
2160 op+=3;
2161 }
2162 assert(op <= oend);
2163 if (nbSeq==0) {
2164
2165 ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
2166 return (size_t)(op - ostart);
2167 }
2168
2169
2170 seqHead = op++;
2171 assert(op <= oend);
2172
2173
2174 ZSTD_seqToCodes(seqStorePtr);
2175
2176 { unsigned max = MaxLL;
2177 size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);
2178 DEBUGLOG(5, "Building LL table");
2179 nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
2180 LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
2181 count, max, mostFrequent, nbSeq,
2182 LLFSELog, prevEntropy->fse.litlengthCTable,
2183 LL_defaultNorm, LL_defaultNormLog,
2184 ZSTD_defaultAllowed, strategy);
2185 assert(set_basic < set_compressed && set_rle < set_compressed);
2186 assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none));
2187 { size_t const countSize = ZSTD_buildCTable(
2188 op, (size_t)(oend - op),
2189 CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
2190 count, max, llCodeTable, nbSeq,
2191 LL_defaultNorm, LL_defaultNormLog, MaxLL,
2192 prevEntropy->fse.litlengthCTable,
2193 sizeof(prevEntropy->fse.litlengthCTable),
2194 entropyWorkspace, entropyWkspSize);
2195 FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
2196 if (LLtype == set_compressed)
2197 lastNCount = op;
2198 op += countSize;
2199 assert(op <= oend);
2200 } }
2201
2202 { unsigned max = MaxOff;
2203 size_t const mostFrequent = HIST_countFast_wksp(
2204 count, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);
2205
2206 ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
2207 DEBUGLOG(5, "Building OF table");
2208 nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode;
2209 Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode,
2210 count, max, mostFrequent, nbSeq,
2211 OffFSELog, prevEntropy->fse.offcodeCTable,
2212 OF_defaultNorm, OF_defaultNormLog,
2213 defaultPolicy, strategy);
2214 assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none));
2215 { size_t const countSize = ZSTD_buildCTable(
2216 op, (size_t)(oend - op),
2217 CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
2218 count, max, ofCodeTable, nbSeq,
2219 OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
2220 prevEntropy->fse.offcodeCTable,
2221 sizeof(prevEntropy->fse.offcodeCTable),
2222 entropyWorkspace, entropyWkspSize);
2223 FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
2224 if (Offtype == set_compressed)
2225 lastNCount = op;
2226 op += countSize;
2227 assert(op <= oend);
2228 } }
2229
2230 { unsigned max = MaxML;
2231 size_t const mostFrequent = HIST_countFast_wksp(
2232 count, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);
2233 DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
2234 nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
2235 MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
2236 count, max, mostFrequent, nbSeq,
2237 MLFSELog, prevEntropy->fse.matchlengthCTable,
2238 ML_defaultNorm, ML_defaultNormLog,
2239 ZSTD_defaultAllowed, strategy);
2240 assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none));
2241 { size_t const countSize = ZSTD_buildCTable(
2242 op, (size_t)(oend - op),
2243 CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
2244 count, max, mlCodeTable, nbSeq,
2245 ML_defaultNorm, ML_defaultNormLog, MaxML,
2246 prevEntropy->fse.matchlengthCTable,
2247 sizeof(prevEntropy->fse.matchlengthCTable),
2248 entropyWorkspace, entropyWkspSize);
2249 FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
2250 if (MLtype == set_compressed)
2251 lastNCount = op;
2252 op += countSize;
2253 assert(op <= oend);
2254 } }
2255
2256 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
2257
2258 { size_t const bitstreamSize = ZSTD_encodeSequences(
2259 op, (size_t)(oend - op),
2260 CTable_MatchLength, mlCodeTable,
2261 CTable_OffsetBits, ofCodeTable,
2262 CTable_LitLength, llCodeTable,
2263 sequences, nbSeq,
2264 longOffsets, bmi2);
2265 FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
2266 op += bitstreamSize;
2267 assert(op <= oend);
2268
2269
2270
2271
2272
2273
2274
2275
2276 if (lastNCount && (op - lastNCount) < 4) {
2277
2278 assert(op - lastNCount == 3);
2279 DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
2280 "emitting an uncompressed block.");
2281 return 0;
2282 }
2283 }
2284
2285 DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
2286 return (size_t)(op - ostart);
2287 }
2288
2289 MEM_STATIC size_t
2290 ZSTD_entropyCompressSequences(seqStore_t* seqStorePtr,
2291 const ZSTD_entropyCTables_t* prevEntropy,
2292 ZSTD_entropyCTables_t* nextEntropy,
2293 const ZSTD_CCtx_params* cctxParams,
2294 void* dst, size_t dstCapacity,
2295 size_t srcSize,
2296 void* entropyWorkspace, size_t entropyWkspSize,
2297 int bmi2)
2298 {
2299 size_t const cSize = ZSTD_entropyCompressSequences_internal(
2300 seqStorePtr, prevEntropy, nextEntropy, cctxParams,
2301 dst, dstCapacity,
2302 entropyWorkspace, entropyWkspSize, bmi2);
2303 if (cSize == 0) return 0;
2304
2305
2306
2307 if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
2308 return 0;
2309 FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSequences_internal failed");
2310
2311
2312 { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
2313 if (cSize >= maxCSize) return 0;
2314 }
2315 DEBUGLOG(4, "ZSTD_entropyCompressSequences() cSize: %zu\n", cSize);
2316 return cSize;
2317 }
2318
2319
2320
2321
2322 ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode)
2323 {
2324 static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {
2325 { ZSTD_compressBlock_fast ,
2326 ZSTD_compressBlock_fast,
2327 ZSTD_compressBlock_doubleFast,
2328 ZSTD_compressBlock_greedy,
2329 ZSTD_compressBlock_lazy,
2330 ZSTD_compressBlock_lazy2,
2331 ZSTD_compressBlock_btlazy2,
2332 ZSTD_compressBlock_btopt,
2333 ZSTD_compressBlock_btultra,
2334 ZSTD_compressBlock_btultra2 },
2335 { ZSTD_compressBlock_fast_extDict ,
2336 ZSTD_compressBlock_fast_extDict,
2337 ZSTD_compressBlock_doubleFast_extDict,
2338 ZSTD_compressBlock_greedy_extDict,
2339 ZSTD_compressBlock_lazy_extDict,
2340 ZSTD_compressBlock_lazy2_extDict,
2341 ZSTD_compressBlock_btlazy2_extDict,
2342 ZSTD_compressBlock_btopt_extDict,
2343 ZSTD_compressBlock_btultra_extDict,
2344 ZSTD_compressBlock_btultra_extDict },
2345 { ZSTD_compressBlock_fast_dictMatchState ,
2346 ZSTD_compressBlock_fast_dictMatchState,
2347 ZSTD_compressBlock_doubleFast_dictMatchState,
2348 ZSTD_compressBlock_greedy_dictMatchState,
2349 ZSTD_compressBlock_lazy_dictMatchState,
2350 ZSTD_compressBlock_lazy2_dictMatchState,
2351 ZSTD_compressBlock_btlazy2_dictMatchState,
2352 ZSTD_compressBlock_btopt_dictMatchState,
2353 ZSTD_compressBlock_btultra_dictMatchState,
2354 ZSTD_compressBlock_btultra_dictMatchState },
2355 { NULL ,
2356 NULL,
2357 NULL,
2358 ZSTD_compressBlock_greedy_dedicatedDictSearch,
2359 ZSTD_compressBlock_lazy_dedicatedDictSearch,
2360 ZSTD_compressBlock_lazy2_dedicatedDictSearch,
2361 NULL,
2362 NULL,
2363 NULL,
2364 NULL }
2365 };
2366 ZSTD_blockCompressor selectedCompressor;
2367 ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
2368
2369 assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
2370 selectedCompressor = blockCompressor[(int)dictMode][(int)strat];
2371 assert(selectedCompressor != NULL);
2372 return selectedCompressor;
2373 }
2374
2375 static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
2376 const BYTE* anchor, size_t lastLLSize)
2377 {
2378 ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize);
2379 seqStorePtr->lit += lastLLSize;
2380 }
2381
2382 void ZSTD_resetSeqStore(seqStore_t* ssPtr)
2383 {
2384 ssPtr->lit = ssPtr->litStart;
2385 ssPtr->sequences = ssPtr->sequencesStart;
2386 ssPtr->longLengthID = 0;
2387 }
2388
2389 typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
2390
2391 static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
2392 {
2393 ZSTD_matchState_t* const ms = &zc->blockState.matchState;
2394 DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
2395 assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
2396
2397 ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
2398 if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
2399 if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) {
2400 ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize);
2401 } else {
2402 ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
2403 }
2404 return ZSTDbss_noCompress;
2405 }
2406 ZSTD_resetSeqStore(&(zc->seqStore));
2407
2408 ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
2409
2410 ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
2411
2412
2413
2414 assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);
2415
2416
2417 { const BYTE* const base = ms->window.base;
2418 const BYTE* const istart = (const BYTE*)src;
2419 const U32 curr = (U32)(istart-base);
2420 if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1));
2421 if (curr > ms->nextToUpdate + 384)
2422 ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
2423 }
2424
2425
2426 { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
2427 size_t lastLLSize;
2428 { int i;
2429 for (i = 0; i < ZSTD_REP_NUM; ++i)
2430 zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];
2431 }
2432 if (zc->externSeqStore.pos < zc->externSeqStore.size) {
2433 assert(!zc->appliedParams.ldmParams.enableLdm);
2434
2435 lastLLSize =
2436 ZSTD_ldm_blockCompress(&zc->externSeqStore,
2437 ms, &zc->seqStore,
2438 zc->blockState.nextCBlock->rep,
2439 src, srcSize);
2440 assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
2441 } else if (zc->appliedParams.ldmParams.enableLdm) {
2442 rawSeqStore_t ldmSeqStore = kNullRawSeqStore;
2443
2444 ldmSeqStore.seq = zc->ldmSequences;
2445 ldmSeqStore.capacity = zc->maxNbLdmSequences;
2446
2447 FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
2448 &zc->appliedParams.ldmParams,
2449 src, srcSize), "");
2450
2451 lastLLSize =
2452 ZSTD_ldm_blockCompress(&ldmSeqStore,
2453 ms, &zc->seqStore,
2454 zc->blockState.nextCBlock->rep,
2455 src, srcSize);
2456 assert(ldmSeqStore.pos == ldmSeqStore.size);
2457 } else {
2458 ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
2459 ms->ldmSeqStore = NULL;
2460 lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
2461 }
2462 { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
2463 ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
2464 } }
2465 return ZSTDbss_compress;
2466 }
2467
2468 static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
2469 {
2470 const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
2471 const seqDef* seqStoreSeqs = seqStore->sequencesStart;
2472 size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs;
2473 size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart);
2474 size_t literalsRead = 0;
2475 size_t lastLLSize;
2476
2477 ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
2478 size_t i;
2479 repcodes_t updatedRepcodes;
2480
2481 assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
2482
2483 assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1);
2484 ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
2485 for (i = 0; i < seqStoreSeqSize; ++i) {
2486 U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM;
2487 outSeqs[i].litLength = seqStoreSeqs[i].litLength;
2488 outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH;
2489 outSeqs[i].rep = 0;
2490
2491 if (i == seqStore->longLengthPos) {
2492 if (seqStore->longLengthID == 1) {
2493 outSeqs[i].litLength += 0x10000;
2494 } else if (seqStore->longLengthID == 2) {
2495 outSeqs[i].matchLength += 0x10000;
2496 }
2497 }
2498
2499 if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) {
2500
2501 outSeqs[i].rep = seqStoreSeqs[i].offset;
2502 if (outSeqs[i].litLength != 0) {
2503 rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
2504 } else {
2505 if (outSeqs[i].rep == 3) {
2506 rawOffset = updatedRepcodes.rep[0] - 1;
2507 } else {
2508 rawOffset = updatedRepcodes.rep[outSeqs[i].rep];
2509 }
2510 }
2511 }
2512 outSeqs[i].offset = rawOffset;
2513
2514
2515 updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep,
2516 seqStoreSeqs[i].offset - 1,
2517 seqStoreSeqs[i].litLength == 0);
2518 literalsRead += outSeqs[i].litLength;
2519 }
2520
2521
2522
2523
2524 assert(seqStoreLiteralsSize >= literalsRead);
2525 lastLLSize = seqStoreLiteralsSize - literalsRead;
2526 outSeqs[i].litLength = (U32)lastLLSize;
2527 outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0;
2528 seqStoreSeqSize++;
2529 zc->seqCollector.seqIndex += seqStoreSeqSize;
2530 }
2531
2532 size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
2533 size_t outSeqsSize, const void* src, size_t srcSize)
2534 {
2535 const size_t dstCapacity = ZSTD_compressBound(srcSize);
2536 void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
2537 SeqCollector seqCollector;
2538
2539 RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
2540
2541 seqCollector.collectSequences = 1;
2542 seqCollector.seqStart = outSeqs;
2543 seqCollector.seqIndex = 0;
2544 seqCollector.maxSequences = outSeqsSize;
2545 zc->seqCollector = seqCollector;
2546
2547 ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
2548 ZSTD_customFree(dst, ZSTD_defaultCMem);
2549 return zc->seqCollector.seqIndex;
2550 }
2551
2552 size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) {
2553 size_t in = 0;
2554 size_t out = 0;
2555 for (; in < seqsSize; ++in) {
2556 if (sequences[in].offset == 0 && sequences[in].matchLength == 0) {
2557 if (in != seqsSize - 1) {
2558 sequences[in+1].litLength += sequences[in].litLength;
2559 }
2560 } else {
2561 sequences[out] = sequences[in];
2562 ++out;
2563 }
2564 }
2565 return out;
2566 }
2567
2568
2569 static int ZSTD_isRLE(const BYTE* src, size_t length) {
2570 const BYTE* ip = src;
2571 const BYTE value = ip[0];
2572 const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL);
2573 const size_t unrollSize = sizeof(size_t) * 4;
2574 const size_t unrollMask = unrollSize - 1;
2575 const size_t prefixLength = length & unrollMask;
2576 size_t i;
2577 size_t u;
2578 if (length == 1) return 1;
2579
2580 if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) {
2581 return 0;
2582 }
2583 for (i = prefixLength; i != length; i += unrollSize) {
2584 for (u = 0; u < unrollSize; u += sizeof(size_t)) {
2585 if (MEM_readST(ip + i + u) != valueST) {
2586 return 0;
2587 }
2588 }
2589 }
2590 return 1;
2591 }
2592
2593
2594
2595
2596
2597 static int ZSTD_maybeRLE(seqStore_t const* seqStore)
2598 {
2599 size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);
2600 size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart);
2601
2602 return nbSeqs < 4 && nbLits < 10;
2603 }
2604
2605 static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc)
2606 {
2607 ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
2608 zc->blockState.prevCBlock = zc->blockState.nextCBlock;
2609 zc->blockState.nextCBlock = tmp;
2610 }
2611
2612 static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2613 void* dst, size_t dstCapacity,
2614 const void* src, size_t srcSize, U32 frame)
2615 {
2616
2617
2618
2619
2620 const U32 rleMaxLength = 25;
2621 size_t cSize;
2622 const BYTE* ip = (const BYTE*)src;
2623 BYTE* op = (BYTE*)dst;
2624 DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
2625 (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
2626 (unsigned)zc->blockState.matchState.nextToUpdate);
2627
2628 { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
2629 FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
2630 if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
2631 }
2632
2633 if (zc->seqCollector.collectSequences) {
2634 ZSTD_copyBlockSequences(zc);
2635 ZSTD_confirmRepcodesAndEntropyTables(zc);
2636 return 0;
2637 }
2638
2639
2640 cSize = ZSTD_entropyCompressSequences(&zc->seqStore,
2641 &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
2642 &zc->appliedParams,
2643 dst, dstCapacity,
2644 srcSize,
2645 zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE ,
2646 zc->bmi2);
2647
2648 if (zc->seqCollector.collectSequences) {
2649 ZSTD_copyBlockSequences(zc);
2650 return 0;
2651 }
2652
2653
2654 if (frame &&
2655
2656
2657
2658
2659 !zc->isFirstBlock &&
2660 cSize < rleMaxLength &&
2661 ZSTD_isRLE(ip, srcSize))
2662 {
2663 cSize = 1;
2664 op[0] = ip[0];
2665 }
2666
2667 out:
2668 if (!ZSTD_isError(cSize) && cSize > 1) {
2669 ZSTD_confirmRepcodesAndEntropyTables(zc);
2670 }
2671
2672
2673
2674
2675 if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
2676 zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
2677
2678 return cSize;
2679 }
2680
2681 static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,
2682 void* dst, size_t dstCapacity,
2683 const void* src, size_t srcSize,
2684 const size_t bss, U32 lastBlock)
2685 {
2686 DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()");
2687 if (bss == ZSTDbss_compress) {
2688 if (
2689
2690
2691
2692 !zc->isFirstBlock &&
2693 ZSTD_maybeRLE(&zc->seqStore) &&
2694 ZSTD_isRLE((BYTE const*)src, srcSize))
2695 {
2696 return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock);
2697 }
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716 {
2717 size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);
2718 if (cSize != ERROR(dstSize_tooSmall)) {
2719 size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);
2720 FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed");
2721 if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {
2722 ZSTD_confirmRepcodesAndEntropyTables(zc);
2723 return cSize;
2724 }
2725 }
2726 }
2727 }
2728
2729 DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()");
2730
2731
2732
2733 return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);
2734 }
2735
2736 static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,
2737 void* dst, size_t dstCapacity,
2738 const void* src, size_t srcSize,
2739 U32 lastBlock)
2740 {
2741 size_t cSize = 0;
2742 const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
2743 DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)",
2744 (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize);
2745 FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
2746
2747 cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock);
2748 FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize_body failed");
2749
2750 if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
2751 zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
2752
2753 return cSize;
2754 }
2755
2756 static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
2757 ZSTD_cwksp* ws,
2758 ZSTD_CCtx_params const* params,
2759 void const* ip,
2760 void const* iend)
2761 {
2762 if (ZSTD_window_needOverflowCorrection(ms->window, iend)) {
2763 U32 const maxDist = (U32)1 << params->cParams.windowLog;
2764 U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
2765 U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
2766 ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2767 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2768 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2769 ZSTD_cwksp_mark_tables_dirty(ws);
2770 ZSTD_reduceIndex(ms, params, correction);
2771 ZSTD_cwksp_mark_tables_clean(ws);
2772 if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2773 else ms->nextToUpdate -= correction;
2774
2775 ms->loadedDictEnd = 0;
2776 ms->dictMatchState = NULL;
2777 }
2778 }
2779
2780
2781
2782
2783
2784
2785
2786
2787 static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2788 void* dst, size_t dstCapacity,
2789 const void* src, size_t srcSize,
2790 U32 lastFrameChunk)
2791 {
2792 size_t blockSize = cctx->blockSize;
2793 size_t remaining = srcSize;
2794 const BYTE* ip = (const BYTE*)src;
2795 BYTE* const ostart = (BYTE*)dst;
2796 BYTE* op = ostart;
2797 U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
2798
2799 assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
2800
2801 DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
2802 if (cctx->appliedParams.fParams.checksumFlag && srcSize)
2803 xxh64_update(&cctx->xxhState, src, srcSize);
2804
2805 while (remaining) {
2806 ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
2807 U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
2808
2809 RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
2810 dstSize_tooSmall,
2811 "not enough space to store compressed block");
2812 if (remaining < blockSize) blockSize = remaining;
2813
2814 ZSTD_overflowCorrectIfNeeded(
2815 ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize);
2816 ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2817
2818
2819 if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
2820
2821 { size_t cSize;
2822 if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) {
2823 cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock);
2824 FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed");
2825 assert(cSize > 0);
2826 assert(cSize <= blockSize + ZSTD_blockHeaderSize);
2827 } else {
2828 cSize = ZSTD_compressBlock_internal(cctx,
2829 op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
2830 ip, blockSize, 1 );
2831 FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_internal failed");
2832
2833 if (cSize == 0) {
2834 cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
2835 FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
2836 } else {
2837 U32 const cBlockHeader = cSize == 1 ?
2838 lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
2839 lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
2840 MEM_writeLE24(op, cBlockHeader);
2841 cSize += ZSTD_blockHeaderSize;
2842 }
2843 }
2844
2845
2846 ip += blockSize;
2847 assert(remaining >= blockSize);
2848 remaining -= blockSize;
2849 op += cSize;
2850 assert(dstCapacity >= cSize);
2851 dstCapacity -= cSize;
2852 cctx->isFirstBlock = 0;
2853 DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
2854 (unsigned)cSize);
2855 } }
2856
2857 if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
2858 return (size_t)(op-ostart);
2859 }
2860
2861
2862 static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2863 const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID)
2864 { BYTE* const op = (BYTE*)dst;
2865 U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536);
2866 U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength;
2867 U32 const checksumFlag = params->fParams.checksumFlag>0;
2868 U32 const windowSize = (U32)1 << params->cParams.windowLog;
2869 U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
2870 BYTE const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2871 U32 const fcsCode = params->fParams.contentSizeFlag ?
2872 (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0;
2873 BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2874 size_t pos=0;
2875
2876 assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
2877 RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall,
2878 "dst buf is too small to fit worst-case frame header size.");
2879 DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2880 !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
2881 if (params->format == ZSTD_f_zstd1) {
2882 MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2883 pos = 4;
2884 }
2885 op[pos++] = frameHeaderDescriptionByte;
2886 if (!singleSegment) op[pos++] = windowLogByte;
2887 switch(dictIDSizeCode)
2888 {
2889 default:
2890 assert(0);
2891 ZSTD_FALLTHROUGH;
2892 case 0 : break;
2893 case 1 : op[pos] = (BYTE)(dictID); pos++; break;
2894 case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break;
2895 case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break;
2896 }
2897 switch(fcsCode)
2898 {
2899 default:
2900 assert(0);
2901 ZSTD_FALLTHROUGH;
2902 case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break;
2903 case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;
2904 case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;
2905 case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break;
2906 }
2907 return pos;
2908 }
2909
2910
2911
2912
2913
2914
2915
2916 size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
2917 const void* src, size_t srcSize, unsigned magicVariant) {
2918 BYTE* op = (BYTE*)dst;
2919 RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE ,
2920 dstSize_tooSmall, "Not enough room for skippable frame");
2921 RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, "Src size too large for skippable frame");
2922 RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, "Skippable frame magic number variant not supported");
2923
2924 MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant));
2925 MEM_writeLE32(op+4, (U32)srcSize);
2926 ZSTD_memcpy(op+8, src, srcSize);
2927 return srcSize + ZSTD_SKIPPABLEHEADERSIZE;
2928 }
2929
2930
2931
2932
2933
2934
2935 size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
2936 {
2937 RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,
2938 "dst buf is too small to write frame trailer empty block.");
2939 { U32 const cBlockHeader24 = 1 + (((U32)bt_raw)<<1);
2940 MEM_writeLE24(dst, cBlockHeader24);
2941 return ZSTD_blockHeaderSize;
2942 }
2943 }
2944
2945 size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
2946 {
2947 RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
2948 "wrong cctx stage");
2949 RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
2950 parameter_unsupported,
2951 "incompatible with ldm");
2952 cctx->externSeqStore.seq = seq;
2953 cctx->externSeqStore.size = nbSeq;
2954 cctx->externSeqStore.capacity = nbSeq;
2955 cctx->externSeqStore.pos = 0;
2956 cctx->externSeqStore.posInSequence = 0;
2957 return 0;
2958 }
2959
2960
2961 static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2962 void* dst, size_t dstCapacity,
2963 const void* src, size_t srcSize,
2964 U32 frame, U32 lastFrameChunk)
2965 {
2966 ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
2967 size_t fhSize = 0;
2968
2969 DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
2970 cctx->stage, (unsigned)srcSize);
2971 RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
2972 "missing init (ZSTD_compressBegin)");
2973
2974 if (frame && (cctx->stage==ZSTDcs_init)) {
2975 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,
2976 cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
2977 FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
2978 assert(fhSize <= dstCapacity);
2979 dstCapacity -= fhSize;
2980 dst = (char*)dst + fhSize;
2981 cctx->stage = ZSTDcs_ongoing;
2982 }
2983
2984 if (!srcSize) return fhSize;
2985
2986 if (!ZSTD_window_update(&ms->window, src, srcSize)) {
2987 ms->nextToUpdate = ms->window.dictLimit;
2988 }
2989 if (cctx->appliedParams.ldmParams.enableLdm) {
2990 ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
2991 }
2992
2993 if (!frame) {
2994
2995 ZSTD_overflowCorrectIfNeeded(
2996 ms, &cctx->workspace, &cctx->appliedParams,
2997 src, (BYTE const*)src + srcSize);
2998 }
2999
3000 DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
3001 { size_t const cSize = frame ?
3002 ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
3003 ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 );
3004 FORWARD_IF_ERROR(cSize, "%s", frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed");
3005 cctx->consumedSrcSize += srcSize;
3006 cctx->producedCSize += (cSize + fhSize);
3007 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
3008 if (cctx->pledgedSrcSizePlusOne != 0) {
3009 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
3010 RETURN_ERROR_IF(
3011 cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
3012 srcSize_wrong,
3013 "error : pledgedSrcSize = %u, while realSrcSize >= %u",
3014 (unsigned)cctx->pledgedSrcSizePlusOne-1,
3015 (unsigned)cctx->consumedSrcSize);
3016 }
3017 return cSize + fhSize;
3018 }
3019 }
3020
3021 size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
3022 void* dst, size_t dstCapacity,
3023 const void* src, size_t srcSize)
3024 {
3025 DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (unsigned)srcSize);
3026 return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 , 0 );
3027 }
3028
3029
3030 size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
3031 {
3032 ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams;
3033 assert(!ZSTD_checkCParams(cParams));
3034 return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
3035 }
3036
3037 size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
3038 {
3039 DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize);
3040 { size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
3041 RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, "input is larger than a block"); }
3042
3043 return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 , 0 );
3044 }
3045
3046
3047
3048
3049 static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
3050 ldmState_t* ls,
3051 ZSTD_cwksp* ws,
3052 ZSTD_CCtx_params const* params,
3053 const void* src, size_t srcSize,
3054 ZSTD_dictTableLoadMethod_e dtlm)
3055 {
3056 const BYTE* ip = (const BYTE*) src;
3057 const BYTE* const iend = ip + srcSize;
3058
3059 ZSTD_window_update(&ms->window, src, srcSize);
3060 ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
3061
3062 if (params->ldmParams.enableLdm && ls != NULL) {
3063 ZSTD_window_update(&ls->window, src, srcSize);
3064 ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base);
3065 }
3066
3067
3068 ZSTD_assertEqualCParams(params->cParams, ms->cParams);
3069
3070 if (srcSize <= HASH_READ_SIZE) return 0;
3071
3072 while (iend - ip > HASH_READ_SIZE) {
3073 size_t const remaining = (size_t)(iend - ip);
3074 size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX);
3075 const BYTE* const ichunk = ip + chunk;
3076
3077 ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk);
3078
3079 if (params->ldmParams.enableLdm && ls != NULL)
3080 ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, ¶ms->ldmParams);
3081
3082 switch(params->cParams.strategy)
3083 {
3084 case ZSTD_fast:
3085 ZSTD_fillHashTable(ms, ichunk, dtlm);
3086 break;
3087 case ZSTD_dfast:
3088 ZSTD_fillDoubleHashTable(ms, ichunk, dtlm);
3089 break;
3090
3091 case ZSTD_greedy:
3092 case ZSTD_lazy:
3093 case ZSTD_lazy2:
3094 if (chunk >= HASH_READ_SIZE && ms->dedicatedDictSearch) {
3095 assert(chunk == remaining);
3096 ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, ichunk-HASH_READ_SIZE);
3097 } else if (chunk >= HASH_READ_SIZE) {
3098 ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
3099 }
3100 break;
3101
3102 case ZSTD_btlazy2:
3103 case ZSTD_btopt:
3104 case ZSTD_btultra:
3105 case ZSTD_btultra2:
3106 if (chunk >= HASH_READ_SIZE)
3107 ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk);
3108 break;
3109
3110 default:
3111 assert(0);
3112 }
3113
3114 ip = ichunk;
3115 }
3116
3117 ms->nextToUpdate = (U32)(iend - ms->window.base);
3118 return 0;
3119 }
3120
3121
3122
3123
3124
3125
3126 static FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue)
3127 {
3128 U32 s;
3129 if (dictMaxSymbolValue < maxSymbolValue) {
3130 return FSE_repeat_check;
3131 }
3132 for (s = 0; s <= maxSymbolValue; ++s) {
3133 if (normalizedCounter[s] == 0) {
3134 return FSE_repeat_check;
3135 }
3136 }
3137 return FSE_repeat_valid;
3138 }
3139
3140 size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
3141 const void* const dict, size_t dictSize)
3142 {
3143 short offcodeNCount[MaxOff+1];
3144 unsigned offcodeMaxValue = MaxOff;
3145 const BYTE* dictPtr = (const BYTE*)dict;
3146 const BYTE* const dictEnd = dictPtr + dictSize;
3147 dictPtr += 8;
3148 bs->entropy.huf.repeatMode = HUF_repeat_check;
3149
3150 { unsigned maxSymbolValue = 255;
3151 unsigned hasZeroWeights = 1;
3152 size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr,
3153 dictEnd-dictPtr, &hasZeroWeights);
3154
3155
3156
3157 if (!hasZeroWeights)
3158 bs->entropy.huf.repeatMode = HUF_repeat_valid;
3159
3160 RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, "");
3161 RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, "");
3162 dictPtr += hufHeaderSize;
3163 }
3164
3165 { unsigned offcodeLog;
3166 size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
3167 RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
3168 RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
3169
3170 RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3171 bs->entropy.fse.offcodeCTable,
3172 offcodeNCount, MaxOff, offcodeLog,
3173 workspace, HUF_WORKSPACE_SIZE)),
3174 dictionary_corrupted, "");
3175
3176 dictPtr += offcodeHeaderSize;
3177 }
3178
3179 { short matchlengthNCount[MaxML+1];
3180 unsigned matchlengthMaxValue = MaxML, matchlengthLog;
3181 size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
3182 RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
3183 RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
3184 RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3185 bs->entropy.fse.matchlengthCTable,
3186 matchlengthNCount, matchlengthMaxValue, matchlengthLog,
3187 workspace, HUF_WORKSPACE_SIZE)),
3188 dictionary_corrupted, "");
3189 bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML);
3190 dictPtr += matchlengthHeaderSize;
3191 }
3192
3193 { short litlengthNCount[MaxLL+1];
3194 unsigned litlengthMaxValue = MaxLL, litlengthLog;
3195 size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
3196 RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
3197 RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
3198 RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3199 bs->entropy.fse.litlengthCTable,
3200 litlengthNCount, litlengthMaxValue, litlengthLog,
3201 workspace, HUF_WORKSPACE_SIZE)),
3202 dictionary_corrupted, "");
3203 bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL);
3204 dictPtr += litlengthHeaderSize;
3205 }
3206
3207 RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
3208 bs->rep[0] = MEM_readLE32(dictPtr+0);
3209 bs->rep[1] = MEM_readLE32(dictPtr+4);
3210 bs->rep[2] = MEM_readLE32(dictPtr+8);
3211 dictPtr += 12;
3212
3213 { size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
3214 U32 offcodeMax = MaxOff;
3215 if (dictContentSize <= ((U32)-1) - 128 KB) {
3216 U32 const maxOffset = (U32)dictContentSize + 128 KB;
3217 offcodeMax = ZSTD_highbit32(maxOffset);
3218 }
3219
3220 bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff));
3221
3222
3223 { U32 u;
3224 for (u=0; u<3; u++) {
3225 RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
3226 RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
3227 } } }
3228
3229 return dictPtr - (const BYTE*)dict;
3230 }
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241 static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
3242 ZSTD_matchState_t* ms,
3243 ZSTD_cwksp* ws,
3244 ZSTD_CCtx_params const* params,
3245 const void* dict, size_t dictSize,
3246 ZSTD_dictTableLoadMethod_e dtlm,
3247 void* workspace)
3248 {
3249 const BYTE* dictPtr = (const BYTE*)dict;
3250 const BYTE* const dictEnd = dictPtr + dictSize;
3251 size_t dictID;
3252 size_t eSize;
3253
3254 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
3255 assert(dictSize >= 8);
3256 assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
3257
3258 dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 );
3259 eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize);
3260 FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed");
3261 dictPtr += eSize;
3262
3263 {
3264 size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
3265 FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
3266 ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
3267 }
3268 return dictID;
3269 }
3270
3271
3272
3273 static size_t
3274 ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
3275 ZSTD_matchState_t* ms,
3276 ldmState_t* ls,
3277 ZSTD_cwksp* ws,
3278 const ZSTD_CCtx_params* params,
3279 const void* dict, size_t dictSize,
3280 ZSTD_dictContentType_e dictContentType,
3281 ZSTD_dictTableLoadMethod_e dtlm,
3282 void* workspace)
3283 {
3284 DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
3285 if ((dict==NULL) || (dictSize<8)) {
3286 RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
3287 return 0;
3288 }
3289
3290 ZSTD_reset_compressedBlockState(bs);
3291
3292
3293 if (dictContentType == ZSTD_dct_rawContent)
3294 return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm);
3295
3296 if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
3297 if (dictContentType == ZSTD_dct_auto) {
3298 DEBUGLOG(4, "raw content dictionary detected");
3299 return ZSTD_loadDictionaryContent(
3300 ms, ls, ws, params, dict, dictSize, dtlm);
3301 }
3302 RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
3303 assert(0);
3304 }
3305
3306
3307 return ZSTD_loadZstdDictionary(
3308 bs, ms, ws, params, dict, dictSize, dtlm, workspace);
3309 }
3310
3311 #define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
3312 #define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL)
3313
3314
3315
3316 static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
3317 const void* dict, size_t dictSize,
3318 ZSTD_dictContentType_e dictContentType,
3319 ZSTD_dictTableLoadMethod_e dtlm,
3320 const ZSTD_CDict* cdict,
3321 const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
3322 ZSTD_buffered_policy_e zbuff)
3323 {
3324 DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
3325
3326 assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
3327 assert(!((dict) && (cdict)));
3328 if ( (cdict)
3329 && (cdict->dictContentSize > 0)
3330 && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
3331 || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
3332 || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
3333 || cdict->compressionLevel == 0)
3334 && (params->attachDictPref != ZSTD_dictForceLoad) ) {
3335 return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
3336 }
3337
3338 FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize,
3339 ZSTDcrp_makeClean, zbuff) , "");
3340 { size_t const dictID = cdict ?
3341 ZSTD_compress_insertDictionary(
3342 cctx->blockState.prevCBlock, &cctx->blockState.matchState,
3343 &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,
3344 cdict->dictContentSize, cdict->dictContentType, dtlm,
3345 cctx->entropyWorkspace)
3346 : ZSTD_compress_insertDictionary(
3347 cctx->blockState.prevCBlock, &cctx->blockState.matchState,
3348 &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize,
3349 dictContentType, dtlm, cctx->entropyWorkspace);
3350 FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
3351 assert(dictID <= UINT_MAX);
3352 cctx->dictID = (U32)dictID;
3353 cctx->dictContentSize = cdict ? cdict->dictContentSize : dictSize;
3354 }
3355 return 0;
3356 }
3357
3358 size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
3359 const void* dict, size_t dictSize,
3360 ZSTD_dictContentType_e dictContentType,
3361 ZSTD_dictTableLoadMethod_e dtlm,
3362 const ZSTD_CDict* cdict,
3363 const ZSTD_CCtx_params* params,
3364 unsigned long long pledgedSrcSize)
3365 {
3366 DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog);
3367
3368 FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , "");
3369 return ZSTD_compressBegin_internal(cctx,
3370 dict, dictSize, dictContentType, dtlm,
3371 cdict,
3372 params, pledgedSrcSize,
3373 ZSTDb_not_buffered);
3374 }
3375
3376
3377
3378 size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
3379 const void* dict, size_t dictSize,
3380 ZSTD_parameters params, unsigned long long pledgedSrcSize)
3381 {
3382 ZSTD_CCtx_params cctxParams;
3383 ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL);
3384 return ZSTD_compressBegin_advanced_internal(cctx,
3385 dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
3386 NULL ,
3387 &cctxParams, pledgedSrcSize);
3388 }
3389
3390 size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
3391 {
3392 ZSTD_CCtx_params cctxParams;
3393 {
3394 ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict);
3395 ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel);
3396 }
3397 DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
3398 return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3399 &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
3400 }
3401
3402 size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
3403 {
3404 return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
3405 }
3406
3407
3408
3409
3410
3411 static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
3412 {
3413 BYTE* const ostart = (BYTE*)dst;
3414 BYTE* op = ostart;
3415 size_t fhSize = 0;
3416
3417 DEBUGLOG(4, "ZSTD_writeEpilogue");
3418 RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
3419
3420
3421 if (cctx->stage == ZSTDcs_init) {
3422 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
3423 FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
3424 dstCapacity -= fhSize;
3425 op += fhSize;
3426 cctx->stage = ZSTDcs_ongoing;
3427 }
3428
3429 if (cctx->stage != ZSTDcs_ending) {
3430
3431 U32 const cBlockHeader24 = 1 + (((U32)bt_raw)<<1) + 0;
3432 RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue");
3433 MEM_writeLE32(op, cBlockHeader24);
3434 op += ZSTD_blockHeaderSize;
3435 dstCapacity -= ZSTD_blockHeaderSize;
3436 }
3437
3438 if (cctx->appliedParams.fParams.checksumFlag) {
3439 U32 const checksum = (U32) xxh64_digest(&cctx->xxhState);
3440 RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
3441 DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
3442 MEM_writeLE32(op, checksum);
3443 op += 4;
3444 }
3445
3446 cctx->stage = ZSTDcs_created;
3447 return op-ostart;
3448 }
3449
3450 void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)
3451 {
3452 (void)cctx;
3453 (void)extraCSize;
3454 }
3455
3456 size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
3457 void* dst, size_t dstCapacity,
3458 const void* src, size_t srcSize)
3459 {
3460 size_t endResult;
3461 size_t const cSize = ZSTD_compressContinue_internal(cctx,
3462 dst, dstCapacity, src, srcSize,
3463 1 , 1 );
3464 FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed");
3465 endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
3466 FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed");
3467 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
3468 if (cctx->pledgedSrcSizePlusOne != 0) {
3469 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
3470 DEBUGLOG(4, "end of frame : controlling src size");
3471 RETURN_ERROR_IF(
3472 cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
3473 srcSize_wrong,
3474 "error : pledgedSrcSize = %u, while realSrcSize = %u",
3475 (unsigned)cctx->pledgedSrcSizePlusOne-1,
3476 (unsigned)cctx->consumedSrcSize);
3477 }
3478 ZSTD_CCtx_trace(cctx, endResult);
3479 return cSize + endResult;
3480 }
3481
3482 size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
3483 void* dst, size_t dstCapacity,
3484 const void* src, size_t srcSize,
3485 const void* dict,size_t dictSize,
3486 ZSTD_parameters params)
3487 {
3488 ZSTD_CCtx_params cctxParams;
3489 DEBUGLOG(4, "ZSTD_compress_advanced");
3490 FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
3491 ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL);
3492 return ZSTD_compress_advanced_internal(cctx,
3493 dst, dstCapacity,
3494 src, srcSize,
3495 dict, dictSize,
3496 &cctxParams);
3497 }
3498
3499
3500 size_t ZSTD_compress_advanced_internal(
3501 ZSTD_CCtx* cctx,
3502 void* dst, size_t dstCapacity,
3503 const void* src, size_t srcSize,
3504 const void* dict,size_t dictSize,
3505 const ZSTD_CCtx_params* params)
3506 {
3507 DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
3508 FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
3509 dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3510 params, srcSize, ZSTDb_not_buffered) , "");
3511 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3512 }
3513
3514 size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
3515 void* dst, size_t dstCapacity,
3516 const void* src, size_t srcSize,
3517 const void* dict, size_t dictSize,
3518 int compressionLevel)
3519 {
3520 ZSTD_CCtx_params cctxParams;
3521 {
3522 ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict);
3523 assert(params.fParams.contentSizeFlag == 1);
3524 ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel);
3525 }
3526 DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize);
3527 return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams);
3528 }
3529
3530 size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
3531 void* dst, size_t dstCapacity,
3532 const void* src, size_t srcSize,
3533 int compressionLevel)
3534 {
3535 DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (unsigned)srcSize);
3536 assert(cctx != NULL);
3537 return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
3538 }
3539
3540 size_t ZSTD_compress(void* dst, size_t dstCapacity,
3541 const void* src, size_t srcSize,
3542 int compressionLevel)
3543 {
3544 size_t result;
3545 ZSTD_CCtx* cctx = ZSTD_createCCtx();
3546 RETURN_ERROR_IF(!cctx, memory_allocation, "ZSTD_createCCtx failed");
3547 result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);
3548 ZSTD_freeCCtx(cctx);
3549 return result;
3550 }
3551
3552
3553
3554
3555
3556
3557 size_t ZSTD_estimateCDictSize_advanced(
3558 size_t dictSize, ZSTD_compressionParameters cParams,
3559 ZSTD_dictLoadMethod_e dictLoadMethod)
3560 {
3561 DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
3562 return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
3563 + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
3564 + ZSTD_sizeof_matchState(&cParams, 0)
3565 + (dictLoadMethod == ZSTD_dlm_byRef ? 0
3566 : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));
3567 }
3568
3569 size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
3570 {
3571 ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
3572 return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
3573 }
3574
3575 size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
3576 {
3577 if (cdict==NULL) return 0;
3578 DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict));
3579
3580 return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict))
3581 + ZSTD_cwksp_sizeof(&cdict->workspace);
3582 }
3583
3584 static size_t ZSTD_initCDict_internal(
3585 ZSTD_CDict* cdict,
3586 const void* dictBuffer, size_t dictSize,
3587 ZSTD_dictLoadMethod_e dictLoadMethod,
3588 ZSTD_dictContentType_e dictContentType,
3589 ZSTD_CCtx_params params)
3590 {
3591 DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType);
3592 assert(!ZSTD_checkCParams(params.cParams));
3593 cdict->matchState.cParams = params.cParams;
3594 cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch;
3595 if (cdict->matchState.dedicatedDictSearch && dictSize > ZSTD_CHUNKSIZE_MAX) {
3596 cdict->matchState.dedicatedDictSearch = 0;
3597 }
3598 if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
3599 cdict->dictContent = dictBuffer;
3600 } else {
3601 void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));
3602 RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!");
3603 cdict->dictContent = internalBuffer;
3604 ZSTD_memcpy(internalBuffer, dictBuffer, dictSize);
3605 }
3606 cdict->dictContentSize = dictSize;
3607 cdict->dictContentType = dictContentType;
3608
3609 cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
3610
3611
3612
3613 ZSTD_reset_compressedBlockState(&cdict->cBlockState);
3614 FORWARD_IF_ERROR(ZSTD_reset_matchState(
3615 &cdict->matchState,
3616 &cdict->workspace,
3617 ¶ms.cParams,
3618 ZSTDcrp_makeClean,
3619 ZSTDirp_reset,
3620 ZSTD_resetTarget_CDict), "");
3621
3622
3623
3624 { params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
3625 params.fParams.contentSizeFlag = 1;
3626 { size_t const dictID = ZSTD_compress_insertDictionary(
3627 &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,
3628 ¶ms, cdict->dictContent, cdict->dictContentSize,
3629 dictContentType, ZSTD_dtlm_full, cdict->entropyWorkspace);
3630 FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
3631 assert(dictID <= (size_t)(U32)-1);
3632 cdict->dictID = (U32)dictID;
3633 }
3634 }
3635
3636 return 0;
3637 }
3638
3639 static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize,
3640 ZSTD_dictLoadMethod_e dictLoadMethod,
3641 ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
3642 {
3643 if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
3644
3645 { size_t const workspaceSize =
3646 ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +
3647 ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) +
3648 ZSTD_sizeof_matchState(&cParams, 0) +
3649 (dictLoadMethod == ZSTD_dlm_byRef ? 0
3650 : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));
3651 void* const workspace = ZSTD_customMalloc(workspaceSize, customMem);
3652 ZSTD_cwksp ws;
3653 ZSTD_CDict* cdict;
3654
3655 if (!workspace) {
3656 ZSTD_customFree(workspace, customMem);
3657 return NULL;
3658 }
3659
3660 ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc);
3661
3662 cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
3663 assert(cdict != NULL);
3664 ZSTD_cwksp_move(&cdict->workspace, &ws);
3665 cdict->customMem = customMem;
3666 cdict->compressionLevel = ZSTD_NO_CLEVEL;
3667
3668 return cdict;
3669 }
3670 }
3671
3672 ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3673 ZSTD_dictLoadMethod_e dictLoadMethod,
3674 ZSTD_dictContentType_e dictContentType,
3675 ZSTD_compressionParameters cParams,
3676 ZSTD_customMem customMem)
3677 {
3678 ZSTD_CCtx_params cctxParams;
3679 ZSTD_memset(&cctxParams, 0, sizeof(cctxParams));
3680 ZSTD_CCtxParams_init(&cctxParams, 0);
3681 cctxParams.cParams = cParams;
3682 cctxParams.customMem = customMem;
3683 return ZSTD_createCDict_advanced2(
3684 dictBuffer, dictSize,
3685 dictLoadMethod, dictContentType,
3686 &cctxParams, customMem);
3687 }
3688
3689 ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
3690 const void* dict, size_t dictSize,
3691 ZSTD_dictLoadMethod_e dictLoadMethod,
3692 ZSTD_dictContentType_e dictContentType,
3693 const ZSTD_CCtx_params* originalCctxParams,
3694 ZSTD_customMem customMem)
3695 {
3696 ZSTD_CCtx_params cctxParams = *originalCctxParams;
3697 ZSTD_compressionParameters cParams;
3698 ZSTD_CDict* cdict;
3699
3700 DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType);
3701 if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
3702
3703 if (cctxParams.enableDedicatedDictSearch) {
3704 cParams = ZSTD_dedicatedDictSearch_getCParams(
3705 cctxParams.compressionLevel, dictSize);
3706 ZSTD_overrideCParams(&cParams, &cctxParams.cParams);
3707 } else {
3708 cParams = ZSTD_getCParamsFromCCtxParams(
3709 &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
3710 }
3711
3712 if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) {
3713
3714 cctxParams.enableDedicatedDictSearch = 0;
3715 cParams = ZSTD_getCParamsFromCCtxParams(
3716 &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
3717 }
3718
3719 cctxParams.cParams = cParams;
3720
3721 cdict = ZSTD_createCDict_advanced_internal(dictSize,
3722 dictLoadMethod, cctxParams.cParams,
3723 customMem);
3724
3725 if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3726 dict, dictSize,
3727 dictLoadMethod, dictContentType,
3728 cctxParams) )) {
3729 ZSTD_freeCDict(cdict);
3730 return NULL;
3731 }
3732
3733 return cdict;
3734 }
3735
3736 ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
3737 {
3738 ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
3739 ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
3740 ZSTD_dlm_byCopy, ZSTD_dct_auto,
3741 cParams, ZSTD_defaultCMem);
3742 if (cdict)
3743 cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
3744 return cdict;
3745 }
3746
3747 ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
3748 {
3749 ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
3750 ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
3751 ZSTD_dlm_byRef, ZSTD_dct_auto,
3752 cParams, ZSTD_defaultCMem);
3753 if (cdict)
3754 cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
3755 return cdict;
3756 }
3757
3758 size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
3759 {
3760 if (cdict==NULL) return 0;
3761 { ZSTD_customMem const cMem = cdict->customMem;
3762 int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);
3763 ZSTD_cwksp_free(&cdict->workspace, cMem);
3764 if (!cdictInWorkspace) {
3765 ZSTD_customFree(cdict, cMem);
3766 }
3767 return 0;
3768 }
3769 }
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784 const ZSTD_CDict* ZSTD_initStaticCDict(
3785 void* workspace, size_t workspaceSize,
3786 const void* dict, size_t dictSize,
3787 ZSTD_dictLoadMethod_e dictLoadMethod,
3788 ZSTD_dictContentType_e dictContentType,
3789 ZSTD_compressionParameters cParams)
3790 {
3791 size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, 0);
3792 size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
3793 + (dictLoadMethod == ZSTD_dlm_byRef ? 0
3794 : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))))
3795 + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
3796 + matchStateSize;
3797 ZSTD_CDict* cdict;
3798 ZSTD_CCtx_params params;
3799
3800 if ((size_t)workspace & 7) return NULL;
3801
3802 {
3803 ZSTD_cwksp ws;
3804 ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
3805 cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
3806 if (cdict == NULL) return NULL;
3807 ZSTD_cwksp_move(&cdict->workspace, &ws);
3808 }
3809
3810 DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
3811 (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
3812 if (workspaceSize < neededSize) return NULL;
3813
3814 ZSTD_CCtxParams_init(¶ms, 0);
3815 params.cParams = cParams;
3816
3817 if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3818 dict, dictSize,
3819 dictLoadMethod, dictContentType,
3820 params) ))
3821 return NULL;
3822
3823 return cdict;
3824 }
3825
3826 ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
3827 {
3828 assert(cdict != NULL);
3829 return cdict->matchState.cParams;
3830 }
3831
3832
3833
3834
3835
3836 unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict)
3837 {
3838 if (cdict==NULL) return 0;
3839 return cdict->dictID;
3840 }
3841
3842
3843
3844
3845 size_t ZSTD_compressBegin_usingCDict_advanced(
3846 ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
3847 ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
3848 {
3849 ZSTD_CCtx_params cctxParams;
3850 DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
3851 RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
3852
3853 {
3854 ZSTD_parameters params;
3855 params.fParams = fParams;
3856 params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
3857 || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
3858 || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
3859 || cdict->compressionLevel == 0 ) ?
3860 ZSTD_getCParamsFromCDict(cdict)
3861 : ZSTD_getCParams(cdict->compressionLevel,
3862 pledgedSrcSize,
3863 cdict->dictContentSize);
3864 ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->compressionLevel);
3865 }
3866
3867
3868
3869
3870 if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
3871 U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
3872 U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
3873 cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog);
3874 }
3875 return ZSTD_compressBegin_internal(cctx,
3876 NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
3877 cdict,
3878 &cctxParams, pledgedSrcSize,
3879 ZSTDb_not_buffered);
3880 }
3881
3882
3883
3884
3885 size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
3886 {
3887 ZSTD_frameParameters const fParams = { 0 , 0 , 0 };
3888 DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
3889 return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);
3890 }
3891
3892 size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
3893 void* dst, size_t dstCapacity,
3894 const void* src, size_t srcSize,
3895 const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
3896 {
3897 FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), "");
3898 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3899 }
3900
3901
3902
3903
3904
3905
3906 size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
3907 void* dst, size_t dstCapacity,
3908 const void* src, size_t srcSize,
3909 const ZSTD_CDict* cdict)
3910 {
3911 ZSTD_frameParameters const fParams = { 1 , 0 , 0 };
3912 return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);
3913 }
3914
3915
3916
3917
3918
3919
3920
3921 ZSTD_CStream* ZSTD_createCStream(void)
3922 {
3923 DEBUGLOG(3, "ZSTD_createCStream");
3924 return ZSTD_createCStream_advanced(ZSTD_defaultCMem);
3925 }
3926
3927 ZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize)
3928 {
3929 return ZSTD_initStaticCCtx(workspace, workspaceSize);
3930 }
3931
3932 ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
3933 {
3934 return ZSTD_createCCtx_advanced(customMem);
3935 }
3936
3937 size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
3938 {
3939 return ZSTD_freeCCtx(zcs);
3940 }
3941
3942
3943
3944
3945
3946 size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX; }
3947
3948 size_t ZSTD_CStreamOutSize(void)
3949 {
3950 return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 ;
3951 }
3952
3953 static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)
3954 {
3955 if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize))
3956 return ZSTD_cpm_attachDict;
3957 else
3958 return ZSTD_cpm_noAttachDict;
3959 }
3960
3961
3962
3963 size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
3964 {
3965
3966
3967
3968
3969 U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3970 DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
3971 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3972 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3973 return 0;
3974 }
3975
3976
3977
3978
3979
3980 size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3981 const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3982 const ZSTD_CCtx_params* params,
3983 unsigned long long pledgedSrcSize)
3984 {
3985 DEBUGLOG(4, "ZSTD_initCStream_internal");
3986 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3987 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3988 assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
3989 zcs->requestedParams = *params;
3990 assert(!((dict) && (cdict)));
3991 if (dict) {
3992 FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
3993 } else {
3994
3995 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
3996 }
3997 return 0;
3998 }
3999
4000
4001
4002 size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
4003 const ZSTD_CDict* cdict,
4004 ZSTD_frameParameters fParams,
4005 unsigned long long pledgedSrcSize)
4006 {
4007 DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
4008 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
4009 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
4010 zcs->requestedParams.fParams = fParams;
4011 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
4012 return 0;
4013 }
4014
4015
4016 size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
4017 {
4018 DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
4019 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
4020 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
4021 return 0;
4022 }
4023
4024
4025
4026
4027
4028
4029 size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
4030 const void* dict, size_t dictSize,
4031 ZSTD_parameters params, unsigned long long pss)
4032 {
4033
4034
4035
4036
4037 U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
4038 DEBUGLOG(4, "ZSTD_initCStream_advanced");
4039 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
4040 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
4041 FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
4042 ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, ¶ms);
4043 FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
4044 return 0;
4045 }
4046
4047 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
4048 {
4049 DEBUGLOG(4, "ZSTD_initCStream_usingDict");
4050 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
4051 FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
4052 FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
4053 return 0;
4054 }
4055
4056 size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
4057 {
4058
4059
4060
4061
4062 U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
4063 DEBUGLOG(4, "ZSTD_initCStream_srcSize");
4064 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
4065 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
4066 FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
4067 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
4068 return 0;
4069 }
4070
4071 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
4072 {
4073 DEBUGLOG(4, "ZSTD_initCStream");
4074 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
4075 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
4076 FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
4077 return 0;
4078 }
4079
4080
4081
4082 static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
4083 {
4084 size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos;
4085 if (hintInSize==0) hintInSize = cctx->blockSize;
4086 return hintInSize;
4087 }
4088
4089
4090
4091
4092
4093 static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
4094 ZSTD_outBuffer* output,
4095 ZSTD_inBuffer* input,
4096 ZSTD_EndDirective const flushMode)
4097 {
4098 const char* const istart = (const char*)input->src;
4099 const char* const iend = input->size != 0 ? istart + input->size : istart;
4100 const char* ip = input->pos != 0 ? istart + input->pos : istart;
4101 char* const ostart = (char*)output->dst;
4102 char* const oend = output->size != 0 ? ostart + output->size : ostart;
4103 char* op = output->pos != 0 ? ostart + output->pos : ostart;
4104 U32 someMoreWork = 1;
4105
4106
4107 DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode);
4108 if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
4109 assert(zcs->inBuff != NULL);
4110 assert(zcs->inBuffSize > 0);
4111 }
4112 if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) {
4113 assert(zcs->outBuff != NULL);
4114 assert(zcs->outBuffSize > 0);
4115 }
4116 assert(output->pos <= output->size);
4117 assert(input->pos <= input->size);
4118 assert((U32)flushMode <= (U32)ZSTD_e_end);
4119
4120 while (someMoreWork) {
4121 switch(zcs->streamStage)
4122 {
4123 case zcss_init:
4124 RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
4125
4126 case zcss_load:
4127 if ( (flushMode == ZSTD_e_end)
4128 && ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip)
4129 || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)
4130 && (zcs->inBuffPos == 0) ) {
4131
4132 size_t const cSize = ZSTD_compressEnd(zcs,
4133 op, oend-op, ip, iend-ip);
4134 DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
4135 FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed");
4136 ip = iend;
4137 op += cSize;
4138 zcs->frameEnded = 1;
4139 ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
4140 someMoreWork = 0; break;
4141 }
4142
4143 if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
4144 size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
4145 size_t const loaded = ZSTD_limitCopy(
4146 zcs->inBuff + zcs->inBuffPos, toLoad,
4147 ip, iend-ip);
4148 zcs->inBuffPos += loaded;
4149 if (loaded != 0)
4150 ip += loaded;
4151 if ( (flushMode == ZSTD_e_continue)
4152 && (zcs->inBuffPos < zcs->inBuffTarget) ) {
4153
4154 someMoreWork = 0; break;
4155 }
4156 if ( (flushMode == ZSTD_e_flush)
4157 && (zcs->inBuffPos == zcs->inToCompress) ) {
4158
4159 someMoreWork = 0; break;
4160 }
4161 }
4162
4163 DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode);
4164 { int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered);
4165 void* cDst;
4166 size_t cSize;
4167 size_t oSize = oend-op;
4168 size_t const iSize = inputBuffered
4169 ? zcs->inBuffPos - zcs->inToCompress
4170 : MIN((size_t)(iend - ip), zcs->blockSize);
4171 if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)
4172 cDst = op;
4173 else
4174 cDst = zcs->outBuff, oSize = zcs->outBuffSize;
4175 if (inputBuffered) {
4176 unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);
4177 cSize = lastBlock ?
4178 ZSTD_compressEnd(zcs, cDst, oSize,
4179 zcs->inBuff + zcs->inToCompress, iSize) :
4180 ZSTD_compressContinue(zcs, cDst, oSize,
4181 zcs->inBuff + zcs->inToCompress, iSize);
4182 FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
4183 zcs->frameEnded = lastBlock;
4184
4185 zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
4186 if (zcs->inBuffTarget > zcs->inBuffSize)
4187 zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
4188 DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
4189 (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);
4190 if (!lastBlock)
4191 assert(zcs->inBuffTarget <= zcs->inBuffSize);
4192 zcs->inToCompress = zcs->inBuffPos;
4193 } else {
4194 unsigned const lastBlock = (ip + iSize == iend);
4195 assert(flushMode == ZSTD_e_end );
4196 cSize = lastBlock ?
4197 ZSTD_compressEnd(zcs, cDst, oSize, ip, iSize) :
4198 ZSTD_compressContinue(zcs, cDst, oSize, ip, iSize);
4199
4200 if (iSize > 0)
4201 ip += iSize;
4202 FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
4203 zcs->frameEnded = lastBlock;
4204 if (lastBlock)
4205 assert(ip == iend);
4206 }
4207 if (cDst == op) {
4208 op += cSize;
4209 if (zcs->frameEnded) {
4210 DEBUGLOG(5, "Frame completed directly in outBuffer");
4211 someMoreWork = 0;
4212 ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
4213 }
4214 break;
4215 }
4216 zcs->outBuffContentSize = cSize;
4217 zcs->outBuffFlushedSize = 0;
4218 zcs->streamStage = zcss_flush;
4219 }
4220 ZSTD_FALLTHROUGH;
4221 case zcss_flush:
4222 DEBUGLOG(5, "flush stage");
4223 assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered);
4224 { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
4225 size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
4226 zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
4227 DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
4228 (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
4229 if (flushed)
4230 op += flushed;
4231 zcs->outBuffFlushedSize += flushed;
4232 if (toFlush!=flushed) {
4233
4234 assert(op==oend);
4235 someMoreWork = 0;
4236 break;
4237 }
4238 zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
4239 if (zcs->frameEnded) {
4240 DEBUGLOG(5, "Frame completed on flush");
4241 someMoreWork = 0;
4242 ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
4243 break;
4244 }
4245 zcs->streamStage = zcss_load;
4246 break;
4247 }
4248
4249 default:
4250 assert(0);
4251 }
4252 }
4253
4254 input->pos = ip - istart;
4255 output->pos = op - ostart;
4256 if (zcs->frameEnded) return 0;
4257 return ZSTD_nextInputSizeHint(zcs);
4258 }
4259
4260 static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
4261 {
4262 return ZSTD_nextInputSizeHint(cctx);
4263
4264 }
4265
4266 size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
4267 {
4268 FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , "");
4269 return ZSTD_nextInputSizeHint_MTorST(zcs);
4270 }
4271
4272
4273
4274
4275 static void ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, ZSTD_outBuffer const* output, ZSTD_inBuffer const* input)
4276 {
4277 if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
4278 cctx->expectedInBuffer = *input;
4279 }
4280 if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
4281 cctx->expectedOutBufferSize = output->size - output->pos;
4282 }
4283 }
4284
4285
4286
4287
4288 static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,
4289 ZSTD_outBuffer const* output,
4290 ZSTD_inBuffer const* input,
4291 ZSTD_EndDirective endOp)
4292 {
4293 if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
4294 ZSTD_inBuffer const expect = cctx->expectedInBuffer;
4295 if (expect.src != input->src || expect.pos != input->pos || expect.size != input->size)
4296 RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer enabled but input differs!");
4297 if (endOp != ZSTD_e_end)
4298 RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer can only be used with ZSTD_e_end!");
4299 }
4300 if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
4301 size_t const outBufferSize = output->size - output->pos;
4302 if (cctx->expectedOutBufferSize != outBufferSize)
4303 RETURN_ERROR(dstBuffer_wrong, "ZSTD_c_stableOutBuffer enabled but output size differs!");
4304 }
4305 return 0;
4306 }
4307
4308 static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
4309 ZSTD_EndDirective endOp,
4310 size_t inSize) {
4311 ZSTD_CCtx_params params = cctx->requestedParams;
4312 ZSTD_prefixDict const prefixDict = cctx->prefixDict;
4313 FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , "");
4314 ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
4315 assert(prefixDict.dict==NULL || cctx->cdict==NULL);
4316 if (cctx->cdict)
4317 params.compressionLevel = cctx->cdict->compressionLevel;
4318 DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
4319 if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1;
4320 {
4321 size_t const dictSize = prefixDict.dict
4322 ? prefixDict.dictSize
4323 : (cctx->cdict ? cctx->cdict->dictContentSize : 0);
4324 ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1);
4325 params.cParams = ZSTD_getCParamsFromCCtxParams(
4326 ¶ms, cctx->pledgedSrcSizePlusOne-1,
4327 dictSize, mode);
4328 }
4329
4330 if (ZSTD_CParams_shouldEnableLdm(¶ms.cParams)) {
4331
4332 DEBUGLOG(4, "LDM enabled by default (window size >= 128MB, strategy >= btopt)");
4333 params.ldmParams.enableLdm = 1;
4334 }
4335
4336 { U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1;
4337 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
4338 FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
4339 prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast,
4340 cctx->cdict,
4341 ¶ms, pledgedSrcSize,
4342 ZSTDb_buffered) , "");
4343 assert(cctx->appliedParams.nbWorkers == 0);
4344 cctx->inToCompress = 0;
4345 cctx->inBuffPos = 0;
4346 if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) {
4347
4348
4349
4350 cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize);
4351 } else {
4352 cctx->inBuffTarget = 0;
4353 }
4354 cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
4355 cctx->streamStage = zcss_load;
4356 cctx->frameEnded = 0;
4357 }
4358 return 0;
4359 }
4360
4361 size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4362 ZSTD_outBuffer* output,
4363 ZSTD_inBuffer* input,
4364 ZSTD_EndDirective endOp)
4365 {
4366 DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
4367
4368 RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, "invalid output buffer");
4369 RETURN_ERROR_IF(input->pos > input->size, srcSize_wrong, "invalid input buffer");
4370 RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, "invalid endDirective");
4371 assert(cctx != NULL);
4372
4373
4374 if (cctx->streamStage == zcss_init) {
4375 FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, input->size), "CompressStream2 initialization failed");
4376 ZSTD_setBufferExpectations(cctx, output, input);
4377 }
4378
4379
4380 FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers");
4381
4382 FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
4383 DEBUGLOG(5, "completed ZSTD_compressStream2");
4384 ZSTD_setBufferExpectations(cctx, output, input);
4385 return cctx->outBuffContentSize - cctx->outBuffFlushedSize;
4386 }
4387
4388 size_t ZSTD_compressStream2_simpleArgs (
4389 ZSTD_CCtx* cctx,
4390 void* dst, size_t dstCapacity, size_t* dstPos,
4391 const void* src, size_t srcSize, size_t* srcPos,
4392 ZSTD_EndDirective endOp)
4393 {
4394 ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
4395 ZSTD_inBuffer input = { src, srcSize, *srcPos };
4396
4397 size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp);
4398 *dstPos = output.pos;
4399 *srcPos = input.pos;
4400 return cErr;
4401 }
4402
4403 size_t ZSTD_compress2(ZSTD_CCtx* cctx,
4404 void* dst, size_t dstCapacity,
4405 const void* src, size_t srcSize)
4406 {
4407 ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode;
4408 ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode;
4409 DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
4410 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
4411
4412 cctx->requestedParams.inBufferMode = ZSTD_bm_stable;
4413 cctx->requestedParams.outBufferMode = ZSTD_bm_stable;
4414 { size_t oPos = 0;
4415 size_t iPos = 0;
4416 size_t const result = ZSTD_compressStream2_simpleArgs(cctx,
4417 dst, dstCapacity, &oPos,
4418 src, srcSize, &iPos,
4419 ZSTD_e_end);
4420
4421 cctx->requestedParams.inBufferMode = originalInBufferMode;
4422 cctx->requestedParams.outBufferMode = originalOutBufferMode;
4423 FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
4424 if (result != 0) {
4425 assert(oPos == dstCapacity);
4426 RETURN_ERROR(dstSize_tooSmall, "");
4427 }
4428 assert(iPos == srcSize);
4429 return oPos;
4430 }
4431 }
4432
4433 typedef struct {
4434 U32 idx;
4435 U32 posInSequence;
4436 size_t posInSrc;
4437 } ZSTD_sequencePosition;
4438
4439
4440 static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength,
4441 size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) {
4442 size_t offsetBound;
4443 U32 windowSize = 1 << windowLog;
4444
4445
4446
4447
4448
4449 offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
4450 RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!");
4451 RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small");
4452 return 0;
4453 }
4454
4455
4456 static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) {
4457 U32 offCode = rawOffset + ZSTD_REP_MOVE;
4458 U32 repCode = 0;
4459
4460 if (!ll0 && rawOffset == rep[0]) {
4461 repCode = 1;
4462 } else if (rawOffset == rep[1]) {
4463 repCode = 2 - ll0;
4464 } else if (rawOffset == rep[2]) {
4465 repCode = 3 - ll0;
4466 } else if (ll0 && rawOffset == rep[0] - 1) {
4467 repCode = 3;
4468 }
4469 if (repCode) {
4470
4471 offCode = repCode - 1;
4472 }
4473 return offCode;
4474 }
4475
4476
4477
4478
4479 static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
4480 const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
4481 const void* src, size_t blockSize) {
4482 U32 idx = seqPos->idx;
4483 BYTE const* ip = (BYTE const*)(src);
4484 const BYTE* const iend = ip + blockSize;
4485 repcodes_t updatedRepcodes;
4486 U32 dictSize;
4487 U32 litLength;
4488 U32 matchLength;
4489 U32 ll0;
4490 U32 offCode;
4491
4492 if (cctx->cdict) {
4493 dictSize = (U32)cctx->cdict->dictContentSize;
4494 } else if (cctx->prefixDict.dict) {
4495 dictSize = (U32)cctx->prefixDict.dictSize;
4496 } else {
4497 dictSize = 0;
4498 }
4499 ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
4500 for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) {
4501 litLength = inSeqs[idx].litLength;
4502 matchLength = inSeqs[idx].matchLength;
4503 ll0 = litLength == 0;
4504 offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
4505 updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
4506
4507 DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
4508 if (cctx->appliedParams.validateSequences) {
4509 seqPos->posInSrc += litLength + matchLength;
4510 FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
4511 cctx->appliedParams.cParams.windowLog, dictSize,
4512 cctx->appliedParams.cParams.minMatch),
4513 "Sequence validation failed");
4514 }
4515 RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
4516 "Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
4517 ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
4518 ip += matchLength + litLength;
4519 }
4520 ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
4521
4522 if (inSeqs[idx].litLength) {
4523 DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength);
4524 ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength);
4525 ip += inSeqs[idx].litLength;
4526 seqPos->posInSrc += inSeqs[idx].litLength;
4527 }
4528 RETURN_ERROR_IF(ip != iend, corruption_detected, "Blocksize doesn't agree with block delimiter!");
4529 seqPos->idx = idx+1;
4530 return 0;
4531 }
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544 static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
4545 const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
4546 const void* src, size_t blockSize) {
4547 U32 idx = seqPos->idx;
4548 U32 startPosInSequence = seqPos->posInSequence;
4549 U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;
4550 size_t dictSize;
4551 BYTE const* ip = (BYTE const*)(src);
4552 BYTE const* iend = ip + blockSize;
4553 repcodes_t updatedRepcodes;
4554 U32 bytesAdjustment = 0;
4555 U32 finalMatchSplit = 0;
4556 U32 litLength;
4557 U32 matchLength;
4558 U32 rawOffset;
4559 U32 offCode;
4560
4561 if (cctx->cdict) {
4562 dictSize = cctx->cdict->dictContentSize;
4563 } else if (cctx->prefixDict.dict) {
4564 dictSize = cctx->prefixDict.dictSize;
4565 } else {
4566 dictSize = 0;
4567 }
4568 DEBUGLOG(5, "ZSTD_copySequencesToSeqStore: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize);
4569 DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
4570 ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
4571 while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {
4572 const ZSTD_Sequence currSeq = inSeqs[idx];
4573 litLength = currSeq.litLength;
4574 matchLength = currSeq.matchLength;
4575 rawOffset = currSeq.offset;
4576
4577
4578 if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {
4579 if (startPosInSequence >= litLength) {
4580 startPosInSequence -= litLength;
4581 litLength = 0;
4582 matchLength -= startPosInSequence;
4583 } else {
4584 litLength -= startPosInSequence;
4585 }
4586
4587 endPosInSequence -= currSeq.litLength + currSeq.matchLength;
4588 startPosInSequence = 0;
4589 idx++;
4590 } else {
4591
4592
4593 DEBUGLOG(6, "Require a split: diff: %u, idx: %u PIS: %u",
4594 currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence);
4595 if (endPosInSequence > litLength) {
4596 U32 firstHalfMatchLength;
4597 litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence;
4598 firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength;
4599 if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) {
4600
4601 U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence;
4602 if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) {
4603
4604 endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
4605 bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
4606 firstHalfMatchLength -= bytesAdjustment;
4607 }
4608 matchLength = firstHalfMatchLength;
4609
4610
4611 finalMatchSplit = 1;
4612 } else {
4613
4614
4615
4616
4617
4618 bytesAdjustment = endPosInSequence - currSeq.litLength;
4619 endPosInSequence = currSeq.litLength;
4620 break;
4621 }
4622 } else {
4623
4624 break;
4625 }
4626 }
4627
4628 { U32 ll0 = (litLength == 0);
4629 offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0);
4630 updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
4631 }
4632
4633 if (cctx->appliedParams.validateSequences) {
4634 seqPos->posInSrc += litLength + matchLength;
4635 FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
4636 cctx->appliedParams.cParams.windowLog, dictSize,
4637 cctx->appliedParams.cParams.minMatch),
4638 "Sequence validation failed");
4639 }
4640 DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
4641 RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
4642 "Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
4643 ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
4644 ip += matchLength + litLength;
4645 }
4646 DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
4647 assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength);
4648 seqPos->idx = idx;
4649 seqPos->posInSequence = endPosInSequence;
4650 ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
4651
4652 iend -= bytesAdjustment;
4653 if (ip != iend) {
4654
4655 U32 lastLLSize = (U32)(iend - ip);
4656 assert(ip <= iend);
4657 DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize);
4658 ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize);
4659 seqPos->posInSrc += lastLLSize;
4660 }
4661
4662 return bytesAdjustment;
4663 }
4664
4665 typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
4666 const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
4667 const void* src, size_t blockSize);
4668 static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) {
4669 ZSTD_sequenceCopier sequenceCopier = NULL;
4670 assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode));
4671 if (mode == ZSTD_sf_explicitBlockDelimiters) {
4672 return ZSTD_copySequencesToSeqStoreExplicitBlockDelim;
4673 } else if (mode == ZSTD_sf_noBlockDelimiters) {
4674 return ZSTD_copySequencesToSeqStoreNoBlockDelim;
4675 }
4676 assert(sequenceCopier != NULL);
4677 return sequenceCopier;
4678 }
4679
4680
4681
4682
4683
4684 static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
4685 void* dst, size_t dstCapacity,
4686 const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
4687 const void* src, size_t srcSize) {
4688 size_t cSize = 0;
4689 U32 lastBlock;
4690 size_t blockSize;
4691 size_t compressedSeqsSize;
4692 size_t remaining = srcSize;
4693 ZSTD_sequencePosition seqPos = {0, 0, 0};
4694
4695 BYTE const* ip = (BYTE const*)src;
4696 BYTE* op = (BYTE*)dst;
4697 ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
4698
4699 DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize);
4700
4701 if (remaining == 0) {
4702 U32 const cBlockHeader24 = 1 + (((U32)bt_raw)<<1);
4703 RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header");
4704 MEM_writeLE32(op, cBlockHeader24);
4705 op += ZSTD_blockHeaderSize;
4706 dstCapacity -= ZSTD_blockHeaderSize;
4707 cSize += ZSTD_blockHeaderSize;
4708 }
4709
4710 while (remaining) {
4711 size_t cBlockSize;
4712 size_t additionalByteAdjustment;
4713 lastBlock = remaining <= cctx->blockSize;
4714 blockSize = lastBlock ? (U32)remaining : (U32)cctx->blockSize;
4715 ZSTD_resetSeqStore(&cctx->seqStore);
4716 DEBUGLOG(4, "Working on new block. Blocksize: %zu", blockSize);
4717
4718 additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize);
4719 FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy");
4720 blockSize -= additionalByteAdjustment;
4721
4722
4723 if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
4724 cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
4725 FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
4726 DEBUGLOG(4, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize);
4727 cSize += cBlockSize;
4728 ip += blockSize;
4729 op += cBlockSize;
4730 remaining -= blockSize;
4731 dstCapacity -= cBlockSize;
4732 continue;
4733 }
4734
4735 compressedSeqsSize = ZSTD_entropyCompressSequences(&cctx->seqStore,
4736 &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,
4737 &cctx->appliedParams,
4738 op + ZSTD_blockHeaderSize , dstCapacity - ZSTD_blockHeaderSize,
4739 blockSize,
4740 cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE ,
4741 cctx->bmi2);
4742 FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed");
4743 DEBUGLOG(4, "Compressed sequences size: %zu", compressedSeqsSize);
4744
4745 if (!cctx->isFirstBlock &&
4746 ZSTD_maybeRLE(&cctx->seqStore) &&
4747 ZSTD_isRLE((BYTE const*)src, srcSize)) {
4748
4749
4750
4751
4752 compressedSeqsSize = 1;
4753 }
4754
4755 if (compressedSeqsSize == 0) {
4756
4757 cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
4758 FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
4759 DEBUGLOG(4, "Writing out nocompress block, size: %zu", cBlockSize);
4760 } else if (compressedSeqsSize == 1) {
4761 cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock);
4762 FORWARD_IF_ERROR(cBlockSize, "RLE compress block failed");
4763 DEBUGLOG(4, "Writing out RLE block, size: %zu", cBlockSize);
4764 } else {
4765 U32 cBlockHeader;
4766
4767 ZSTD_confirmRepcodesAndEntropyTables(cctx);
4768 if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
4769 cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
4770
4771
4772 cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);
4773 MEM_writeLE24(op, cBlockHeader);
4774 cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;
4775 DEBUGLOG(4, "Writing out compressed block, size: %zu", cBlockSize);
4776 }
4777
4778 cSize += cBlockSize;
4779 DEBUGLOG(4, "cSize running total: %zu", cSize);
4780
4781 if (lastBlock) {
4782 break;
4783 } else {
4784 ip += blockSize;
4785 op += cBlockSize;
4786 remaining -= blockSize;
4787 dstCapacity -= cBlockSize;
4788 cctx->isFirstBlock = 0;
4789 }
4790 }
4791
4792 return cSize;
4793 }
4794
4795 size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity,
4796 const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
4797 const void* src, size_t srcSize) {
4798 BYTE* op = (BYTE*)dst;
4799 size_t cSize = 0;
4800 size_t compressedBlocksSize = 0;
4801 size_t frameHeaderSize = 0;
4802
4803
4804 DEBUGLOG(3, "ZSTD_compressSequences()");
4805 assert(cctx != NULL);
4806 FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed");
4807
4808 frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID);
4809 op += frameHeaderSize;
4810 dstCapacity -= frameHeaderSize;
4811 cSize += frameHeaderSize;
4812 if (cctx->appliedParams.fParams.checksumFlag && srcSize) {
4813 xxh64_update(&cctx->xxhState, src, srcSize);
4814 }
4815
4816 compressedBlocksSize = ZSTD_compressSequences_internal(cctx,
4817 op, dstCapacity,
4818 inSeqs, inSeqsSize,
4819 src, srcSize);
4820 FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!");
4821 cSize += compressedBlocksSize;
4822 dstCapacity -= compressedBlocksSize;
4823
4824 if (cctx->appliedParams.fParams.checksumFlag) {
4825 U32 const checksum = (U32) xxh64_digest(&cctx->xxhState);
4826 RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
4827 DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum);
4828 MEM_writeLE32((char*)dst + cSize, checksum);
4829 cSize += 4;
4830 }
4831
4832 DEBUGLOG(3, "Final compressed size: %zu", cSize);
4833 return cSize;
4834 }
4835
4836
4837
4838
4839
4840 size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
4841 {
4842 ZSTD_inBuffer input = { NULL, 0, 0 };
4843 return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush);
4844 }
4845
4846
4847 size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
4848 {
4849 ZSTD_inBuffer input = { NULL, 0, 0 };
4850 size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
4851 FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed");
4852 if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush;
4853
4854 { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
4855 size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);
4856 size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
4857 DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
4858 return toFlush;
4859 }
4860 }
4861
4862
4863
4864
4865 #define ZSTD_MAX_CLEVEL 22
4866 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
4867 int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
4868
4869 static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
4870 {
4871
4872 { 19, 12, 13, 1, 6, 1, ZSTD_fast },
4873 { 19, 13, 14, 1, 7, 0, ZSTD_fast },
4874 { 20, 15, 16, 1, 6, 0, ZSTD_fast },
4875 { 21, 16, 17, 1, 5, 0, ZSTD_dfast },
4876 { 21, 18, 18, 1, 5, 0, ZSTD_dfast },
4877 { 21, 18, 19, 2, 5, 2, ZSTD_greedy },
4878 { 21, 19, 19, 3, 5, 4, ZSTD_greedy },
4879 { 21, 19, 19, 3, 5, 8, ZSTD_lazy },
4880 { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 },
4881 { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 },
4882 { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 },
4883 { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 },
4884 { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 },
4885 { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 },
4886 { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 },
4887 { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 },
4888 { 22, 22, 22, 5, 5, 48, ZSTD_btopt },
4889 { 23, 23, 22, 5, 4, 64, ZSTD_btopt },
4890 { 23, 23, 22, 6, 3, 64, ZSTD_btultra },
4891 { 23, 24, 22, 7, 3,256, ZSTD_btultra2},
4892 { 25, 25, 23, 7, 3,256, ZSTD_btultra2},
4893 { 26, 26, 24, 7, 3,512, ZSTD_btultra2},
4894 { 27, 27, 25, 9, 3,999, ZSTD_btultra2},
4895 },
4896 {
4897
4898 { 18, 12, 13, 1, 5, 1, ZSTD_fast },
4899 { 18, 13, 14, 1, 6, 0, ZSTD_fast },
4900 { 18, 14, 14, 1, 5, 0, ZSTD_dfast },
4901 { 18, 16, 16, 1, 4, 0, ZSTD_dfast },
4902 { 18, 16, 17, 2, 5, 2, ZSTD_greedy },
4903 { 18, 18, 18, 3, 5, 2, ZSTD_greedy },
4904 { 18, 18, 19, 3, 5, 4, ZSTD_lazy },
4905 { 18, 18, 19, 4, 4, 4, ZSTD_lazy },
4906 { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 },
4907 { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 },
4908 { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 },
4909 { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 },
4910 { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 },
4911 { 18, 18, 19, 4, 4, 16, ZSTD_btopt },
4912 { 18, 18, 19, 4, 3, 32, ZSTD_btopt },
4913 { 18, 18, 19, 6, 3,128, ZSTD_btopt },
4914 { 18, 19, 19, 6, 3,128, ZSTD_btultra },
4915 { 18, 19, 19, 8, 3,256, ZSTD_btultra },
4916 { 18, 19, 19, 6, 3,128, ZSTD_btultra2},
4917 { 18, 19, 19, 8, 3,256, ZSTD_btultra2},
4918 { 18, 19, 19, 10, 3,512, ZSTD_btultra2},
4919 { 18, 19, 19, 12, 3,512, ZSTD_btultra2},
4920 { 18, 19, 19, 13, 3,999, ZSTD_btultra2},
4921 },
4922 {
4923
4924 { 17, 12, 12, 1, 5, 1, ZSTD_fast },
4925 { 17, 12, 13, 1, 6, 0, ZSTD_fast },
4926 { 17, 13, 15, 1, 5, 0, ZSTD_fast },
4927 { 17, 15, 16, 2, 5, 0, ZSTD_dfast },
4928 { 17, 17, 17, 2, 4, 0, ZSTD_dfast },
4929 { 17, 16, 17, 3, 4, 2, ZSTD_greedy },
4930 { 17, 17, 17, 3, 4, 4, ZSTD_lazy },
4931 { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 },
4932 { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 },
4933 { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 },
4934 { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 },
4935 { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 },
4936 { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 },
4937 { 17, 18, 17, 3, 4, 12, ZSTD_btopt },
4938 { 17, 18, 17, 4, 3, 32, ZSTD_btopt },
4939 { 17, 18, 17, 6, 3,256, ZSTD_btopt },
4940 { 17, 18, 17, 6, 3,128, ZSTD_btultra },
4941 { 17, 18, 17, 8, 3,256, ZSTD_btultra },
4942 { 17, 18, 17, 10, 3,512, ZSTD_btultra },
4943 { 17, 18, 17, 5, 3,256, ZSTD_btultra2},
4944 { 17, 18, 17, 7, 3,512, ZSTD_btultra2},
4945 { 17, 18, 17, 9, 3,512, ZSTD_btultra2},
4946 { 17, 18, 17, 11, 3,999, ZSTD_btultra2},
4947 },
4948 {
4949
4950 { 14, 12, 13, 1, 5, 1, ZSTD_fast },
4951 { 14, 14, 15, 1, 5, 0, ZSTD_fast },
4952 { 14, 14, 15, 1, 4, 0, ZSTD_fast },
4953 { 14, 14, 15, 2, 4, 0, ZSTD_dfast },
4954 { 14, 14, 14, 4, 4, 2, ZSTD_greedy },
4955 { 14, 14, 14, 3, 4, 4, ZSTD_lazy },
4956 { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 },
4957 { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 },
4958 { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 },
4959 { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 },
4960 { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 },
4961 { 14, 15, 14, 3, 4, 12, ZSTD_btopt },
4962 { 14, 15, 14, 4, 3, 24, ZSTD_btopt },
4963 { 14, 15, 14, 5, 3, 32, ZSTD_btultra },
4964 { 14, 15, 15, 6, 3, 64, ZSTD_btultra },
4965 { 14, 15, 15, 7, 3,256, ZSTD_btultra },
4966 { 14, 15, 15, 5, 3, 48, ZSTD_btultra2},
4967 { 14, 15, 15, 6, 3,128, ZSTD_btultra2},
4968 { 14, 15, 15, 7, 3,256, ZSTD_btultra2},
4969 { 14, 15, 15, 8, 3,256, ZSTD_btultra2},
4970 { 14, 15, 15, 8, 3,512, ZSTD_btultra2},
4971 { 14, 15, 15, 9, 3,512, ZSTD_btultra2},
4972 { 14, 15, 15, 10, 3,999, ZSTD_btultra2},
4973 },
4974 };
4975
4976 static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)
4977 {
4978 ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);
4979 switch (cParams.strategy) {
4980 case ZSTD_fast:
4981 case ZSTD_dfast:
4982 break;
4983 case ZSTD_greedy:
4984 case ZSTD_lazy:
4985 case ZSTD_lazy2:
4986 cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG;
4987 break;
4988 case ZSTD_btlazy2:
4989 case ZSTD_btopt:
4990 case ZSTD_btultra:
4991 case ZSTD_btultra2:
4992 break;
4993 }
4994 return cParams;
4995 }
4996
4997 static int ZSTD_dedicatedDictSearch_isSupported(
4998 ZSTD_compressionParameters const* cParams)
4999 {
5000 return (cParams->strategy >= ZSTD_greedy)
5001 && (cParams->strategy <= ZSTD_lazy2)
5002 && (cParams->hashLog >= cParams->chainLog)
5003 && (cParams->chainLog <= 24);
5004 }
5005
5006
5007
5008
5009
5010
5011 static void ZSTD_dedicatedDictSearch_revertCParams(
5012 ZSTD_compressionParameters* cParams) {
5013 switch (cParams->strategy) {
5014 case ZSTD_fast:
5015 case ZSTD_dfast:
5016 break;
5017 case ZSTD_greedy:
5018 case ZSTD_lazy:
5019 case ZSTD_lazy2:
5020 cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG;
5021 break;
5022 case ZSTD_btlazy2:
5023 case ZSTD_btopt:
5024 case ZSTD_btultra:
5025 case ZSTD_btultra2:
5026 break;
5027 }
5028 }
5029
5030 static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
5031 {
5032 switch (mode) {
5033 case ZSTD_cpm_unknown:
5034 case ZSTD_cpm_noAttachDict:
5035 case ZSTD_cpm_createCDict:
5036 break;
5037 case ZSTD_cpm_attachDict:
5038 dictSize = 0;
5039 break;
5040 default:
5041 assert(0);
5042 break;
5043 }
5044 { int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;
5045 size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
5046 return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
5047 }
5048 }
5049
5050
5051
5052
5053
5054
5055 static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
5056 {
5057 U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode);
5058 U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
5059 int row;
5060 DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
5061
5062
5063 if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT;
5064 else if (compressionLevel < 0) row = 0;
5065 else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
5066 else row = compressionLevel;
5067
5068 { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
5069
5070 if (compressionLevel < 0) {
5071 int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel);
5072 cp.targetLength = (unsigned)(-clampedCompressionLevel);
5073 }
5074
5075 return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode);
5076 }
5077 }
5078
5079
5080
5081
5082 ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
5083 {
5084 if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
5085 return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
5086 }
5087
5088
5089
5090
5091
5092 static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) {
5093 ZSTD_parameters params;
5094 ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode);
5095 DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
5096 ZSTD_memset(¶ms, 0, sizeof(params));
5097 params.cParams = cParams;
5098 params.fParams.contentSizeFlag = 1;
5099 return params;
5100 }
5101
5102
5103
5104
5105
5106 ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
5107 if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
5108 return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
5109 }