comparison contrib/python-zstandard/zstd/compress/zstd_compress.c @ 40121:73fef626dae3

zstandard: vendor python-zstandard 0.10.1 This was just released. The upstream source distribution from PyPI was extracted. Unwanted files were removed. The clang-format ignore list was updated to reflect the new source of files. setup.py was updated to pass a new argument to python-zstandard's function for returning an Extension instance. Upstream had to change to use relative paths because Python 3.7's packaging doesn't seem to like absolute paths when defining sources, includes, etc. The default relative path calculation is relative to setup_zstd.py which is different from the directory of Mercurial's setup.py. The project contains a vendored copy of zstandard 1.3.6. The old version was 1.3.4. The API should be backwards compatible and nothing in core should need adjusted. However, there is a new "chunker" API that we may find useful in places where we want to emit compressed chunks of a fixed size. There are a pair of bug fixes in 0.10.0 with regards to compressobj() and decompressobj() when block flushing is used. I actually found these bugs when introducing these APIs in Mercurial! But existing Mercurial code is not affected because we don't perform block flushing. # no-check-commit because 3rd party code has different style guidelines Differential Revision: https://phab.mercurial-scm.org/D4911
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 08 Oct 2018 16:27:40 -0700
parents b1fb341d8a61
children 675775c33ab6
comparison
equal deleted inserted replaced
40120:89742f1fa6cb 40121:73fef626dae3
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found 6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree). 7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses. 8 * You may select, at your option, one of the above-listed licenses.
9 */ 9 */
10 10
11
12 /*-*************************************
13 * Tuning parameters
14 ***************************************/
15 #ifndef ZSTD_CLEVEL_DEFAULT
16 # define ZSTD_CLEVEL_DEFAULT 3
17 #endif
18
19
20 /*-************************************* 11 /*-*************************************
21 * Dependencies 12 * Dependencies
22 ***************************************/ 13 ***************************************/
23 #include <string.h> /* memset */ 14 #include <string.h> /* memset */
24 #include "cpu.h" 15 #include "cpu.h"
25 #include "mem.h" 16 #include "mem.h"
17 #include "hist.h" /* HIST_countFast_wksp */
26 #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ 18 #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
27 #include "fse.h" 19 #include "fse.h"
28 #define HUF_STATIC_LINKING_ONLY 20 #define HUF_STATIC_LINKING_ONLY
29 #include "huf.h" 21 #include "huf.h"
30 #include "zstd_compress_internal.h" 22 #include "zstd_compress_internal.h"
52 size_t dictContentSize; 44 size_t dictContentSize;
53 void* workspace; 45 void* workspace;
54 size_t workspaceSize; 46 size_t workspaceSize;
55 ZSTD_matchState_t matchState; 47 ZSTD_matchState_t matchState;
56 ZSTD_compressedBlockState_t cBlockState; 48 ZSTD_compressedBlockState_t cBlockState;
57 ZSTD_compressionParameters cParams;
58 ZSTD_customMem customMem; 49 ZSTD_customMem customMem;
59 U32 dictID; 50 U32 dictID;
60 }; /* typedef'd to ZSTD_CDict within "zstd.h" */ 51 }; /* typedef'd to ZSTD_CDict within "zstd.h" */
61 52
62 ZSTD_CCtx* ZSTD_createCCtx(void) 53 ZSTD_CCtx* ZSTD_createCCtx(void)
63 { 54 {
64 return ZSTD_createCCtx_advanced(ZSTD_defaultCMem); 55 return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
65 } 56 }
66 57
58 static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
59 {
60 assert(cctx != NULL);
61 memset(cctx, 0, sizeof(*cctx));
62 cctx->customMem = memManager;
63 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
64 { size_t const err = ZSTD_CCtx_resetParameters(cctx);
65 assert(!ZSTD_isError(err));
66 (void)err;
67 }
68 }
69
67 ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) 70 ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
68 { 71 {
69 ZSTD_STATIC_ASSERT(zcss_init==0); 72 ZSTD_STATIC_ASSERT(zcss_init==0);
70 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1)); 73 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
71 if (!customMem.customAlloc ^ !customMem.customFree) return NULL; 74 if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
72 { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_calloc(sizeof(ZSTD_CCtx), customMem); 75 { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
73 if (!cctx) return NULL; 76 if (!cctx) return NULL;
74 cctx->customMem = customMem; 77 ZSTD_initCCtx(cctx, customMem);
75 cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
76 cctx->requestedParams.fParams.contentSizeFlag = 1;
77 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
78 return cctx; 78 return cctx;
79 } 79 }
80 } 80 }
81 81
82 ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize) 82 ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
100 } 100 }
101 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); 101 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
102 return cctx; 102 return cctx;
103 } 103 }
104 104
105 size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) 105 static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
106 { 106 {
107 if (cctx==NULL) return 0; /* support free on NULL */ 107 assert(cctx != NULL);
108 if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */ 108 assert(cctx->staticSize == 0);
109 ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL; 109 ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
110 ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL; 110 ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
111 #ifdef ZSTD_MULTITHREAD 111 #ifdef ZSTD_MULTITHREAD
112 ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL; 112 ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
113 #endif 113 #endif
114 }
115
116 size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
117 {
118 if (cctx==NULL) return 0; /* support free on NULL */
119 if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
120 ZSTD_freeCCtxContent(cctx);
114 ZSTD_free(cctx, cctx->customMem); 121 ZSTD_free(cctx, cctx->customMem);
115 return 0; /* reserved as a potential error code in the future */ 122 return 0;
116 } 123 }
117 124
118 125
119 static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx) 126 static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
120 { 127 {
140 return ZSTD_sizeof_CCtx(zcs); /* same object */ 147 return ZSTD_sizeof_CCtx(zcs); /* same object */
141 } 148 }
142 149
143 /* private API call, for dictBuilder only */ 150 /* private API call, for dictBuilder only */
144 const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); } 151 const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
145
146 ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
147 const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
148 {
149 ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
150 if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
151 if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
152 if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
153 if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
154 if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
155 if (CCtxParams->cParams.searchLength) cParams.searchLength = CCtxParams->cParams.searchLength;
156 if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
157 if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
158 return cParams;
159 }
160 152
161 static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( 153 static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
162 ZSTD_compressionParameters cParams) 154 ZSTD_compressionParameters cParams)
163 { 155 {
164 ZSTD_CCtx_params cctxParams; 156 ZSTD_CCtx_params cctxParams;
249 case ZSTD_p_chainLog: 241 case ZSTD_p_chainLog:
250 case ZSTD_p_searchLog: 242 case ZSTD_p_searchLog:
251 case ZSTD_p_minMatch: 243 case ZSTD_p_minMatch:
252 case ZSTD_p_targetLength: 244 case ZSTD_p_targetLength:
253 case ZSTD_p_compressionStrategy: 245 case ZSTD_p_compressionStrategy:
254 case ZSTD_p_compressLiterals:
255 return 1; 246 return 1;
256 247
257 case ZSTD_p_format: 248 case ZSTD_p_format:
258 case ZSTD_p_windowLog: 249 case ZSTD_p_windowLog:
259 case ZSTD_p_contentSizeFlag: 250 case ZSTD_p_contentSizeFlag:
266 case ZSTD_p_enableLongDistanceMatching: 257 case ZSTD_p_enableLongDistanceMatching:
267 case ZSTD_p_ldmHashLog: 258 case ZSTD_p_ldmHashLog:
268 case ZSTD_p_ldmMinMatch: 259 case ZSTD_p_ldmMinMatch:
269 case ZSTD_p_ldmBucketSizeLog: 260 case ZSTD_p_ldmBucketSizeLog:
270 case ZSTD_p_ldmHashEveryLog: 261 case ZSTD_p_ldmHashEveryLog:
262 case ZSTD_p_forceAttachDict:
271 default: 263 default:
272 return 0; 264 return 0;
273 } 265 }
274 } 266 }
275 267
300 case ZSTD_p_targetLength: 292 case ZSTD_p_targetLength:
301 case ZSTD_p_compressionStrategy: 293 case ZSTD_p_compressionStrategy:
302 if (cctx->cdict) return ERROR(stage_wrong); 294 if (cctx->cdict) return ERROR(stage_wrong);
303 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 295 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
304 296
305 case ZSTD_p_compressLiterals:
306 case ZSTD_p_contentSizeFlag: 297 case ZSTD_p_contentSizeFlag:
307 case ZSTD_p_checksumFlag: 298 case ZSTD_p_checksumFlag:
308 case ZSTD_p_dictIDFlag: 299 case ZSTD_p_dictIDFlag:
309 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 300 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
310 301
311 case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize, 302 case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
312 * even when referencing into Dictionary content. 303 * even when referencing into Dictionary content.
313 * default : 0 when using a CDict, 1 when using a Prefix */ 304 * default : 0 when using a CDict, 1 when using a Prefix */
305 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
306
307 case ZSTD_p_forceAttachDict:
314 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 308 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
315 309
316 case ZSTD_p_nbWorkers: 310 case ZSTD_p_nbWorkers:
317 if ((value>0) && cctx->staticSize) { 311 if ((value>0) && cctx->staticSize) {
318 return ERROR(parameter_unsupported); /* MT not compatible with static alloc */ 312 return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
349 343
350 case ZSTD_p_compressionLevel : { 344 case ZSTD_p_compressionLevel : {
351 int cLevel = (int)value; /* cast expected to restore negative sign */ 345 int cLevel = (int)value; /* cast expected to restore negative sign */
352 if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); 346 if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
353 if (cLevel) { /* 0 : does not change current level */ 347 if (cLevel) { /* 0 : does not change current level */
354 CCtxParams->disableLiteralCompression = (cLevel<0); /* negative levels disable huffman */
355 CCtxParams->compressionLevel = cLevel; 348 CCtxParams->compressionLevel = cLevel;
356 } 349 }
357 if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel; 350 if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
358 return 0; /* return type (size_t) cannot represent negative values */ 351 return 0; /* return type (size_t) cannot represent negative values */
359 } 352 }
397 if (value>0) /* 0 => use default */ 390 if (value>0) /* 0 => use default */
398 CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra); 391 CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
399 CCtxParams->cParams.strategy = (ZSTD_strategy)value; 392 CCtxParams->cParams.strategy = (ZSTD_strategy)value;
400 return (size_t)CCtxParams->cParams.strategy; 393 return (size_t)CCtxParams->cParams.strategy;
401 394
402 case ZSTD_p_compressLiterals:
403 CCtxParams->disableLiteralCompression = !value;
404 return !CCtxParams->disableLiteralCompression;
405
406 case ZSTD_p_contentSizeFlag : 395 case ZSTD_p_contentSizeFlag :
407 /* Content size written in frame header _when known_ (default:1) */ 396 /* Content size written in frame header _when known_ (default:1) */
408 DEBUGLOG(4, "set content size flag = %u", (value>0)); 397 DEBUGLOG(4, "set content size flag = %u", (value>0));
409 CCtxParams->fParams.contentSizeFlag = value > 0; 398 CCtxParams->fParams.contentSizeFlag = value > 0;
410 return CCtxParams->fParams.contentSizeFlag; 399 return CCtxParams->fParams.contentSizeFlag;
420 return !CCtxParams->fParams.noDictIDFlag; 409 return !CCtxParams->fParams.noDictIDFlag;
421 410
422 case ZSTD_p_forceMaxWindow : 411 case ZSTD_p_forceMaxWindow :
423 CCtxParams->forceWindow = (value > 0); 412 CCtxParams->forceWindow = (value > 0);
424 return CCtxParams->forceWindow; 413 return CCtxParams->forceWindow;
414
415 case ZSTD_p_forceAttachDict :
416 CCtxParams->attachDictPref = value ?
417 (value > 0 ? ZSTD_dictForceAttach : ZSTD_dictForceCopy) :
418 ZSTD_dictDefaultAttach;
419 return CCtxParams->attachDictPref;
425 420
426 case ZSTD_p_nbWorkers : 421 case ZSTD_p_nbWorkers :
427 #ifndef ZSTD_MULTITHREAD 422 #ifndef ZSTD_MULTITHREAD
428 if (value>0) return ERROR(parameter_unsupported); 423 if (value>0) return ERROR(parameter_unsupported);
429 return 0; 424 return 0;
473 CCtxParams->ldmParams.hashEveryLog = value; 468 CCtxParams->ldmParams.hashEveryLog = value;
474 return CCtxParams->ldmParams.hashEveryLog; 469 return CCtxParams->ldmParams.hashEveryLog;
475 470
476 default: return ERROR(parameter_unsupported); 471 default: return ERROR(parameter_unsupported);
477 } 472 }
473 }
474
475 size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned* value)
476 {
477 return ZSTD_CCtxParam_getParameter(&cctx->requestedParams, param, value);
478 }
479
480 size_t ZSTD_CCtxParam_getParameter(
481 ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, unsigned* value)
482 {
483 switch(param)
484 {
485 case ZSTD_p_format :
486 *value = CCtxParams->format;
487 break;
488 case ZSTD_p_compressionLevel :
489 *value = CCtxParams->compressionLevel;
490 break;
491 case ZSTD_p_windowLog :
492 *value = CCtxParams->cParams.windowLog;
493 break;
494 case ZSTD_p_hashLog :
495 *value = CCtxParams->cParams.hashLog;
496 break;
497 case ZSTD_p_chainLog :
498 *value = CCtxParams->cParams.chainLog;
499 break;
500 case ZSTD_p_searchLog :
501 *value = CCtxParams->cParams.searchLog;
502 break;
503 case ZSTD_p_minMatch :
504 *value = CCtxParams->cParams.searchLength;
505 break;
506 case ZSTD_p_targetLength :
507 *value = CCtxParams->cParams.targetLength;
508 break;
509 case ZSTD_p_compressionStrategy :
510 *value = (unsigned)CCtxParams->cParams.strategy;
511 break;
512 case ZSTD_p_contentSizeFlag :
513 *value = CCtxParams->fParams.contentSizeFlag;
514 break;
515 case ZSTD_p_checksumFlag :
516 *value = CCtxParams->fParams.checksumFlag;
517 break;
518 case ZSTD_p_dictIDFlag :
519 *value = !CCtxParams->fParams.noDictIDFlag;
520 break;
521 case ZSTD_p_forceMaxWindow :
522 *value = CCtxParams->forceWindow;
523 break;
524 case ZSTD_p_forceAttachDict :
525 *value = CCtxParams->attachDictPref;
526 break;
527 case ZSTD_p_nbWorkers :
528 #ifndef ZSTD_MULTITHREAD
529 assert(CCtxParams->nbWorkers == 0);
530 #endif
531 *value = CCtxParams->nbWorkers;
532 break;
533 case ZSTD_p_jobSize :
534 #ifndef ZSTD_MULTITHREAD
535 return ERROR(parameter_unsupported);
536 #else
537 *value = CCtxParams->jobSize;
538 break;
539 #endif
540 case ZSTD_p_overlapSizeLog :
541 #ifndef ZSTD_MULTITHREAD
542 return ERROR(parameter_unsupported);
543 #else
544 *value = CCtxParams->overlapSizeLog;
545 break;
546 #endif
547 case ZSTD_p_enableLongDistanceMatching :
548 *value = CCtxParams->ldmParams.enableLdm;
549 break;
550 case ZSTD_p_ldmHashLog :
551 *value = CCtxParams->ldmParams.hashLog;
552 break;
553 case ZSTD_p_ldmMinMatch :
554 *value = CCtxParams->ldmParams.minMatchLength;
555 break;
556 case ZSTD_p_ldmBucketSizeLog :
557 *value = CCtxParams->ldmParams.bucketSizeLog;
558 break;
559 case ZSTD_p_ldmHashEveryLog :
560 *value = CCtxParams->ldmParams.hashEveryLog;
561 break;
562 default: return ERROR(parameter_unsupported);
563 }
564 return 0;
478 } 565 }
479 566
480 /** ZSTD_CCtx_setParametersUsingCCtxParams() : 567 /** ZSTD_CCtx_setParametersUsingCCtxParams() :
481 * just applies `params` into `cctx` 568 * just applies `params` into `cctx`
482 * no action is performed, parameters are merely stored. 569 * no action is performed, parameters are merely stored.
485 * In which case, new parameters will be applied on the fly, starting with next compression job. 572 * In which case, new parameters will be applied on the fly, starting with next compression job.
486 */ 573 */
487 size_t ZSTD_CCtx_setParametersUsingCCtxParams( 574 size_t ZSTD_CCtx_setParametersUsingCCtxParams(
488 ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params) 575 ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
489 { 576 {
577 DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
490 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); 578 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
491 if (cctx->cdict) return ERROR(stage_wrong); 579 if (cctx->cdict) return ERROR(stage_wrong);
492 580
493 cctx->requestedParams = *params; 581 cctx->requestedParams = *params;
494 return 0; 582 return 0;
563 cctx->prefixDict.dictSize = prefixSize; 651 cctx->prefixDict.dictSize = prefixSize;
564 cctx->prefixDict.dictContentType = dictContentType; 652 cctx->prefixDict.dictContentType = dictContentType;
565 return 0; 653 return 0;
566 } 654 }
567 655
568 static void ZSTD_startNewCompression(ZSTD_CCtx* cctx)
569 {
570 cctx->streamStage = zcss_init;
571 cctx->pledgedSrcSizePlusOne = 0;
572 }
573
574 /*! ZSTD_CCtx_reset() : 656 /*! ZSTD_CCtx_reset() :
575 * Also dumps dictionary */ 657 * Also dumps dictionary */
576 void ZSTD_CCtx_reset(ZSTD_CCtx* cctx) 658 void ZSTD_CCtx_reset(ZSTD_CCtx* cctx)
577 { 659 {
578 ZSTD_startNewCompression(cctx); 660 cctx->streamStage = zcss_init;
661 cctx->pledgedSrcSizePlusOne = 0;
662 }
663
664 size_t ZSTD_CCtx_resetParameters(ZSTD_CCtx* cctx)
665 {
666 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
579 cctx->cdict = NULL; 667 cctx->cdict = NULL;
668 return ZSTD_CCtxParams_reset(&cctx->requestedParams);
580 } 669 }
581 670
582 /** ZSTD_checkCParams() : 671 /** ZSTD_checkCParams() :
583 control CParam values remain within authorized range. 672 control CParam values remain within authorized range.
584 @return : 0, or an error code if one value is beyond authorized range */ 673 @return : 0, or an error code if one value is beyond authorized range */
587 CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX); 676 CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
588 CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX); 677 CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
589 CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX); 678 CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
590 CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX); 679 CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
591 CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX); 680 CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
592 if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN) 681 ZSTD_STATIC_ASSERT(ZSTD_TARGETLENGTH_MIN == 0);
593 return ERROR(parameter_unsupported); 682 if (cParams.targetLength > ZSTD_TARGETLENGTH_MAX)
683 return ERROR(parameter_outOfBound);
594 if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) 684 if ((U32)(cParams.strategy) > (U32)ZSTD_btultra)
595 return ERROR(parameter_unsupported); 685 return ERROR(parameter_unsupported);
596 return 0; 686 return 0;
597 } 687 }
598 688
599 /** ZSTD_clampCParams() : 689 /** ZSTD_clampCParams() :
600 * make CParam values within valid range. 690 * make CParam values within valid range.
601 * @return : valid CParams */ 691 * @return : valid CParams */
602 static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters cParams) 692 static ZSTD_compressionParameters
693 ZSTD_clampCParams(ZSTD_compressionParameters cParams)
603 { 694 {
604 # define CLAMP(val,min,max) { \ 695 # define CLAMP(val,min,max) { \
605 if (val<min) val=min; \ 696 if (val<min) val=min; \
606 else if (val>max) val=max; \ 697 else if (val>max) val=max; \
607 } 698 }
608 CLAMP(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX); 699 CLAMP(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
609 CLAMP(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX); 700 CLAMP(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
610 CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX); 701 CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
611 CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX); 702 CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
612 CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX); 703 CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
613 if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN) cParams.targetLength = ZSTD_TARGETLENGTH_MIN; 704 ZSTD_STATIC_ASSERT(ZSTD_TARGETLENGTH_MIN == 0);
614 if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) cParams.strategy = ZSTD_btultra; 705 if (cParams.targetLength > ZSTD_TARGETLENGTH_MAX)
706 cParams.targetLength = ZSTD_TARGETLENGTH_MAX;
707 CLAMP(cParams.strategy, ZSTD_fast, ZSTD_btultra);
615 return cParams; 708 return cParams;
616 } 709 }
617 710
618 /** ZSTD_cycleLog() : 711 /** ZSTD_cycleLog() :
619 * condition for correct operation : hashLog > 1 */ 712 * condition for correct operation : hashLog > 1 */
625 718
626 /** ZSTD_adjustCParams_internal() : 719 /** ZSTD_adjustCParams_internal() :
627 optimize `cPar` for a given input (`srcSize` and `dictSize`). 720 optimize `cPar` for a given input (`srcSize` and `dictSize`).
628 mostly downsizing to reduce memory consumption and initialization latency. 721 mostly downsizing to reduce memory consumption and initialization latency.
629 Both `srcSize` and `dictSize` are optional (use 0 if unknown). 722 Both `srcSize` and `dictSize` are optional (use 0 if unknown).
630 Note : cPar is considered validated at this stage. Use ZSTD_checkCParams() to ensure that condition. */ 723 Note : cPar is assumed validated. Use ZSTD_checkCParams() to ensure this condition. */
631 ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize) 724 static ZSTD_compressionParameters
725 ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
726 unsigned long long srcSize,
727 size_t dictSize)
632 { 728 {
633 static const U64 minSrcSize = 513; /* (1<<9) + 1 */ 729 static const U64 minSrcSize = 513; /* (1<<9) + 1 */
634 static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); 730 static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
635 assert(ZSTD_checkCParams(cPar)==0); 731 assert(ZSTD_checkCParams(cPar)==0);
636 732
646 static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN; 742 static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;
647 U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN : 743 U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :
648 ZSTD_highbit32(tSize-1) + 1; 744 ZSTD_highbit32(tSize-1) + 1;
649 if (cPar.windowLog > srcLog) cPar.windowLog = srcLog; 745 if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
650 } 746 }
651 if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog; 747 if (cPar.hashLog > cPar.windowLog+1) cPar.hashLog = cPar.windowLog+1;
652 { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); 748 { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
653 if (cycleLog > cPar.windowLog) 749 if (cycleLog > cPar.windowLog)
654 cPar.chainLog -= (cycleLog - cPar.windowLog); 750 cPar.chainLog -= (cycleLog - cPar.windowLog);
655 } 751 }
656 752
658 cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */ 754 cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
659 755
660 return cPar; 756 return cPar;
661 } 757 }
662 758
663 ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize) 759 ZSTD_compressionParameters
760 ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
761 unsigned long long srcSize,
762 size_t dictSize)
664 { 763 {
665 cPar = ZSTD_clampCParams(cPar); 764 cPar = ZSTD_clampCParams(cPar);
666 return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize); 765 return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
667 } 766 }
668 767
669 static size_t ZSTD_sizeof_matchState(ZSTD_compressionParameters const* cParams, const U32 forCCtx) 768 ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
769 const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
770 {
771 ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
772 if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
773 if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
774 if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
775 if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
776 if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
777 if (CCtxParams->cParams.searchLength) cParams.searchLength = CCtxParams->cParams.searchLength;
778 if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
779 if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
780 assert(!ZSTD_checkCParams(cParams));
781 return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
782 }
783
784 static size_t
785 ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
786 const U32 forCCtx)
670 { 787 {
671 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); 788 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
672 size_t const hSize = ((size_t)1) << cParams->hashLog; 789 size_t const hSize = ((size_t)1) << cParams->hashLog;
673 U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; 790 U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
674 size_t const h3Size = ((size_t)1) << hashLog3; 791 size_t const h3Size = ((size_t)1) << hashLog3;
691 { ZSTD_compressionParameters const cParams = 808 { ZSTD_compressionParameters const cParams =
692 ZSTD_getCParamsFromCCtxParams(params, 0, 0); 809 ZSTD_getCParamsFromCCtxParams(params, 0, 0);
693 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); 810 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
694 U32 const divider = (cParams.searchLength==3) ? 3 : 4; 811 U32 const divider = (cParams.searchLength==3) ? 3 : 4;
695 size_t const maxNbSeq = blockSize / divider; 812 size_t const maxNbSeq = blockSize / divider;
696 size_t const tokenSpace = blockSize + 11*maxNbSeq; 813 size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
697 size_t const entropySpace = HUF_WORKSPACE_SIZE; 814 size_t const entropySpace = HUF_WORKSPACE_SIZE;
698 size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t); 815 size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
699 size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1); 816 size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
700 817
701 size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams); 818 size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
750 { 867 {
751 ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams); 868 ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
752 return ZSTD_estimateCStreamSize_usingCCtxParams(&params); 869 return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
753 } 870 }
754 871
755 static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) { 872 static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
873 {
756 ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0); 874 ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
757 return ZSTD_estimateCStreamSize_usingCParams(cParams); 875 return ZSTD_estimateCStreamSize_usingCParams(cParams);
758 } 876 }
759 877
760 size_t ZSTD_estimateCStreamSize(int compressionLevel) { 878 size_t ZSTD_estimateCStreamSize(int compressionLevel)
879 {
761 int level; 880 int level;
762 size_t memBudget = 0; 881 size_t memBudget = 0;
763 for (level=1; level<=compressionLevel; level++) { 882 for (level=1; level<=compressionLevel; level++) {
764 size_t const newMB = ZSTD_estimateCStreamSize_internal(level); 883 size_t const newMB = ZSTD_estimateCStreamSize_internal(level);
765 if (newMB > memBudget) memBudget = newMB; 884 if (newMB > memBudget) memBudget = newMB;
784 if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress); 903 if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress);
785 assert(buffered <= ZSTD_BLOCKSIZE_MAX); 904 assert(buffered <= ZSTD_BLOCKSIZE_MAX);
786 fp.ingested = cctx->consumedSrcSize + buffered; 905 fp.ingested = cctx->consumedSrcSize + buffered;
787 fp.consumed = cctx->consumedSrcSize; 906 fp.consumed = cctx->consumedSrcSize;
788 fp.produced = cctx->producedCSize; 907 fp.produced = cctx->producedCSize;
908 fp.flushed = cctx->producedCSize; /* simplified; some data might still be left within streaming output buffer */
909 fp.currentJobID = 0;
910 fp.nbActiveWorkers = 0;
789 return fp; 911 return fp;
790 } } 912 } }
913
914 /*! ZSTD_toFlushNow()
915 * Only useful for multithreading scenarios currently (nbWorkers >= 1).
916 */
917 size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
918 {
919 #ifdef ZSTD_MULTITHREAD
920 if (cctx->appliedParams.nbWorkers > 0) {
921 return ZSTDMT_toFlushNow(cctx->mtctx);
922 }
923 #endif
924 (void)cctx;
925 return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */
926 }
927
791 928
792 929
793 static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1, 930 static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
794 ZSTD_compressionParameters cParams2) 931 ZSTD_compressionParameters cParams2)
795 { 932 {
796 return (cParams1.hashLog == cParams2.hashLog) 933 return (cParams1.hashLog == cParams2.hashLog)
797 & (cParams1.chainLog == cParams2.chainLog) 934 & (cParams1.chainLog == cParams2.chainLog)
798 & (cParams1.strategy == cParams2.strategy) /* opt parser space */ 935 & (cParams1.strategy == cParams2.strategy) /* opt parser space */
799 & ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */ 936 & ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
937 }
938
939 static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
940 ZSTD_compressionParameters cParams2)
941 {
942 (void)cParams1;
943 (void)cParams2;
944 assert(cParams1.windowLog == cParams2.windowLog);
945 assert(cParams1.chainLog == cParams2.chainLog);
946 assert(cParams1.hashLog == cParams2.hashLog);
947 assert(cParams1.searchLog == cParams2.searchLog);
948 assert(cParams1.searchLength == cParams2.searchLength);
949 assert(cParams1.targetLength == cParams2.targetLength);
950 assert(cParams1.strategy == cParams2.strategy);
800 } 951 }
801 952
802 /** The parameters are equivalent if ldm is not enabled in both sets or 953 /** The parameters are equivalent if ldm is not enabled in both sets or
803 * all the parameters are equivalent. */ 954 * all the parameters are equivalent. */
804 static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1, 955 static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
815 typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e; 966 typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
816 967
817 /* ZSTD_sufficientBuff() : 968 /* ZSTD_sufficientBuff() :
818 * check internal buffers exist for streaming if buffPol == ZSTDb_buffered . 969 * check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
819 * Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */ 970 * Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
820 static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t blockSize1, 971 static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t maxNbSeq1,
972 size_t maxNbLit1,
821 ZSTD_buffered_policy_e buffPol2, 973 ZSTD_buffered_policy_e buffPol2,
822 ZSTD_compressionParameters cParams2, 974 ZSTD_compressionParameters cParams2,
823 U64 pledgedSrcSize) 975 U64 pledgedSrcSize)
824 { 976 {
825 size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize)); 977 size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
826 size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2); 978 size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
979 size_t const maxNbSeq2 = blockSize2 / ((cParams2.searchLength == 3) ? 3 : 4);
980 size_t const maxNbLit2 = blockSize2;
827 size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0; 981 size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
828 DEBUGLOG(4, "ZSTD_sufficientBuff: is windowSize2=%u <= wlog1=%u", 982 DEBUGLOG(4, "ZSTD_sufficientBuff: is neededBufferSize2=%u <= bufferSize1=%u",
829 (U32)windowSize2, cParams2.windowLog); 983 (U32)neededBufferSize2, (U32)bufferSize1);
830 DEBUGLOG(4, "ZSTD_sufficientBuff: is blockSize2=%u <= blockSize1=%u", 984 DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbSeq2=%u <= maxNbSeq1=%u",
831 (U32)blockSize2, (U32)blockSize1); 985 (U32)maxNbSeq2, (U32)maxNbSeq1);
832 return (blockSize2 <= blockSize1) /* seqStore space depends on blockSize */ 986 DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbLit2=%u <= maxNbLit1=%u",
987 (U32)maxNbLit2, (U32)maxNbLit1);
988 return (maxNbLit2 <= maxNbLit1)
989 & (maxNbSeq2 <= maxNbSeq1)
833 & (neededBufferSize2 <= bufferSize1); 990 & (neededBufferSize2 <= bufferSize1);
834 } 991 }
835 992
836 /** Equivalence for resetCCtx purposes */ 993 /** Equivalence for resetCCtx purposes */
837 static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1, 994 static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
838 ZSTD_CCtx_params params2, 995 ZSTD_CCtx_params params2,
839 size_t buffSize1, size_t blockSize1, 996 size_t buffSize1,
997 size_t maxNbSeq1, size_t maxNbLit1,
840 ZSTD_buffered_policy_e buffPol2, 998 ZSTD_buffered_policy_e buffPol2,
841 U64 pledgedSrcSize) 999 U64 pledgedSrcSize)
842 { 1000 {
843 DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize); 1001 DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
844 return ZSTD_equivalentCParams(params1.cParams, params2.cParams) && 1002 if (!ZSTD_equivalentCParams(params1.cParams, params2.cParams)) {
845 ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams) && 1003 DEBUGLOG(4, "ZSTD_equivalentCParams() == 0");
846 ZSTD_sufficientBuff(buffSize1, blockSize1, buffPol2, params2.cParams, pledgedSrcSize); 1004 return 0;
1005 }
1006 if (!ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams)) {
1007 DEBUGLOG(4, "ZSTD_equivalentLdmParams() == 0");
1008 return 0;
1009 }
1010 if (!ZSTD_sufficientBuff(buffSize1, maxNbSeq1, maxNbLit1, buffPol2,
1011 params2.cParams, pledgedSrcSize)) {
1012 DEBUGLOG(4, "ZSTD_sufficientBuff() == 0");
1013 return 0;
1014 }
1015 return 1;
847 } 1016 }
848 1017
849 static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs) 1018 static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
850 { 1019 {
851 int i; 1020 int i;
852 for (i = 0; i < ZSTD_REP_NUM; ++i) 1021 for (i = 0; i < ZSTD_REP_NUM; ++i)
853 bs->rep[i] = repStartValue[i]; 1022 bs->rep[i] = repStartValue[i];
854 bs->entropy.hufCTable_repeatMode = HUF_repeat_none; 1023 bs->entropy.huf.repeatMode = HUF_repeat_none;
855 bs->entropy.offcode_repeatMode = FSE_repeat_none; 1024 bs->entropy.fse.offcode_repeatMode = FSE_repeat_none;
856 bs->entropy.matchlength_repeatMode = FSE_repeat_none; 1025 bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;
857 bs->entropy.litlength_repeatMode = FSE_repeat_none; 1026 bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;
858 } 1027 }
859 1028
860 /*! ZSTD_invalidateMatchState() 1029 /*! ZSTD_invalidateMatchState()
861 * Invalidate all the matches in the match finder tables. 1030 * Invalidate all the matches in the match finder tables.
862 * Requires nextSrc and base to be set (can be NULL). 1031 * Requires nextSrc and base to be set (can be NULL).
864 static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) 1033 static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
865 { 1034 {
866 ZSTD_window_clear(&ms->window); 1035 ZSTD_window_clear(&ms->window);
867 1036
868 ms->nextToUpdate = ms->window.dictLimit + 1; 1037 ms->nextToUpdate = ms->window.dictLimit + 1;
1038 ms->nextToUpdate3 = ms->window.dictLimit + 1;
869 ms->loadedDictEnd = 0; 1039 ms->loadedDictEnd = 0;
870 ms->opt.litLengthSum = 0; /* force reset of btopt stats */ 1040 ms->opt.litLengthSum = 0; /* force reset of btopt stats */
1041 ms->dictMatchState = NULL;
871 } 1042 }
872 1043
873 /*! ZSTD_continueCCtx() : 1044 /*! ZSTD_continueCCtx() :
874 * reuse CCtx without reset (note : requires no dictionary) */ 1045 * reuse CCtx without reset (note : requires no dictionary) */
875 static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize) 1046 static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
878 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); 1049 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
879 DEBUGLOG(4, "ZSTD_continueCCtx: re-use context in place"); 1050 DEBUGLOG(4, "ZSTD_continueCCtx: re-use context in place");
880 1051
881 cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */ 1052 cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
882 cctx->appliedParams = params; 1053 cctx->appliedParams = params;
1054 cctx->blockState.matchState.cParams = params.cParams;
883 cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1; 1055 cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
884 cctx->consumedSrcSize = 0; 1056 cctx->consumedSrcSize = 0;
885 cctx->producedCSize = 0; 1057 cctx->producedCSize = 0;
886 if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN) 1058 if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
887 cctx->appliedParams.fParams.contentSizeFlag = 0; 1059 cctx->appliedParams.fParams.contentSizeFlag = 0;
898 return 0; 1070 return 0;
899 } 1071 }
900 1072
901 typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e; 1073 typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
902 1074
903 static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compressionParameters const* cParams, ZSTD_compResetPolicy_e const crp, U32 const forCCtx) 1075 static void*
1076 ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1077 void* ptr,
1078 const ZSTD_compressionParameters* cParams,
1079 ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
904 { 1080 {
905 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); 1081 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
906 size_t const hSize = ((size_t)1) << cParams->hashLog; 1082 size_t const hSize = ((size_t)1) << cParams->hashLog;
907 U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; 1083 U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
908 size_t const h3Size = ((size_t)1) << hashLog3; 1084 size_t const h3Size = ((size_t)1) << hashLog3;
910 1086
911 assert(((size_t)ptr & 3) == 0); 1087 assert(((size_t)ptr & 3) == 0);
912 1088
913 ms->hashLog3 = hashLog3; 1089 ms->hashLog3 = hashLog3;
914 memset(&ms->window, 0, sizeof(ms->window)); 1090 memset(&ms->window, 0, sizeof(ms->window));
1091 ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */
1092 ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
1093 ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
915 ZSTD_invalidateMatchState(ms); 1094 ZSTD_invalidateMatchState(ms);
916 1095
917 /* opt parser space */ 1096 /* opt parser space */
918 if (forCCtx && ((cParams->strategy == ZSTD_btopt) | (cParams->strategy == ZSTD_btultra))) { 1097 if (forCCtx && ((cParams->strategy == ZSTD_btopt) | (cParams->strategy == ZSTD_btultra))) {
919 DEBUGLOG(4, "reserving optimal parser space"); 1098 DEBUGLOG(4, "reserving optimal parser space");
935 ms->hashTable = (U32*)(ptr); 1114 ms->hashTable = (U32*)(ptr);
936 ms->chainTable = ms->hashTable + hSize; 1115 ms->chainTable = ms->hashTable + hSize;
937 ms->hashTable3 = ms->chainTable + chainSize; 1116 ms->hashTable3 = ms->chainTable + chainSize;
938 ptr = ms->hashTable3 + h3Size; 1117 ptr = ms->hashTable3 + h3Size;
939 1118
1119 ms->cParams = *cParams;
1120
940 assert(((size_t)ptr & 3) == 0); 1121 assert(((size_t)ptr & 3) == 0);
941 return ptr; 1122 return ptr;
942 } 1123 }
1124
1125 #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */
1126 #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large
1127 * during at least this number of times,
1128 * context's memory usage is considered wasteful,
1129 * because it's sized to handle a worst case scenario which rarely happens.
1130 * In which case, resize it down to free some memory */
943 1131
944 /*! ZSTD_resetCCtx_internal() : 1132 /*! ZSTD_resetCCtx_internal() :
945 note : `params` are assumed fully validated at this stage */ 1133 note : `params` are assumed fully validated at this stage */
946 static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, 1134 static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
947 ZSTD_CCtx_params params, U64 pledgedSrcSize, 1135 ZSTD_CCtx_params params,
1136 U64 pledgedSrcSize,
948 ZSTD_compResetPolicy_e const crp, 1137 ZSTD_compResetPolicy_e const crp,
949 ZSTD_buffered_policy_e const zbuff) 1138 ZSTD_buffered_policy_e const zbuff)
950 { 1139 {
951 DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u", 1140 DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
952 (U32)pledgedSrcSize, params.cParams.windowLog); 1141 (U32)pledgedSrcSize, params.cParams.windowLog);
953 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); 1142 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
954 1143
955 if (crp == ZSTDcrp_continue) { 1144 if (crp == ZSTDcrp_continue) {
956 if (ZSTD_equivalentParams(zc->appliedParams, params, 1145 if (ZSTD_equivalentParams(zc->appliedParams, params,
957 zc->inBuffSize, zc->blockSize, 1146 zc->inBuffSize,
958 zbuff, pledgedSrcSize)) { 1147 zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
959 DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%u)", 1148 zbuff, pledgedSrcSize)) {
960 zc->appliedParams.cParams.windowLog, (U32)zc->blockSize); 1149 DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
961 return ZSTD_continueCCtx(zc, params, pledgedSrcSize); 1150 zc->appliedParams.cParams.windowLog, zc->blockSize);
1151 zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
1152 if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
1153 return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
962 } } 1154 } }
963 DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx"); 1155 DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
964 1156
965 if (params.ldmParams.enableLdm) { 1157 if (params.ldmParams.enableLdm) {
966 /* Adjust long distance matching parameters */ 1158 /* Adjust long distance matching parameters */
967 params.ldmParams.windowLog = params.cParams.windowLog;
968 ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams); 1159 ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
969 assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); 1160 assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
970 assert(params.ldmParams.hashEveryLog < 32); 1161 assert(params.ldmParams.hashEveryLog < 32);
971 zc->ldmState.hashPower = 1162 zc->ldmState.hashPower = ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
972 ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
973 } 1163 }
974 1164
975 { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize)); 1165 { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
976 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); 1166 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
977 U32 const divider = (params.cParams.searchLength==3) ? 3 : 4; 1167 U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
978 size_t const maxNbSeq = blockSize / divider; 1168 size_t const maxNbSeq = blockSize / divider;
979 size_t const tokenSpace = blockSize + 11*maxNbSeq; 1169 size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
980 size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0; 1170 size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
981 size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0; 1171 size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
982 size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1); 1172 size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
983 size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize); 1173 size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
984 void* ptr; 1174 void* ptr; /* used to partition workSpace */
985 1175
986 /* Check if workSpace is large enough, alloc a new one if needed */ 1176 /* Check if workSpace is large enough, alloc a new one if needed */
987 { size_t const entropySpace = HUF_WORKSPACE_SIZE; 1177 { size_t const entropySpace = HUF_WORKSPACE_SIZE;
988 size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t); 1178 size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
989 size_t const bufferSpace = buffInSize + buffOutSize; 1179 size_t const bufferSpace = buffInSize + buffOutSize;
991 size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq); 1181 size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq);
992 1182
993 size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace + 1183 size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
994 ldmSeqSpace + matchStateSize + tokenSpace + 1184 ldmSeqSpace + matchStateSize + tokenSpace +
995 bufferSpace; 1185 bufferSpace;
996 DEBUGLOG(4, "Need %uKB workspace, including %uKB for match state, and %uKB for buffers", 1186
997 (U32)(neededSpace>>10), (U32)(matchStateSize>>10), (U32)(bufferSpace>>10)); 1187 int const workSpaceTooSmall = zc->workSpaceSize < neededSpace;
998 DEBUGLOG(4, "windowSize: %u - blockSize: %u", (U32)windowSize, (U32)blockSize); 1188 int const workSpaceTooLarge = zc->workSpaceSize > ZSTD_WORKSPACETOOLARGE_FACTOR * neededSpace;
999 1189 int const workSpaceWasteful = workSpaceTooLarge && (zc->workSpaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION);
1000 if (zc->workSpaceSize < neededSpace) { /* too small : resize */ 1190 zc->workSpaceOversizedDuration = workSpaceTooLarge ? zc->workSpaceOversizedDuration+1 : 0;
1001 DEBUGLOG(4, "Need to update workSpaceSize from %uK to %uK", 1191
1002 (unsigned)(zc->workSpaceSize>>10), 1192 DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
1003 (unsigned)(neededSpace>>10)); 1193 neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
1194 DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
1195
1196 if (workSpaceTooSmall || workSpaceWasteful) {
1197 DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB",
1198 zc->workSpaceSize >> 10,
1199 neededSpace >> 10);
1004 /* static cctx : no resize, error out */ 1200 /* static cctx : no resize, error out */
1005 if (zc->staticSize) return ERROR(memory_allocation); 1201 if (zc->staticSize) return ERROR(memory_allocation);
1006 1202
1007 zc->workSpaceSize = 0; 1203 zc->workSpaceSize = 0;
1008 ZSTD_free(zc->workSpace, zc->customMem); 1204 ZSTD_free(zc->workSpace, zc->customMem);
1009 zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem); 1205 zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
1010 if (zc->workSpace == NULL) return ERROR(memory_allocation); 1206 if (zc->workSpace == NULL) return ERROR(memory_allocation);
1011 zc->workSpaceSize = neededSpace; 1207 zc->workSpaceSize = neededSpace;
1012 ptr = zc->workSpace; 1208 zc->workSpaceOversizedDuration = 0;
1013 1209
1014 /* Statically sized space. entropyWorkspace never moves (but prev/next block swap places) */ 1210 /* Statically sized space.
1211 * entropyWorkspace never moves,
1212 * though prev/next block swap places */
1015 assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */ 1213 assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */
1016 assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t)); 1214 assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t));
1017 zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace; 1215 zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace;
1018 zc->blockState.nextCBlock = zc->blockState.prevCBlock + 1; 1216 zc->blockState.nextCBlock = zc->blockState.prevCBlock + 1;
1019 ptr = zc->blockState.nextCBlock + 1; 1217 ptr = zc->blockState.nextCBlock + 1;
1020 zc->entropyWorkspace = (U32*)ptr; 1218 zc->entropyWorkspace = (U32*)ptr;
1021 } } 1219 } }
1022 1220
1023 /* init params */ 1221 /* init params */
1024 zc->appliedParams = params; 1222 zc->appliedParams = params;
1223 zc->blockState.matchState.cParams = params.cParams;
1025 zc->pledgedSrcSizePlusOne = pledgedSrcSize+1; 1224 zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
1026 zc->consumedSrcSize = 0; 1225 zc->consumedSrcSize = 0;
1027 zc->producedCSize = 0; 1226 zc->producedCSize = 0;
1028 if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN) 1227 if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
1029 zc->appliedParams.fParams.contentSizeFlag = 0; 1228 zc->appliedParams.fParams.contentSizeFlag = 0;
1056 assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */ 1255 assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1057 1256
1058 ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1); 1257 ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
1059 1258
1060 /* sequences storage */ 1259 /* sequences storage */
1260 zc->seqStore.maxNbSeq = maxNbSeq;
1061 zc->seqStore.sequencesStart = (seqDef*)ptr; 1261 zc->seqStore.sequencesStart = (seqDef*)ptr;
1062 ptr = zc->seqStore.sequencesStart + maxNbSeq; 1262 ptr = zc->seqStore.sequencesStart + maxNbSeq;
1063 zc->seqStore.llCode = (BYTE*) ptr; 1263 zc->seqStore.llCode = (BYTE*) ptr;
1064 zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq; 1264 zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
1065 zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq; 1265 zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
1066 zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq; 1266 zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
1067 ptr = zc->seqStore.litStart + blockSize; 1267 /* ZSTD_wildcopy() is used to copy into the literals buffer,
1268 * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
1269 */
1270 zc->seqStore.maxNbLit = blockSize;
1271 ptr = zc->seqStore.litStart + blockSize + WILDCOPY_OVERLENGTH;
1068 1272
1069 /* ldm bucketOffsets table */ 1273 /* ldm bucketOffsets table */
1070 if (params.ldmParams.enableLdm) { 1274 if (params.ldmParams.enableLdm) {
1071 size_t const ldmBucketSize = 1275 size_t const ldmBucketSize =
1072 ((size_t)1) << (params.ldmParams.hashLog - 1276 ((size_t)1) << (params.ldmParams.hashLog -
1096 int i; 1300 int i;
1097 for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0; 1301 for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;
1098 assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window)); 1302 assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
1099 } 1303 }
1100 1304
1101 static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx, 1305 /* These are the approximate sizes for each strategy past which copying the
1306 * dictionary tables into the working context is faster than using them
1307 * in-place.
1308 */
1309 static const size_t attachDictSizeCutoffs[(unsigned)ZSTD_btultra+1] = {
1310 8 KB, /* unused */
1311 8 KB, /* ZSTD_fast */
1312 16 KB, /* ZSTD_dfast */
1313 32 KB, /* ZSTD_greedy */
1314 32 KB, /* ZSTD_lazy */
1315 32 KB, /* ZSTD_lazy2 */
1316 32 KB, /* ZSTD_btlazy2 */
1317 32 KB, /* ZSTD_btopt */
1318 8 KB /* ZSTD_btultra */
1319 };
1320
1321 static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
1322 ZSTD_CCtx_params params,
1323 U64 pledgedSrcSize)
1324 {
1325 size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
1326 return ( pledgedSrcSize <= cutoff
1327 || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
1328 || params.attachDictPref == ZSTD_dictForceAttach )
1329 && params.attachDictPref != ZSTD_dictForceCopy
1330 && !params.forceWindow; /* dictMatchState isn't correctly
1331 * handled in _enforceMaxDist */
1332 }
1333
1334 static size_t ZSTD_resetCCtx_byAttachingCDict(
1335 ZSTD_CCtx* cctx,
1336 const ZSTD_CDict* cdict,
1337 ZSTD_CCtx_params params,
1338 U64 pledgedSrcSize,
1339 ZSTD_buffered_policy_e zbuff)
1340 {
1341 {
1342 const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1343 unsigned const windowLog = params.cParams.windowLog;
1344 assert(windowLog != 0);
1345 /* Resize working context table params for input only, since the dict
1346 * has its own tables. */
1347 params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
1348 params.cParams.windowLog = windowLog;
1349 ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1350 ZSTDcrp_continue, zbuff);
1351 assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1352 }
1353
1354 {
1355 const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1356 - cdict->matchState.window.base);
1357 const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
1358 if (cdictLen == 0) {
1359 /* don't even attach dictionaries with no contents */
1360 DEBUGLOG(4, "skipping attaching empty dictionary");
1361 } else {
1362 DEBUGLOG(4, "attaching dictionary into context");
1363 cctx->blockState.matchState.dictMatchState = &cdict->matchState;
1364
1365 /* prep working match state so dict matches never have negative indices
1366 * when they are translated to the working context's index space. */
1367 if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {
1368 cctx->blockState.matchState.window.nextSrc =
1369 cctx->blockState.matchState.window.base + cdictEnd;
1370 ZSTD_window_clear(&cctx->blockState.matchState.window);
1371 }
1372 cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
1373 }
1374 }
1375
1376 cctx->dictID = cdict->dictID;
1377
1378 /* copy block state */
1379 memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
1380
1381 return 0;
1382 }
1383
1384 static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
1102 const ZSTD_CDict* cdict, 1385 const ZSTD_CDict* cdict,
1103 unsigned windowLog, 1386 ZSTD_CCtx_params params,
1104 ZSTD_frameParameters fParams,
1105 U64 pledgedSrcSize, 1387 U64 pledgedSrcSize,
1106 ZSTD_buffered_policy_e zbuff) 1388 ZSTD_buffered_policy_e zbuff)
1107 { 1389 {
1108 { ZSTD_CCtx_params params = cctx->requestedParams; 1390 const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1391
1392 DEBUGLOG(4, "copying dictionary into context");
1393
1394 { unsigned const windowLog = params.cParams.windowLog;
1395 assert(windowLog != 0);
1109 /* Copy only compression parameters related to tables. */ 1396 /* Copy only compression parameters related to tables. */
1110 params.cParams = cdict->cParams; 1397 params.cParams = *cdict_cParams;
1111 if (windowLog) params.cParams.windowLog = windowLog; 1398 params.cParams.windowLog = windowLog;
1112 params.fParams = fParams;
1113 ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, 1399 ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1114 ZSTDcrp_noMemset, zbuff); 1400 ZSTDcrp_noMemset, zbuff);
1115 assert(cctx->appliedParams.cParams.strategy == cdict->cParams.strategy); 1401 assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1116 assert(cctx->appliedParams.cParams.hashLog == cdict->cParams.hashLog); 1402 assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
1117 assert(cctx->appliedParams.cParams.chainLog == cdict->cParams.chainLog); 1403 assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
1118 } 1404 }
1119 1405
1120 /* copy tables */ 1406 /* copy tables */
1121 { size_t const chainSize = (cdict->cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict->cParams.chainLog); 1407 { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
1122 size_t const hSize = (size_t)1 << cdict->cParams.hashLog; 1408 size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
1123 size_t const tableSpace = (chainSize + hSize) * sizeof(U32); 1409 size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
1124 assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */ 1410 assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1125 assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize); 1411 assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
1126 assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */ 1412 assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
1127 assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize); 1413 assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
1128 memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */ 1414 memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1129 } 1415 }
1416
1130 /* Zero the hashTable3, since the cdict never fills it */ 1417 /* Zero the hashTable3, since the cdict never fills it */
1131 { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3; 1418 { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
1132 assert(cdict->matchState.hashLog3 == 0); 1419 assert(cdict->matchState.hashLog3 == 0);
1133 memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); 1420 memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1134 } 1421 }
1135 1422
1136 /* copy dictionary offsets */ 1423 /* copy dictionary offsets */
1137 { 1424 { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1138 ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1139 ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState; 1425 ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1140 dstMatchState->window = srcMatchState->window; 1426 dstMatchState->window = srcMatchState->window;
1141 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; 1427 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1142 dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3; 1428 dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1143 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; 1429 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1144 } 1430 }
1431
1145 cctx->dictID = cdict->dictID; 1432 cctx->dictID = cdict->dictID;
1146 1433
1147 /* copy block state */ 1434 /* copy block state */
1148 memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); 1435 memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
1149 1436
1150 return 0; 1437 return 0;
1438 }
1439
1440 /* We have a choice between copying the dictionary context into the working
1441 * context, or referencing the dictionary context from the working context
1442 * in-place. We decide here which strategy to use. */
1443 static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1444 const ZSTD_CDict* cdict,
1445 ZSTD_CCtx_params params,
1446 U64 pledgedSrcSize,
1447 ZSTD_buffered_policy_e zbuff)
1448 {
1449
1450 DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
1451
1452 if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
1453 return ZSTD_resetCCtx_byAttachingCDict(
1454 cctx, cdict, params, pledgedSrcSize, zbuff);
1455 } else {
1456 return ZSTD_resetCCtx_byCopyingCDict(
1457 cctx, cdict, params, pledgedSrcSize, zbuff);
1458 }
1151 } 1459 }
1152 1460
1153 /*! ZSTD_copyCCtx_internal() : 1461 /*! ZSTD_copyCCtx_internal() :
1154 * Duplicate an existing context `srcCCtx` into another one `dstCCtx`. 1462 * Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
1155 * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). 1463 * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
1190 memcpy(dstCCtx->blockState.matchState.hashTable, srcCCtx->blockState.matchState.hashTable, tableSpace); /* presumes all tables follow each other */ 1498 memcpy(dstCCtx->blockState.matchState.hashTable, srcCCtx->blockState.matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1191 } 1499 }
1192 1500
1193 /* copy dictionary offsets */ 1501 /* copy dictionary offsets */
1194 { 1502 {
1195 ZSTD_matchState_t const* srcMatchState = &srcCCtx->blockState.matchState; 1503 const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
1196 ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState; 1504 ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
1197 dstMatchState->window = srcMatchState->window; 1505 dstMatchState->window = srcMatchState->window;
1198 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; 1506 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1199 dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3; 1507 dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1200 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; 1508 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1292 * Block entropic compression 1600 * Block entropic compression
1293 *********************************************************/ 1601 *********************************************************/
1294 1602
1295 /* See doc/zstd_compression_format.md for detailed format description */ 1603 /* See doc/zstd_compression_format.md for detailed format description */
1296 1604
1297 size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize) 1605 static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
1298 { 1606 {
1607 U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
1299 if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall); 1608 if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
1609 MEM_writeLE24(dst, cBlockHeader24);
1300 memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); 1610 memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
1301 MEM_writeLE24(dst, (U32)(srcSize << 2) + (U32)bt_raw); 1611 return ZSTD_blockHeaderSize + srcSize;
1302 return ZSTD_blockHeaderSize+srcSize; 1612 }
1303 }
1304
1305 1613
1306 static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize) 1614 static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1307 { 1615 {
1308 BYTE* const ostart = (BYTE* const)dst; 1616 BYTE* const ostart = (BYTE* const)dst;
1309 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); 1617 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
1354 ostart[flSize] = *(const BYTE*)src; 1662 ostart[flSize] = *(const BYTE*)src;
1355 return flSize+1; 1663 return flSize+1;
1356 } 1664 }
1357 1665
1358 1666
1359 static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; } 1667 /* ZSTD_minGain() :
1360 1668 * minimum compression required
1361 static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy, 1669 * to generate a compress block or a compressed literals section.
1362 ZSTD_entropyCTables_t* nextEntropy, 1670 * note : use same formula for both situations */
1671 static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
1672 {
1673 U32 const minlog = (strat==ZSTD_btultra) ? 7 : 6;
1674 return (srcSize >> minlog) + 2;
1675 }
1676
1677 static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
1678 ZSTD_hufCTables_t* nextHuf,
1363 ZSTD_strategy strategy, int disableLiteralCompression, 1679 ZSTD_strategy strategy, int disableLiteralCompression,
1364 void* dst, size_t dstCapacity, 1680 void* dst, size_t dstCapacity,
1365 const void* src, size_t srcSize, 1681 const void* src, size_t srcSize,
1366 U32* workspace, const int bmi2) 1682 U32* workspace, const int bmi2)
1367 { 1683 {
1368 size_t const minGain = ZSTD_minGain(srcSize); 1684 size_t const minGain = ZSTD_minGain(srcSize, strategy);
1369 size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB); 1685 size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
1370 BYTE* const ostart = (BYTE*)dst; 1686 BYTE* const ostart = (BYTE*)dst;
1371 U32 singleStream = srcSize < 256; 1687 U32 singleStream = srcSize < 256;
1372 symbolEncodingType_e hType = set_compressed; 1688 symbolEncodingType_e hType = set_compressed;
1373 size_t cLitSize; 1689 size_t cLitSize;
1374 1690
1375 DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)", 1691 DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
1376 disableLiteralCompression); 1692 disableLiteralCompression);
1377 1693
1378 /* Prepare nextEntropy assuming reusing the existing table */ 1694 /* Prepare nextEntropy assuming reusing the existing table */
1379 nextEntropy->hufCTable_repeatMode = prevEntropy->hufCTable_repeatMode; 1695 memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1380 memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable,
1381 sizeof(prevEntropy->hufCTable));
1382 1696
1383 if (disableLiteralCompression) 1697 if (disableLiteralCompression)
1384 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); 1698 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1385 1699
1386 /* small ? don't even attempt compression (speed opt) */ 1700 /* small ? don't even attempt compression (speed opt) */
1387 # define COMPRESS_LITERALS_SIZE_MIN 63 1701 # define COMPRESS_LITERALS_SIZE_MIN 63
1388 { size_t const minLitSize = (prevEntropy->hufCTable_repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN; 1702 { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
1389 if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); 1703 if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1390 } 1704 }
1391 1705
1392 if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */ 1706 if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
1393 { HUF_repeat repeat = prevEntropy->hufCTable_repeatMode; 1707 { HUF_repeat repeat = prevHuf->repeatMode;
1394 int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0; 1708 int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
1395 if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1; 1709 if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
1396 cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11, 1710 cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1397 workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2) 1711 workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
1398 : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11, 1712 : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1399 workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2); 1713 workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
1400 if (repeat != HUF_repeat_none) { 1714 if (repeat != HUF_repeat_none) {
1401 /* reused the existing table */ 1715 /* reused the existing table */
1402 hType = set_repeat; 1716 hType = set_repeat;
1403 } 1717 }
1404 } 1718 }
1405 1719
1406 if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) { 1720 if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
1407 memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable)); 1721 memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1408 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); 1722 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1409 } 1723 }
1410 if (cLitSize==1) { 1724 if (cLitSize==1) {
1411 memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable)); 1725 memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1412 return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); 1726 return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
1413 } 1727 }
1414 1728
1415 if (hType == set_compressed) { 1729 if (hType == set_compressed) {
1416 /* using a newly constructed table */ 1730 /* using a newly constructed table */
1417 nextEntropy->hufCTable_repeatMode = HUF_repeat_check; 1731 nextHuf->repeatMode = HUF_repeat_check;
1418 } 1732 }
1419 1733
1420 /* Build header */ 1734 /* Build header */
1421 switch(lhSize) 1735 switch(lhSize)
1422 { 1736 {
1449 BYTE* const llCodeTable = seqStorePtr->llCode; 1763 BYTE* const llCodeTable = seqStorePtr->llCode;
1450 BYTE* const ofCodeTable = seqStorePtr->ofCode; 1764 BYTE* const ofCodeTable = seqStorePtr->ofCode;
1451 BYTE* const mlCodeTable = seqStorePtr->mlCode; 1765 BYTE* const mlCodeTable = seqStorePtr->mlCode;
1452 U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); 1766 U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
1453 U32 u; 1767 U32 u;
1768 assert(nbSeq <= seqStorePtr->maxNbSeq);
1454 for (u=0; u<nbSeq; u++) { 1769 for (u=0; u<nbSeq; u++) {
1455 U32 const llv = sequences[u].litLength; 1770 U32 const llv = sequences[u].litLength;
1456 U32 const mlv = sequences[u].matchLength; 1771 U32 const mlv = sequences[u].matchLength;
1457 llCodeTable[u] = (BYTE)ZSTD_LLcode(llv); 1772 llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
1458 ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset); 1773 ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
1462 llCodeTable[seqStorePtr->longLengthPos] = MaxLL; 1777 llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
1463 if (seqStorePtr->longLengthID==2) 1778 if (seqStorePtr->longLengthID==2)
1464 mlCodeTable[seqStorePtr->longLengthPos] = MaxML; 1779 mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
1465 } 1780 }
1466 1781
1782
1783 /**
1784 * -log2(x / 256) lookup table for x in [0, 256).
1785 * If x == 0: Return 0
1786 * Else: Return floor(-log2(x / 256) * 256)
1787 */
1788 static unsigned const kInverseProbabiltyLog256[256] = {
1789 0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
1790 1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
1791 874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
1792 724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
1793 618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
1794 535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
1795 468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
1796 411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
1797 362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
1798 318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
1799 279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
1800 244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
1801 212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
1802 182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
1803 155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
1804 130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
1805 106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
1806 83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
1807 62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
1808 42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
1809 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
1810 5, 4, 2, 1,
1811 };
1812
1813
1814 /**
1815 * Returns the cost in bits of encoding the distribution described by count
1816 * using the entropy bound.
1817 */
1818 static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
1819 {
1820 unsigned cost = 0;
1821 unsigned s;
1822 for (s = 0; s <= max; ++s) {
1823 unsigned norm = (unsigned)((256 * count[s]) / total);
1824 if (count[s] != 0 && norm == 0)
1825 norm = 1;
1826 assert(count[s] < total);
1827 cost += count[s] * kInverseProbabiltyLog256[norm];
1828 }
1829 return cost >> 8;
1830 }
1831
1832
1833 /**
1834 * Returns the cost in bits of encoding the distribution in count using the
1835 * table described by norm. The max symbol support by norm is assumed >= max.
1836 * norm must be valid for every symbol with non-zero probability in count.
1837 */
1838 static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
1839 unsigned const* count, unsigned const max)
1840 {
1841 unsigned const shift = 8 - accuracyLog;
1842 size_t cost = 0;
1843 unsigned s;
1844 assert(accuracyLog <= 8);
1845 for (s = 0; s <= max; ++s) {
1846 unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
1847 unsigned const norm256 = normAcc << shift;
1848 assert(norm256 > 0);
1849 assert(norm256 < 256);
1850 cost += count[s] * kInverseProbabiltyLog256[norm256];
1851 }
1852 return cost >> 8;
1853 }
1854
1855
1856 static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
1857 void const* ptr = ctable;
1858 U16 const* u16ptr = (U16 const*)ptr;
1859 U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
1860 return maxSymbolValue;
1861 }
1862
1863
1864 /**
1865 * Returns the cost in bits of encoding the distribution in count using ctable.
1866 * Returns an error if ctable cannot represent all the symbols in count.
1867 */
1868 static size_t ZSTD_fseBitCost(
1869 FSE_CTable const* ctable,
1870 unsigned const* count,
1871 unsigned const max)
1872 {
1873 unsigned const kAccuracyLog = 8;
1874 size_t cost = 0;
1875 unsigned s;
1876 FSE_CState_t cstate;
1877 FSE_initCState(&cstate, ctable);
1878 if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {
1879 DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u",
1880 ZSTD_getFSEMaxSymbolValue(ctable), max);
1881 return ERROR(GENERIC);
1882 }
1883 for (s = 0; s <= max; ++s) {
1884 unsigned const tableLog = cstate.stateLog;
1885 unsigned const badCost = (tableLog + 1) << kAccuracyLog;
1886 unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
1887 if (count[s] == 0)
1888 continue;
1889 if (bitCost >= badCost) {
1890 DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s);
1891 return ERROR(GENERIC);
1892 }
1893 cost += count[s] * bitCost;
1894 }
1895 return cost >> kAccuracyLog;
1896 }
1897
1898 /**
1899 * Returns the cost in bytes of encoding the normalized count header.
1900 * Returns an error if any of the helper functions return an error.
1901 */
1902 static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
1903 size_t const nbSeq, unsigned const FSELog)
1904 {
1905 BYTE wksp[FSE_NCOUNTBOUND];
1906 S16 norm[MaxSeq + 1];
1907 const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
1908 CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
1909 return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
1910 }
1911
1912
1467 typedef enum { 1913 typedef enum {
1468 ZSTD_defaultDisallowed = 0, 1914 ZSTD_defaultDisallowed = 0,
1469 ZSTD_defaultAllowed = 1 1915 ZSTD_defaultAllowed = 1
1470 } ZSTD_defaultPolicy_e; 1916 } ZSTD_defaultPolicy_e;
1471 1917
1472 MEM_STATIC 1918 MEM_STATIC symbolEncodingType_e
1473 symbolEncodingType_e ZSTD_selectEncodingType( 1919 ZSTD_selectEncodingType(
1474 FSE_repeat* repeatMode, size_t const mostFrequent, size_t nbSeq, 1920 FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
1475 U32 defaultNormLog, ZSTD_defaultPolicy_e const isDefaultAllowed) 1921 size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
1476 { 1922 FSE_CTable const* prevCTable,
1477 #define MIN_SEQ_FOR_DYNAMIC_FSE 64 1923 short const* defaultNorm, U32 defaultNormLog,
1478 #define MAX_SEQ_FOR_STATIC_FSE 1000 1924 ZSTD_defaultPolicy_e const isDefaultAllowed,
1925 ZSTD_strategy const strategy)
1926 {
1479 ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0); 1927 ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
1480 if ((mostFrequent == nbSeq) && (!isDefaultAllowed || nbSeq > 2)) { 1928 if (mostFrequent == nbSeq) {
1929 *repeatMode = FSE_repeat_none;
1930 if (isDefaultAllowed && nbSeq <= 2) {
1931 /* Prefer set_basic over set_rle when there are 2 or less symbols,
1932 * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
1933 * If basic encoding isn't possible, always choose RLE.
1934 */
1935 DEBUGLOG(5, "Selected set_basic");
1936 return set_basic;
1937 }
1481 DEBUGLOG(5, "Selected set_rle"); 1938 DEBUGLOG(5, "Selected set_rle");
1482 /* Prefer set_basic over set_rle when there are 2 or less symbols,
1483 * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
1484 * If basic encoding isn't possible, always choose RLE.
1485 */
1486 *repeatMode = FSE_repeat_check;
1487 return set_rle; 1939 return set_rle;
1488 } 1940 }
1489 if ( isDefaultAllowed 1941 if (strategy < ZSTD_lazy) {
1490 && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) { 1942 if (isDefaultAllowed) {
1491 DEBUGLOG(5, "Selected set_repeat"); 1943 size_t const staticFse_nbSeq_max = 1000;
1492 return set_repeat; 1944 size_t const mult = 10 - strategy;
1493 } 1945 size_t const baseLog = 3;
1494 if ( isDefaultAllowed 1946 size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
1495 && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1)))) ) { 1947 assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
1496 DEBUGLOG(5, "Selected set_basic"); 1948 assert(mult <= 9 && mult >= 7);
1497 /* The format allows default tables to be repeated, but it isn't useful. 1949 if ( (*repeatMode == FSE_repeat_valid)
1498 * When using simple heuristics to select encoding type, we don't want 1950 && (nbSeq < staticFse_nbSeq_max) ) {
1499 * to confuse these tables with dictionaries. When running more careful 1951 DEBUGLOG(5, "Selected set_repeat");
1500 * analysis, we don't need to waste time checking both repeating tables 1952 return set_repeat;
1501 * and default tables. 1953 }
1502 */ 1954 if ( (nbSeq < dynamicFse_nbSeq_min)
1503 *repeatMode = FSE_repeat_none; 1955 || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
1504 return set_basic; 1956 DEBUGLOG(5, "Selected set_basic");
1957 /* The format allows default tables to be repeated, but it isn't useful.
1958 * When using simple heuristics to select encoding type, we don't want
1959 * to confuse these tables with dictionaries. When running more careful
1960 * analysis, we don't need to waste time checking both repeating tables
1961 * and default tables.
1962 */
1963 *repeatMode = FSE_repeat_none;
1964 return set_basic;
1965 }
1966 }
1967 } else {
1968 size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
1969 size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
1970 size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
1971 size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
1972
1973 if (isDefaultAllowed) {
1974 assert(!ZSTD_isError(basicCost));
1975 assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
1976 }
1977 assert(!ZSTD_isError(NCountCost));
1978 assert(compressedCost < ERROR(maxCode));
1979 DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
1980 (U32)basicCost, (U32)repeatCost, (U32)compressedCost);
1981 if (basicCost <= repeatCost && basicCost <= compressedCost) {
1982 DEBUGLOG(5, "Selected set_basic");
1983 assert(isDefaultAllowed);
1984 *repeatMode = FSE_repeat_none;
1985 return set_basic;
1986 }
1987 if (repeatCost <= compressedCost) {
1988 DEBUGLOG(5, "Selected set_repeat");
1989 assert(!ZSTD_isError(repeatCost));
1990 return set_repeat;
1991 }
1992 assert(compressedCost < basicCost && compressedCost < repeatCost);
1505 } 1993 }
1506 DEBUGLOG(5, "Selected set_compressed"); 1994 DEBUGLOG(5, "Selected set_compressed");
1507 *repeatMode = FSE_repeat_check; 1995 *repeatMode = FSE_repeat_check;
1508 return set_compressed; 1996 return set_compressed;
1509 } 1997 }
1510 1998
1511 MEM_STATIC 1999 MEM_STATIC size_t
1512 size_t ZSTD_buildCTable(void* dst, size_t dstCapacity, 2000 ZSTD_buildCTable(void* dst, size_t dstCapacity,
1513 FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type, 2001 FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
1514 U32* count, U32 max, 2002 U32* count, U32 max,
1515 BYTE const* codeTable, size_t nbSeq, 2003 const BYTE* codeTable, size_t nbSeq,
1516 S16 const* defaultNorm, U32 defaultNormLog, U32 defaultMax, 2004 const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
1517 FSE_CTable const* prevCTable, size_t prevCTableSize, 2005 const FSE_CTable* prevCTable, size_t prevCTableSize,
1518 void* workspace, size_t workspaceSize) 2006 void* workspace, size_t workspaceSize)
1519 { 2007 {
1520 BYTE* op = (BYTE*)dst; 2008 BYTE* op = (BYTE*)dst;
1521 BYTE const* const oend = op + dstCapacity; 2009 const BYTE* const oend = op + dstCapacity;
1522 2010
1523 switch (type) { 2011 switch (type) {
1524 case set_rle: 2012 case set_rle:
1525 *op = codeTable[0]; 2013 *op = codeTable[0];
1526 CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max)); 2014 CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
1672 sequences, nbSeq, longOffsets); 2160 sequences, nbSeq, longOffsets);
1673 } 2161 }
1674 2162
1675 #endif 2163 #endif
1676 2164
1677 size_t ZSTD_encodeSequences( 2165 static size_t ZSTD_encodeSequences(
1678 void* dst, size_t dstCapacity, 2166 void* dst, size_t dstCapacity,
1679 FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable, 2167 FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1680 FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable, 2168 FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1681 FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable, 2169 FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1682 seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2) 2170 seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
1704 ZSTD_CCtx_params const* cctxParams, 2192 ZSTD_CCtx_params const* cctxParams,
1705 void* dst, size_t dstCapacity, U32* workspace, 2193 void* dst, size_t dstCapacity, U32* workspace,
1706 const int bmi2) 2194 const int bmi2)
1707 { 2195 {
1708 const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN; 2196 const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
2197 ZSTD_strategy const strategy = cctxParams->cParams.strategy;
1709 U32 count[MaxSeq+1]; 2198 U32 count[MaxSeq+1];
1710 FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable; 2199 FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
1711 FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable; 2200 FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
1712 FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable; 2201 FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
1713 U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ 2202 U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
1714 const seqDef* const sequences = seqStorePtr->sequencesStart; 2203 const seqDef* const sequences = seqStorePtr->sequencesStart;
1715 const BYTE* const ofCodeTable = seqStorePtr->ofCode; 2204 const BYTE* const ofCodeTable = seqStorePtr->ofCode;
1716 const BYTE* const llCodeTable = seqStorePtr->llCode; 2205 const BYTE* const llCodeTable = seqStorePtr->llCode;
1717 const BYTE* const mlCodeTable = seqStorePtr->mlCode; 2206 const BYTE* const mlCodeTable = seqStorePtr->mlCode;
1718 BYTE* const ostart = (BYTE*)dst; 2207 BYTE* const ostart = (BYTE*)dst;
1719 BYTE* const oend = ostart + dstCapacity; 2208 BYTE* const oend = ostart + dstCapacity;
1720 BYTE* op = ostart; 2209 BYTE* op = ostart;
1721 size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; 2210 size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
1722 BYTE* seqHead; 2211 BYTE* seqHead;
2212 BYTE* lastNCount = NULL;
1723 2213
1724 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog))); 2214 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
1725 2215
1726 /* Compress literals */ 2216 /* Compress literals */
1727 { const BYTE* const literals = seqStorePtr->litStart; 2217 { const BYTE* const literals = seqStorePtr->litStart;
1728 size_t const litSize = seqStorePtr->lit - literals; 2218 size_t const litSize = seqStorePtr->lit - literals;
2219 int const disableLiteralCompression = (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
1729 size_t const cSize = ZSTD_compressLiterals( 2220 size_t const cSize = ZSTD_compressLiterals(
1730 prevEntropy, nextEntropy, 2221 &prevEntropy->huf, &nextEntropy->huf,
1731 cctxParams->cParams.strategy, cctxParams->disableLiteralCompression, 2222 cctxParams->cParams.strategy, disableLiteralCompression,
1732 op, dstCapacity, 2223 op, dstCapacity,
1733 literals, litSize, 2224 literals, litSize,
1734 workspace, bmi2); 2225 workspace, bmi2);
1735 if (ZSTD_isError(cSize)) 2226 if (ZSTD_isError(cSize))
1736 return cSize; 2227 return cSize;
1745 else if (nbSeq < LONGNBSEQ) 2236 else if (nbSeq < LONGNBSEQ)
1746 op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2; 2237 op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
1747 else 2238 else
1748 op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3; 2239 op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1749 if (nbSeq==0) { 2240 if (nbSeq==0) {
1750 memcpy(nextEntropy->litlengthCTable, prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable)); 2241 /* Copy the old tables over as if we repeated them */
1751 nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode; 2242 memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
1752 memcpy(nextEntropy->offcodeCTable, prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable)); 2243 return op - ostart;
1753 nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
1754 memcpy(nextEntropy->matchlengthCTable, prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable));
1755 nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
1756 return op - ostart;
1757 } 2244 }
1758 2245
1759 /* seqHead : flags for FSE encoding type */ 2246 /* seqHead : flags for FSE encoding type */
1760 seqHead = op++; 2247 seqHead = op++;
1761 2248
1762 /* convert length/distances into codes */ 2249 /* convert length/distances into codes */
1763 ZSTD_seqToCodes(seqStorePtr); 2250 ZSTD_seqToCodes(seqStorePtr);
1764 /* build CTable for Literal Lengths */ 2251 /* build CTable for Literal Lengths */
1765 { U32 max = MaxLL; 2252 { U32 max = MaxLL;
1766 size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace); 2253 size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace); /* can't fail */
1767 DEBUGLOG(5, "Building LL table"); 2254 DEBUGLOG(5, "Building LL table");
1768 nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode; 2255 nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
1769 LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed); 2256 LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode, count, max, mostFrequent, nbSeq, LLFSELog, prevEntropy->fse.litlengthCTable, LL_defaultNorm, LL_defaultNormLog, ZSTD_defaultAllowed, strategy);
2257 assert(set_basic < set_compressed && set_rle < set_compressed);
2258 assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
1770 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype, 2259 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
1771 count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL, 2260 count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
1772 prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable), 2261 prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
1773 workspace, HUF_WORKSPACE_SIZE); 2262 workspace, HUF_WORKSPACE_SIZE);
1774 if (ZSTD_isError(countSize)) return countSize; 2263 if (ZSTD_isError(countSize)) return countSize;
2264 if (LLtype == set_compressed)
2265 lastNCount = op;
1775 op += countSize; 2266 op += countSize;
1776 } } 2267 } }
1777 /* build CTable for Offsets */ 2268 /* build CTable for Offsets */
1778 { U32 max = MaxOff; 2269 { U32 max = MaxOff;
1779 size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace); 2270 size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace); /* can't fail */
1780 /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ 2271 /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
1781 ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; 2272 ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
1782 DEBUGLOG(5, "Building OF table"); 2273 DEBUGLOG(5, "Building OF table");
1783 nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode; 2274 nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode;
1784 Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy); 2275 Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode, count, max, mostFrequent, nbSeq, OffFSELog, prevEntropy->fse.offcodeCTable, OF_defaultNorm, OF_defaultNormLog, defaultPolicy, strategy);
2276 assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
1785 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype, 2277 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
1786 count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, 2278 count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
1787 prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable), 2279 prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
1788 workspace, HUF_WORKSPACE_SIZE); 2280 workspace, HUF_WORKSPACE_SIZE);
1789 if (ZSTD_isError(countSize)) return countSize; 2281 if (ZSTD_isError(countSize)) return countSize;
2282 if (Offtype == set_compressed)
2283 lastNCount = op;
1790 op += countSize; 2284 op += countSize;
1791 } } 2285 } }
1792 /* build CTable for MatchLengths */ 2286 /* build CTable for MatchLengths */
1793 { U32 max = MaxML; 2287 { U32 max = MaxML;
1794 size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace); 2288 size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace); /* can't fail */
1795 DEBUGLOG(5, "Building ML table"); 2289 DEBUGLOG(5, "Building ML table");
1796 nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode; 2290 nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
1797 MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed); 2291 MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode, count, max, mostFrequent, nbSeq, MLFSELog, prevEntropy->fse.matchlengthCTable, ML_defaultNorm, ML_defaultNormLog, ZSTD_defaultAllowed, strategy);
2292 assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
1798 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype, 2293 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
1799 count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML, 2294 count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
1800 prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable), 2295 prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
1801 workspace, HUF_WORKSPACE_SIZE); 2296 workspace, HUF_WORKSPACE_SIZE);
1802 if (ZSTD_isError(countSize)) return countSize; 2297 if (ZSTD_isError(countSize)) return countSize;
2298 if (MLtype == set_compressed)
2299 lastNCount = op;
1803 op += countSize; 2300 op += countSize;
1804 } } 2301 } }
1805 2302
1806 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); 2303 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
1807 2304
1812 CTable_LitLength, llCodeTable, 2309 CTable_LitLength, llCodeTable,
1813 sequences, nbSeq, 2310 sequences, nbSeq,
1814 longOffsets, bmi2); 2311 longOffsets, bmi2);
1815 if (ZSTD_isError(bitstreamSize)) return bitstreamSize; 2312 if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
1816 op += bitstreamSize; 2313 op += bitstreamSize;
2314 /* zstd versions <= 1.3.4 mistakenly report corruption when
2315 * FSE_readNCount() recieves a buffer < 4 bytes.
2316 * Fixed by https://github.com/facebook/zstd/pull/1146.
2317 * This can happen when the last set_compressed table present is 2
2318 * bytes and the bitstream is only one byte.
2319 * In this exceedingly rare case, we will simply emit an uncompressed
2320 * block, since it isn't worth optimizing.
2321 */
2322 if (lastNCount && (op - lastNCount) < 4) {
2323 /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
2324 assert(op - lastNCount == 3);
2325 DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
2326 "emitting an uncompressed block.");
2327 return 0;
2328 }
1817 } 2329 }
1818 2330
1819 return op - ostart; 2331 return op - ostart;
1820 } 2332 }
1821 2333
1822 MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr, 2334 MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1823 ZSTD_entropyCTables_t const* prevEntropy, 2335 const ZSTD_entropyCTables_t* prevEntropy,
1824 ZSTD_entropyCTables_t* nextEntropy, 2336 ZSTD_entropyCTables_t* nextEntropy,
1825 ZSTD_CCtx_params const* cctxParams, 2337 const ZSTD_CCtx_params* cctxParams,
1826 void* dst, size_t dstCapacity, 2338 void* dst, size_t dstCapacity,
1827 size_t srcSize, U32* workspace, int bmi2) 2339 size_t srcSize, U32* workspace, int bmi2)
1828 { 2340 {
1829 size_t const cSize = ZSTD_compressSequences_internal( 2341 size_t const cSize = ZSTD_compressSequences_internal(
1830 seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity, 2342 seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity,
1831 workspace, bmi2); 2343 workspace, bmi2);
2344 if (cSize == 0) return 0;
1832 /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block. 2345 /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
1833 * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block. 2346 * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
1834 */ 2347 */
1835 if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) 2348 if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
1836 return 0; /* block not compressed */ 2349 return 0; /* block not compressed */
1837 if (ZSTD_isError(cSize)) return cSize; 2350 if (ZSTD_isError(cSize)) return cSize;
1838 2351
1839 /* Check compressibility */ 2352 /* Check compressibility */
1840 { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize); /* note : fixed formula, maybe should depend on compression level, or strategy */ 2353 { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
1841 if (cSize >= maxCSize) return 0; /* block not compressed */ 2354 if (cSize >= maxCSize) return 0; /* block not compressed */
1842 } 2355 }
1843
1844 /* We check that dictionaries have offset codes available for the first
1845 * block. After the first block, the offcode table might not have large
1846 * enough codes to represent the offsets in the data.
1847 */
1848 if (nextEntropy->offcode_repeatMode == FSE_repeat_valid)
1849 nextEntropy->offcode_repeatMode = FSE_repeat_check;
1850 2356
1851 return cSize; 2357 return cSize;
1852 } 2358 }
1853 2359
1854 /* ZSTD_selectBlockCompressor() : 2360 /* ZSTD_selectBlockCompressor() :
1855 * Not static, but internal use only (used by long distance matcher) 2361 * Not static, but internal use only (used by long distance matcher)
1856 * assumption : strat is a valid strategy */ 2362 * assumption : strat is a valid strategy */
1857 ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict) 2363 ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode)
1858 { 2364 {
1859 static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = { 2365 static const ZSTD_blockCompressor blockCompressor[3][(unsigned)ZSTD_btultra+1] = {
1860 { ZSTD_compressBlock_fast /* default for 0 */, 2366 { ZSTD_compressBlock_fast /* default for 0 */,
1861 ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy, 2367 ZSTD_compressBlock_fast,
1862 ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, 2368 ZSTD_compressBlock_doubleFast,
1863 ZSTD_compressBlock_btopt, ZSTD_compressBlock_btultra }, 2369 ZSTD_compressBlock_greedy,
2370 ZSTD_compressBlock_lazy,
2371 ZSTD_compressBlock_lazy2,
2372 ZSTD_compressBlock_btlazy2,
2373 ZSTD_compressBlock_btopt,
2374 ZSTD_compressBlock_btultra },
1864 { ZSTD_compressBlock_fast_extDict /* default for 0 */, 2375 { ZSTD_compressBlock_fast_extDict /* default for 0 */,
1865 ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict, 2376 ZSTD_compressBlock_fast_extDict,
1866 ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, 2377 ZSTD_compressBlock_doubleFast_extDict,
1867 ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btultra_extDict } 2378 ZSTD_compressBlock_greedy_extDict,
2379 ZSTD_compressBlock_lazy_extDict,
2380 ZSTD_compressBlock_lazy2_extDict,
2381 ZSTD_compressBlock_btlazy2_extDict,
2382 ZSTD_compressBlock_btopt_extDict,
2383 ZSTD_compressBlock_btultra_extDict },
2384 { ZSTD_compressBlock_fast_dictMatchState /* default for 0 */,
2385 ZSTD_compressBlock_fast_dictMatchState,
2386 ZSTD_compressBlock_doubleFast_dictMatchState,
2387 ZSTD_compressBlock_greedy_dictMatchState,
2388 ZSTD_compressBlock_lazy_dictMatchState,
2389 ZSTD_compressBlock_lazy2_dictMatchState,
2390 ZSTD_compressBlock_btlazy2_dictMatchState,
2391 ZSTD_compressBlock_btopt_dictMatchState,
2392 ZSTD_compressBlock_btultra_dictMatchState }
1868 }; 2393 };
2394 ZSTD_blockCompressor selectedCompressor;
1869 ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); 2395 ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
1870 2396
1871 assert((U32)strat >= (U32)ZSTD_fast); 2397 assert((U32)strat >= (U32)ZSTD_fast);
1872 assert((U32)strat <= (U32)ZSTD_btultra); 2398 assert((U32)strat <= (U32)ZSTD_btultra);
1873 return blockCompressor[extDict!=0][(U32)strat]; 2399 selectedCompressor = blockCompressor[(int)dictMode][(U32)strat];
2400 assert(selectedCompressor != NULL);
2401 return selectedCompressor;
1874 } 2402 }
1875 2403
1876 static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr, 2404 static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
1877 const BYTE* anchor, size_t lastLLSize) 2405 const BYTE* anchor, size_t lastLLSize)
1878 { 2406 {
1879 memcpy(seqStorePtr->lit, anchor, lastLLSize); 2407 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1880 seqStorePtr->lit += lastLLSize; 2408 seqStorePtr->lit += lastLLSize;
1881 } 2409 }
1882 2410
1883 static void ZSTD_resetSeqStore(seqStore_t* ssPtr) 2411 void ZSTD_resetSeqStore(seqStore_t* ssPtr)
1884 { 2412 {
1885 ssPtr->lit = ssPtr->litStart; 2413 ssPtr->lit = ssPtr->litStart;
1886 ssPtr->sequences = ssPtr->sequencesStart; 2414 ssPtr->sequences = ssPtr->sequencesStart;
1887 ssPtr->longLengthID = 0; 2415 ssPtr->longLengthID = 0;
1888 } 2416 }
1890 static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, 2418 static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
1891 void* dst, size_t dstCapacity, 2419 void* dst, size_t dstCapacity,
1892 const void* src, size_t srcSize) 2420 const void* src, size_t srcSize)
1893 { 2421 {
1894 ZSTD_matchState_t* const ms = &zc->blockState.matchState; 2422 ZSTD_matchState_t* const ms = &zc->blockState.matchState;
1895 DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", 2423 size_t cSize;
1896 (U32)dstCapacity, ms->window.dictLimit, ms->nextToUpdate); 2424 DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%zu, dictLimit=%u, nextToUpdate=%u)",
2425 dstCapacity, ms->window.dictLimit, ms->nextToUpdate);
2426 assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
2427
2428 /* Assert that we have correctly flushed the ctx params into the ms's copy */
2429 ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
2430
1897 if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) { 2431 if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
1898 ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.searchLength); 2432 ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.searchLength);
1899 return 0; /* don't even attempt compression below a certain srcSize */ 2433 cSize = 0;
2434 goto out; /* don't even attempt compression below a certain srcSize */
1900 } 2435 }
1901 ZSTD_resetSeqStore(&(zc->seqStore)); 2436 ZSTD_resetSeqStore(&(zc->seqStore));
2437 ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* required for optimal parser to read stats from dictionary */
2438
2439 /* a gap between an attached dict and the current window is not safe,
2440 * they must remain adjacent, and when that stops being the case, the dict
2441 * must be unset */
2442 assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);
1902 2443
1903 /* limited update after a very long match */ 2444 /* limited update after a very long match */
1904 { const BYTE* const base = ms->window.base; 2445 { const BYTE* const base = ms->window.base;
1905 const BYTE* const istart = (const BYTE*)src; 2446 const BYTE* const istart = (const BYTE*)src;
1906 const U32 current = (U32)(istart-base); 2447 const U32 current = (U32)(istart-base);
2448 if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */
1907 if (current > ms->nextToUpdate + 384) 2449 if (current > ms->nextToUpdate + 384)
1908 ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384)); 2450 ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384));
1909 } 2451 }
1910 2452
1911 /* select and store sequences */ 2453 /* select and store sequences */
1912 { U32 const extDict = ZSTD_window_hasExtDict(ms->window); 2454 { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
1913 size_t lastLLSize; 2455 size_t lastLLSize;
1914 { int i; 2456 { int i;
1915 for (i = 0; i < ZSTD_REP_NUM; ++i) 2457 for (i = 0; i < ZSTD_REP_NUM; ++i)
1916 zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i]; 2458 zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];
1917 } 2459 }
1920 /* Updates ldmSeqStore.pos */ 2462 /* Updates ldmSeqStore.pos */
1921 lastLLSize = 2463 lastLLSize =
1922 ZSTD_ldm_blockCompress(&zc->externSeqStore, 2464 ZSTD_ldm_blockCompress(&zc->externSeqStore,
1923 ms, &zc->seqStore, 2465 ms, &zc->seqStore,
1924 zc->blockState.nextCBlock->rep, 2466 zc->blockState.nextCBlock->rep,
1925 &zc->appliedParams.cParams, 2467 src, srcSize);
1926 src, srcSize, extDict);
1927 assert(zc->externSeqStore.pos <= zc->externSeqStore.size); 2468 assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
1928 } else if (zc->appliedParams.ldmParams.enableLdm) { 2469 } else if (zc->appliedParams.ldmParams.enableLdm) {
1929 rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0}; 2470 rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
1930 2471
1931 ldmSeqStore.seq = zc->ldmSequences; 2472 ldmSeqStore.seq = zc->ldmSequences;
1937 /* Updates ldmSeqStore.pos */ 2478 /* Updates ldmSeqStore.pos */
1938 lastLLSize = 2479 lastLLSize =
1939 ZSTD_ldm_blockCompress(&ldmSeqStore, 2480 ZSTD_ldm_blockCompress(&ldmSeqStore,
1940 ms, &zc->seqStore, 2481 ms, &zc->seqStore,
1941 zc->blockState.nextCBlock->rep, 2482 zc->blockState.nextCBlock->rep,
1942 &zc->appliedParams.cParams, 2483 src, srcSize);
1943 src, srcSize, extDict);
1944 assert(ldmSeqStore.pos == ldmSeqStore.size); 2484 assert(ldmSeqStore.pos == ldmSeqStore.size);
1945 } else { /* not long range mode */ 2485 } else { /* not long range mode */
1946 ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict); 2486 ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
1947 lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, &zc->appliedParams.cParams, src, srcSize); 2487 lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
1948 } 2488 }
1949 { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; 2489 { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
1950 ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize); 2490 ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
1951 } } 2491 } }
1952 2492
1953 /* encode sequences and literals */ 2493 /* encode sequences and literals */
1954 { size_t const cSize = ZSTD_compressSequences(&zc->seqStore, 2494 cSize = ZSTD_compressSequences(&zc->seqStore,
1955 &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, 2495 &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
1956 &zc->appliedParams, 2496 &zc->appliedParams,
1957 dst, dstCapacity, 2497 dst, dstCapacity,
1958 srcSize, zc->entropyWorkspace, zc->bmi2); 2498 srcSize, zc->entropyWorkspace, zc->bmi2);
1959 if (ZSTD_isError(cSize) || cSize == 0) return cSize; 2499
1960 /* confirm repcodes and entropy tables */ 2500 out:
1961 { ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; 2501 if (!ZSTD_isError(cSize) && cSize != 0) {
1962 zc->blockState.prevCBlock = zc->blockState.nextCBlock; 2502 /* confirm repcodes and entropy tables when emitting a compressed block */
1963 zc->blockState.nextCBlock = tmp; 2503 ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
1964 } 2504 zc->blockState.prevCBlock = zc->blockState.nextCBlock;
1965 return cSize; 2505 zc->blockState.nextCBlock = tmp;
1966 } 2506 }
2507 /* We check that dictionaries have offset codes available for the first
2508 * block. After the first block, the offcode table might not have large
2509 * enough codes to represent the offsets in the data.
2510 */
2511 if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
2512 zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
2513
2514 return cSize;
1967 } 2515 }
1968 2516
1969 2517
1970 /*! ZSTD_compress_frameChunk() : 2518 /*! ZSTD_compress_frameChunk() :
1971 * Compress a chunk of data into one or multiple blocks. 2519 * Compress a chunk of data into one or multiple blocks.
2003 U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy); 2551 U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2004 U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); 2552 U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
2005 ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); 2553 ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2006 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30); 2554 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2007 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31); 2555 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2008
2009 ZSTD_reduceIndex(cctx, correction); 2556 ZSTD_reduceIndex(cctx, correction);
2010 if (ms->nextToUpdate < correction) ms->nextToUpdate = 0; 2557 if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2011 else ms->nextToUpdate -= correction; 2558 else ms->nextToUpdate -= correction;
2012 ms->loadedDictEnd = 0; 2559 ms->loadedDictEnd = 0;
2560 ms->dictMatchState = NULL;
2013 } 2561 }
2014 ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd); 2562 ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2015 if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; 2563 if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
2016 2564
2017 { size_t cSize = ZSTD_compressBlock_internal(cctx, 2565 { size_t cSize = ZSTD_compressBlock_internal(cctx,
2018 op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, 2566 op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
2019 ip, blockSize); 2567 ip, blockSize);
2020 if (ZSTD_isError(cSize)) return cSize; 2568 if (ZSTD_isError(cSize)) return cSize;
2021 2569
2022 if (cSize == 0) { /* block is not compressible */ 2570 if (cSize == 0) { /* block is not compressible */
2023 U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(blockSize << 3); 2571 cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
2024 if (blockSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall); 2572 if (ZSTD_isError(cSize)) return cSize;
2025 MEM_writeLE32(op, cBlockHeader24); /* 4th byte will be overwritten */
2026 memcpy(op + ZSTD_blockHeaderSize, ip, blockSize);
2027 cSize = ZSTD_blockHeaderSize + blockSize;
2028 } else { 2573 } else {
2029 U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); 2574 U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
2030 MEM_writeLE24(op, cBlockHeader24); 2575 MEM_writeLE24(op, cBlockHeader24);
2031 cSize += ZSTD_blockHeaderSize; 2576 cSize += ZSTD_blockHeaderSize;
2032 } 2577 }
2058 U32 const fcsCode = params.fParams.contentSizeFlag ? 2603 U32 const fcsCode = params.fParams.contentSizeFlag ?
2059 (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */ 2604 (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
2060 BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); 2605 BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2061 size_t pos=0; 2606 size_t pos=0;
2062 2607
2608 assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
2063 if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall); 2609 if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
2064 DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", 2610 DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2065 !params.fParams.noDictIDFlag, dictID, dictIDSizeCode); 2611 !params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
2066 2612
2067 if (params.format == ZSTD_f_zstd1) { 2613 if (params.format == ZSTD_f_zstd1) {
2120 static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, 2666 static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2121 void* dst, size_t dstCapacity, 2667 void* dst, size_t dstCapacity,
2122 const void* src, size_t srcSize, 2668 const void* src, size_t srcSize,
2123 U32 frame, U32 lastFrameChunk) 2669 U32 frame, U32 lastFrameChunk)
2124 { 2670 {
2125 ZSTD_matchState_t* ms = &cctx->blockState.matchState; 2671 ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
2126 size_t fhSize = 0; 2672 size_t fhSize = 0;
2127 2673
2128 DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u", 2674 DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
2129 cctx->stage, (U32)srcSize); 2675 cctx->stage, (U32)srcSize);
2130 if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */ 2676 if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
2141 if (!srcSize) return fhSize; /* do not generate an empty block if no input */ 2687 if (!srcSize) return fhSize; /* do not generate an empty block if no input */
2142 2688
2143 if (!ZSTD_window_update(&ms->window, src, srcSize)) { 2689 if (!ZSTD_window_update(&ms->window, src, srcSize)) {
2144 ms->nextToUpdate = ms->window.dictLimit; 2690 ms->nextToUpdate = ms->window.dictLimit;
2145 } 2691 }
2146 if (cctx->appliedParams.ldmParams.enableLdm) 2692 if (cctx->appliedParams.ldmParams.enableLdm) {
2147 ZSTD_window_update(&cctx->ldmState.window, src, srcSize); 2693 ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
2694 }
2695
2696 if (!frame) {
2697 /* overflow check and correction for block mode */
2698 if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) {
2699 U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2700 U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src);
2701 ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2702 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2703 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2704 ZSTD_reduceIndex(cctx, correction);
2705 if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2706 else ms->nextToUpdate -= correction;
2707 ms->loadedDictEnd = 0;
2708 ms->dictMatchState = NULL;
2709 }
2710 }
2148 2711
2149 DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (U32)cctx->blockSize); 2712 DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (U32)cctx->blockSize);
2150 { size_t const cSize = frame ? 2713 { size_t const cSize = frame ?
2151 ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : 2714 ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
2152 ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize); 2715 ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
2153 if (ZSTD_isError(cSize)) return cSize; 2716 if (ZSTD_isError(cSize)) return cSize;
2154 cctx->consumedSrcSize += srcSize; 2717 cctx->consumedSrcSize += srcSize;
2155 cctx->producedCSize += (cSize + fhSize); 2718 cctx->producedCSize += (cSize + fhSize);
2156 if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */ 2719 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
2720 if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
2721 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
2157 if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) { 2722 if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) {
2158 DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u", 2723 DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u",
2159 (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize); 2724 (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
2160 return ERROR(srcSize_wrong); 2725 return ERROR(srcSize_wrong);
2161 } 2726 }
2182 2747
2183 size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) 2748 size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2184 { 2749 {
2185 size_t const blockSizeMax = ZSTD_getBlockSize(cctx); 2750 size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
2186 if (srcSize > blockSizeMax) return ERROR(srcSize_wrong); 2751 if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
2752
2187 return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */); 2753 return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
2188 } 2754 }
2189 2755
2190 /*! ZSTD_loadDictionaryContent() : 2756 /*! ZSTD_loadDictionaryContent() :
2191 * @return : 0, or an error code 2757 * @return : 0, or an error code
2192 */ 2758 */
2193 static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* src, size_t srcSize) 2759 static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
2760 ZSTD_CCtx_params const* params,
2761 const void* src, size_t srcSize,
2762 ZSTD_dictTableLoadMethod_e dtlm)
2194 { 2763 {
2195 const BYTE* const ip = (const BYTE*) src; 2764 const BYTE* const ip = (const BYTE*) src;
2196 const BYTE* const iend = ip + srcSize; 2765 const BYTE* const iend = ip + srcSize;
2197 ZSTD_compressionParameters const* cParams = &params->cParams;
2198 2766
2199 ZSTD_window_update(&ms->window, src, srcSize); 2767 ZSTD_window_update(&ms->window, src, srcSize);
2200 ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base); 2768 ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
2769
2770 /* Assert that we the ms params match the params we're being given */
2771 ZSTD_assertEqualCParams(params->cParams, ms->cParams);
2201 2772
2202 if (srcSize <= HASH_READ_SIZE) return 0; 2773 if (srcSize <= HASH_READ_SIZE) return 0;
2203 2774
2204 switch(params->cParams.strategy) 2775 switch(params->cParams.strategy)
2205 { 2776 {
2206 case ZSTD_fast: 2777 case ZSTD_fast:
2207 ZSTD_fillHashTable(ms, cParams, iend); 2778 ZSTD_fillHashTable(ms, iend, dtlm);
2208 break; 2779 break;
2209 case ZSTD_dfast: 2780 case ZSTD_dfast:
2210 ZSTD_fillDoubleHashTable(ms, cParams, iend); 2781 ZSTD_fillDoubleHashTable(ms, iend, dtlm);
2211 break; 2782 break;
2212 2783
2213 case ZSTD_greedy: 2784 case ZSTD_greedy:
2214 case ZSTD_lazy: 2785 case ZSTD_lazy:
2215 case ZSTD_lazy2: 2786 case ZSTD_lazy2:
2216 if (srcSize >= HASH_READ_SIZE) 2787 if (srcSize >= HASH_READ_SIZE)
2217 ZSTD_insertAndFindFirstIndex(ms, cParams, iend-HASH_READ_SIZE); 2788 ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
2218 break; 2789 break;
2219 2790
2220 case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ 2791 case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
2221 case ZSTD_btopt: 2792 case ZSTD_btopt:
2222 case ZSTD_btultra: 2793 case ZSTD_btultra:
2223 if (srcSize >= HASH_READ_SIZE) 2794 if (srcSize >= HASH_READ_SIZE)
2224 ZSTD_updateTree(ms, cParams, iend-HASH_READ_SIZE, iend); 2795 ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
2225 break; 2796 break;
2226 2797
2227 default: 2798 default:
2228 assert(0); /* not possible : not a valid strategy id */ 2799 assert(0); /* not possible : not a valid strategy id */
2229 } 2800 }
2254 /*! ZSTD_loadZstdDictionary() : 2825 /*! ZSTD_loadZstdDictionary() :
2255 * @return : dictID, or an error code 2826 * @return : dictID, or an error code
2256 * assumptions : magic number supposed already checked 2827 * assumptions : magic number supposed already checked
2257 * dictSize supposed > 8 2828 * dictSize supposed > 8
2258 */ 2829 */
2259 static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* dict, size_t dictSize, void* workspace) 2830 static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
2831 ZSTD_matchState_t* ms,
2832 ZSTD_CCtx_params const* params,
2833 const void* dict, size_t dictSize,
2834 ZSTD_dictTableLoadMethod_e dtlm,
2835 void* workspace)
2260 { 2836 {
2261 const BYTE* dictPtr = (const BYTE*)dict; 2837 const BYTE* dictPtr = (const BYTE*)dict;
2262 const BYTE* const dictEnd = dictPtr + dictSize; 2838 const BYTE* const dictEnd = dictPtr + dictSize;
2263 short offcodeNCount[MaxOff+1]; 2839 short offcodeNCount[MaxOff+1];
2264 unsigned offcodeMaxValue = MaxOff; 2840 unsigned offcodeMaxValue = MaxOff;
2265 size_t dictID; 2841 size_t dictID;
2266 2842
2267 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog))); 2843 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
2844 assert(dictSize > 8);
2845 assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
2268 2846
2269 dictPtr += 4; /* skip magic number */ 2847 dictPtr += 4; /* skip magic number */
2270 dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr); 2848 dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
2271 dictPtr += 4; 2849 dictPtr += 4;
2272 2850
2273 { unsigned maxSymbolValue = 255; 2851 { unsigned maxSymbolValue = 255;
2274 size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); 2852 size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
2275 if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted); 2853 if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
2276 if (maxSymbolValue < 255) return ERROR(dictionary_corrupted); 2854 if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
2277 dictPtr += hufHeaderSize; 2855 dictPtr += hufHeaderSize;
2278 } 2856 }
2279 2857
2280 { unsigned offcodeLog; 2858 { unsigned offcodeLog;
2281 size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); 2859 size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
2282 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted); 2860 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
2283 if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted); 2861 if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
2284 /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ 2862 /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
2285 CHECK_E( FSE_buildCTable_wksp(bs->entropy.offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, workspace, HUF_WORKSPACE_SIZE), 2863 /* fill all offset symbols to avoid garbage at end of table */
2864 CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.offcodeCTable, offcodeNCount, MaxOff, offcodeLog, workspace, HUF_WORKSPACE_SIZE),
2286 dictionary_corrupted); 2865 dictionary_corrupted);
2287 dictPtr += offcodeHeaderSize; 2866 dictPtr += offcodeHeaderSize;
2288 } 2867 }
2289 2868
2290 { short matchlengthNCount[MaxML+1]; 2869 { short matchlengthNCount[MaxML+1];
2292 size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); 2871 size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
2293 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted); 2872 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
2294 if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted); 2873 if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
2295 /* Every match length code must have non-zero probability */ 2874 /* Every match length code must have non-zero probability */
2296 CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML)); 2875 CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
2297 CHECK_E( FSE_buildCTable_wksp(bs->entropy.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE), 2876 CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE),
2298 dictionary_corrupted); 2877 dictionary_corrupted);
2299 dictPtr += matchlengthHeaderSize; 2878 dictPtr += matchlengthHeaderSize;
2300 } 2879 }
2301 2880
2302 { short litlengthNCount[MaxLL+1]; 2881 { short litlengthNCount[MaxLL+1];
2304 size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); 2883 size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
2305 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted); 2884 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
2306 if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted); 2885 if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
2307 /* Every literal length code must have non-zero probability */ 2886 /* Every literal length code must have non-zero probability */
2308 CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL)); 2887 CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
2309 CHECK_E( FSE_buildCTable_wksp(bs->entropy.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE), 2888 CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE),
2310 dictionary_corrupted); 2889 dictionary_corrupted);
2311 dictPtr += litlengthHeaderSize; 2890 dictPtr += litlengthHeaderSize;
2312 } 2891 }
2313 2892
2314 if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted); 2893 if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
2330 for (u=0; u<3; u++) { 2909 for (u=0; u<3; u++) {
2331 if (bs->rep[u] == 0) return ERROR(dictionary_corrupted); 2910 if (bs->rep[u] == 0) return ERROR(dictionary_corrupted);
2332 if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted); 2911 if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
2333 } } 2912 } }
2334 2913
2335 bs->entropy.hufCTable_repeatMode = HUF_repeat_valid; 2914 bs->entropy.huf.repeatMode = HUF_repeat_valid;
2336 bs->entropy.offcode_repeatMode = FSE_repeat_valid; 2915 bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
2337 bs->entropy.matchlength_repeatMode = FSE_repeat_valid; 2916 bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
2338 bs->entropy.litlength_repeatMode = FSE_repeat_valid; 2917 bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
2339 CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize)); 2918 CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
2340 return dictID; 2919 return dictID;
2341 } 2920 }
2342 } 2921 }
2343 2922
2344 /** ZSTD_compress_insertDictionary() : 2923 /** ZSTD_compress_insertDictionary() :
2345 * @return : dictID, or an error code */ 2924 * @return : dictID, or an error code */
2346 static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms, 2925 static size_t
2347 ZSTD_CCtx_params const* params, 2926 ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
2348 const void* dict, size_t dictSize, 2927 ZSTD_matchState_t* ms,
2349 ZSTD_dictContentType_e dictContentType, 2928 const ZSTD_CCtx_params* params,
2350 void* workspace) 2929 const void* dict, size_t dictSize,
2930 ZSTD_dictContentType_e dictContentType,
2931 ZSTD_dictTableLoadMethod_e dtlm,
2932 void* workspace)
2351 { 2933 {
2352 DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize); 2934 DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
2353 if ((dict==NULL) || (dictSize<=8)) return 0; 2935 if ((dict==NULL) || (dictSize<=8)) return 0;
2354 2936
2355 ZSTD_reset_compressedBlockState(bs); 2937 ZSTD_reset_compressedBlockState(bs);
2356 2938
2357 /* dict restricted modes */ 2939 /* dict restricted modes */
2358 if (dictContentType == ZSTD_dct_rawContent) 2940 if (dictContentType == ZSTD_dct_rawContent)
2359 return ZSTD_loadDictionaryContent(ms, params, dict, dictSize); 2941 return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
2360 2942
2361 if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) { 2943 if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
2362 if (dictContentType == ZSTD_dct_auto) { 2944 if (dictContentType == ZSTD_dct_auto) {
2363 DEBUGLOG(4, "raw content dictionary detected"); 2945 DEBUGLOG(4, "raw content dictionary detected");
2364 return ZSTD_loadDictionaryContent(ms, params, dict, dictSize); 2946 return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
2365 } 2947 }
2366 if (dictContentType == ZSTD_dct_fullDict) 2948 if (dictContentType == ZSTD_dct_fullDict)
2367 return ERROR(dictionary_wrong); 2949 return ERROR(dictionary_wrong);
2368 assert(0); /* impossible */ 2950 assert(0); /* impossible */
2369 } 2951 }
2370 2952
2371 /* dict as full zstd dictionary */ 2953 /* dict as full zstd dictionary */
2372 return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, workspace); 2954 return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, dtlm, workspace);
2373 } 2955 }
2374 2956
2375 /*! ZSTD_compressBegin_internal() : 2957 /*! ZSTD_compressBegin_internal() :
2376 * @return : 0, or an error code */ 2958 * @return : 0, or an error code */
2377 size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, 2959 static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2378 const void* dict, size_t dictSize, 2960 const void* dict, size_t dictSize,
2379 ZSTD_dictContentType_e dictContentType, 2961 ZSTD_dictContentType_e dictContentType,
2380 const ZSTD_CDict* cdict, 2962 ZSTD_dictTableLoadMethod_e dtlm,
2381 ZSTD_CCtx_params params, U64 pledgedSrcSize, 2963 const ZSTD_CDict* cdict,
2382 ZSTD_buffered_policy_e zbuff) 2964 ZSTD_CCtx_params params, U64 pledgedSrcSize,
2965 ZSTD_buffered_policy_e zbuff)
2383 { 2966 {
2384 DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params.cParams.windowLog); 2967 DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params.cParams.windowLog);
2385 /* params are supposed to be fully validated at this point */ 2968 /* params are supposed to be fully validated at this point */
2386 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); 2969 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
2387 assert(!((dict) && (cdict))); /* either dict or cdict, not both */ 2970 assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2388 2971
2389 if (cdict && cdict->dictContentSize>0) { 2972 if (cdict && cdict->dictContentSize>0) {
2390 cctx->requestedParams = params; 2973 return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
2391 return ZSTD_resetCCtx_usingCDict(cctx, cdict, params.cParams.windowLog,
2392 params.fParams, pledgedSrcSize, zbuff);
2393 } 2974 }
2394 2975
2395 CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, 2976 CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
2396 ZSTDcrp_continue, zbuff) ); 2977 ZSTDcrp_continue, zbuff) );
2397 { 2978 {
2398 size_t const dictID = ZSTD_compress_insertDictionary( 2979 size_t const dictID = ZSTD_compress_insertDictionary(
2399 cctx->blockState.prevCBlock, &cctx->blockState.matchState, 2980 cctx->blockState.prevCBlock, &cctx->blockState.matchState,
2400 &params, dict, dictSize, dictContentType, cctx->entropyWorkspace); 2981 &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
2401 if (ZSTD_isError(dictID)) return dictID; 2982 if (ZSTD_isError(dictID)) return dictID;
2402 assert(dictID <= (size_t)(U32)-1); 2983 assert(dictID <= (size_t)(U32)-1);
2403 cctx->dictID = (U32)dictID; 2984 cctx->dictID = (U32)dictID;
2404 } 2985 }
2405 return 0; 2986 return 0;
2406 } 2987 }
2407 2988
2408 size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, 2989 size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
2409 const void* dict, size_t dictSize, 2990 const void* dict, size_t dictSize,
2410 ZSTD_dictContentType_e dictContentType, 2991 ZSTD_dictContentType_e dictContentType,
2992 ZSTD_dictTableLoadMethod_e dtlm,
2411 const ZSTD_CDict* cdict, 2993 const ZSTD_CDict* cdict,
2412 ZSTD_CCtx_params params, 2994 ZSTD_CCtx_params params,
2413 unsigned long long pledgedSrcSize) 2995 unsigned long long pledgedSrcSize)
2414 { 2996 {
2415 DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog); 2997 DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
2416 /* compression parameters verification and optimization */ 2998 /* compression parameters verification and optimization */
2417 CHECK_F( ZSTD_checkCParams(params.cParams) ); 2999 CHECK_F( ZSTD_checkCParams(params.cParams) );
2418 return ZSTD_compressBegin_internal(cctx, 3000 return ZSTD_compressBegin_internal(cctx,
2419 dict, dictSize, dictContentType, 3001 dict, dictSize, dictContentType, dtlm,
2420 cdict, 3002 cdict,
2421 params, pledgedSrcSize, 3003 params, pledgedSrcSize,
2422 ZSTDb_not_buffered); 3004 ZSTDb_not_buffered);
2423 } 3005 }
2424 3006
2429 ZSTD_parameters params, unsigned long long pledgedSrcSize) 3011 ZSTD_parameters params, unsigned long long pledgedSrcSize)
2430 { 3012 {
2431 ZSTD_CCtx_params const cctxParams = 3013 ZSTD_CCtx_params const cctxParams =
2432 ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params); 3014 ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2433 return ZSTD_compressBegin_advanced_internal(cctx, 3015 return ZSTD_compressBegin_advanced_internal(cctx,
2434 dict, dictSize, ZSTD_dct_auto, 3016 dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
2435 NULL /*cdict*/, 3017 NULL /*cdict*/,
2436 cctxParams, pledgedSrcSize); 3018 cctxParams, pledgedSrcSize);
2437 } 3019 }
2438 3020
2439 size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) 3021 size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
2440 { 3022 {
2441 ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); 3023 ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
2442 ZSTD_CCtx_params const cctxParams = 3024 ZSTD_CCtx_params const cctxParams =
2443 ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params); 3025 ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2444 DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (U32)dictSize); 3026 DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (U32)dictSize);
2445 return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL, 3027 return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
2446 cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered); 3028 cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
2447 } 3029 }
2448 3030
2449 size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel) 3031 size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
2450 { 3032 {
2503 dst, dstCapacity, src, srcSize, 3085 dst, dstCapacity, src, srcSize,
2504 1 /* frame mode */, 1 /* last chunk */); 3086 1 /* frame mode */, 1 /* last chunk */);
2505 if (ZSTD_isError(cSize)) return cSize; 3087 if (ZSTD_isError(cSize)) return cSize;
2506 endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); 3088 endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
2507 if (ZSTD_isError(endResult)) return endResult; 3089 if (ZSTD_isError(endResult)) return endResult;
2508 if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */ 3090 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
3091 if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
3092 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
2509 DEBUGLOG(4, "end of frame : controlling src size"); 3093 DEBUGLOG(4, "end of frame : controlling src size");
2510 if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) { 3094 if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
2511 DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u", 3095 DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
2512 (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize); 3096 (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
2513 return ERROR(srcSize_wrong); 3097 return ERROR(srcSize_wrong);
2515 return cSize + endResult; 3099 return cSize + endResult;
2516 } 3100 }
2517 3101
2518 3102
2519 static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx, 3103 static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
3104 void* dst, size_t dstCapacity,
3105 const void* src, size_t srcSize,
3106 const void* dict,size_t dictSize,
3107 ZSTD_parameters params)
3108 {
3109 ZSTD_CCtx_params const cctxParams =
3110 ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3111 DEBUGLOG(4, "ZSTD_compress_internal");
3112 return ZSTD_compress_advanced_internal(cctx,
3113 dst, dstCapacity,
3114 src, srcSize,
3115 dict, dictSize,
3116 cctxParams);
3117 }
3118
3119 size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
2520 void* dst, size_t dstCapacity, 3120 void* dst, size_t dstCapacity,
2521 const void* src, size_t srcSize, 3121 const void* src, size_t srcSize,
2522 const void* dict,size_t dictSize, 3122 const void* dict,size_t dictSize,
2523 ZSTD_parameters params) 3123 ZSTD_parameters params)
2524 { 3124 {
2525 ZSTD_CCtx_params const cctxParams =
2526 ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2527 DEBUGLOG(4, "ZSTD_compress_internal");
2528 return ZSTD_compress_advanced_internal(cctx,
2529 dst, dstCapacity,
2530 src, srcSize,
2531 dict, dictSize,
2532 cctxParams);
2533 }
2534
2535 size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
2536 void* dst, size_t dstCapacity,
2537 const void* src, size_t srcSize,
2538 const void* dict,size_t dictSize,
2539 ZSTD_parameters params)
2540 {
2541 DEBUGLOG(4, "ZSTD_compress_advanced"); 3125 DEBUGLOG(4, "ZSTD_compress_advanced");
2542 CHECK_F(ZSTD_checkCParams(params.cParams)); 3126 CHECK_F(ZSTD_checkCParams(params.cParams));
2543 return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params); 3127 return ZSTD_compress_internal(cctx,
3128 dst, dstCapacity,
3129 src, srcSize,
3130 dict, dictSize,
3131 params);
2544 } 3132 }
2545 3133
2546 /* Internal */ 3134 /* Internal */
2547 size_t ZSTD_compress_advanced_internal( 3135 size_t ZSTD_compress_advanced_internal(
2548 ZSTD_CCtx* cctx, 3136 ZSTD_CCtx* cctx,
2549 void* dst, size_t dstCapacity, 3137 void* dst, size_t dstCapacity,
2550 const void* src, size_t srcSize, 3138 const void* src, size_t srcSize,
2551 const void* dict,size_t dictSize, 3139 const void* dict,size_t dictSize,
2552 ZSTD_CCtx_params params) 3140 ZSTD_CCtx_params params)
2553 { 3141 {
2554 DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", 3142 DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (U32)srcSize);
2555 (U32)srcSize); 3143 CHECK_F( ZSTD_compressBegin_internal(cctx,
2556 CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL, 3144 dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
2557 params, srcSize, ZSTDb_not_buffered) ); 3145 params, srcSize, ZSTDb_not_buffered) );
2558 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); 3146 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
2559 } 3147 }
2560 3148
2561 size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, 3149 size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
2562 const void* dict, size_t dictSize, int compressionLevel) 3150 void* dst, size_t dstCapacity,
2563 { 3151 const void* src, size_t srcSize,
2564 ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0); 3152 const void* dict, size_t dictSize,
3153 int compressionLevel)
3154 {
3155 ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize + (!srcSize), dict ? dictSize : 0);
2565 ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params); 3156 ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2566 assert(params.fParams.contentSizeFlag == 1); 3157 assert(params.fParams.contentSizeFlag == 1);
2567 ZSTD_CCtxParam_setParameter(&cctxParams, ZSTD_p_compressLiterals, compressionLevel>=0);
2568 return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams); 3158 return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams);
2569 } 3159 }
2570 3160
2571 size_t ZSTD_compressCCtx (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel) 3161 size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
3162 void* dst, size_t dstCapacity,
3163 const void* src, size_t srcSize,
3164 int compressionLevel)
2572 { 3165 {
2573 DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (U32)srcSize); 3166 DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (U32)srcSize);
3167 assert(cctx != NULL);
2574 return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel); 3168 return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
2575 } 3169 }
2576 3170
2577 size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel) 3171 size_t ZSTD_compress(void* dst, size_t dstCapacity,
3172 const void* src, size_t srcSize,
3173 int compressionLevel)
2578 { 3174 {
2579 size_t result; 3175 size_t result;
2580 ZSTD_CCtx ctxBody; 3176 ZSTD_CCtx ctxBody;
2581 memset(&ctxBody, 0, sizeof(ctxBody)); 3177 ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem);
2582 ctxBody.customMem = ZSTD_defaultCMem;
2583 result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel); 3178 result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
2584 ZSTD_free(ctxBody.workSpace, ZSTD_defaultCMem); /* can't free ctxBody itself, as it's on stack; free only heap content */ 3179 ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */
2585 return result; 3180 return result;
2586 } 3181 }
2587 3182
2588 3183
2589 /* ===== Dictionary API ===== */ 3184 /* ===== Dictionary API ===== */
2617 const void* dictBuffer, size_t dictSize, 3212 const void* dictBuffer, size_t dictSize,
2618 ZSTD_dictLoadMethod_e dictLoadMethod, 3213 ZSTD_dictLoadMethod_e dictLoadMethod,
2619 ZSTD_dictContentType_e dictContentType, 3214 ZSTD_dictContentType_e dictContentType,
2620 ZSTD_compressionParameters cParams) 3215 ZSTD_compressionParameters cParams)
2621 { 3216 {
2622 DEBUGLOG(3, "ZSTD_initCDict_internal, dictContentType %u", (U32)dictContentType); 3217 DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (U32)dictContentType);
2623 assert(!ZSTD_checkCParams(cParams)); 3218 assert(!ZSTD_checkCParams(cParams));
2624 cdict->cParams = cParams; 3219 cdict->matchState.cParams = cParams;
2625 if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) { 3220 if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
2626 cdict->dictBuffer = NULL; 3221 cdict->dictBuffer = NULL;
2627 cdict->dictContent = dictBuffer; 3222 cdict->dictContent = dictBuffer;
2628 } else { 3223 } else {
2629 void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem); 3224 void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
2652 params.fParams.contentSizeFlag = 1; 3247 params.fParams.contentSizeFlag = 1;
2653 params.cParams = cParams; 3248 params.cParams = cParams;
2654 { size_t const dictID = ZSTD_compress_insertDictionary( 3249 { size_t const dictID = ZSTD_compress_insertDictionary(
2655 &cdict->cBlockState, &cdict->matchState, &params, 3250 &cdict->cBlockState, &cdict->matchState, &params,
2656 cdict->dictContent, cdict->dictContentSize, 3251 cdict->dictContent, cdict->dictContentSize,
2657 dictContentType, cdict->workspace); 3252 dictContentType, ZSTD_dtlm_full, cdict->workspace);
2658 if (ZSTD_isError(dictID)) return dictID; 3253 if (ZSTD_isError(dictID)) return dictID;
2659 assert(dictID <= (size_t)(U32)-1); 3254 assert(dictID <= (size_t)(U32)-1);
2660 cdict->dictID = (U32)dictID; 3255 cdict->dictID = (U32)dictID;
2661 } 3256 }
2662 } 3257 }
2773 } 3368 }
2774 3369
2775 ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) 3370 ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
2776 { 3371 {
2777 assert(cdict != NULL); 3372 assert(cdict != NULL);
2778 return cdict->cParams; 3373 return cdict->matchState.cParams;
2779 } 3374 }
2780 3375
2781 /* ZSTD_compressBegin_usingCDict_advanced() : 3376 /* ZSTD_compressBegin_usingCDict_advanced() :
2782 * cdict must be != NULL */ 3377 * cdict must be != NULL */
2783 size_t ZSTD_compressBegin_usingCDict_advanced( 3378 size_t ZSTD_compressBegin_usingCDict_advanced(
2797 U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1; 3392 U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
2798 params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog); 3393 params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog);
2799 } 3394 }
2800 params.fParams = fParams; 3395 params.fParams = fParams;
2801 return ZSTD_compressBegin_internal(cctx, 3396 return ZSTD_compressBegin_internal(cctx,
2802 NULL, 0, ZSTD_dct_auto, 3397 NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
2803 cdict, 3398 cdict,
2804 params, pledgedSrcSize, 3399 params, pledgedSrcSize,
2805 ZSTDb_not_buffered); 3400 ZSTDb_not_buffered);
2806 } 3401 }
2807 } 3402 }
2811 * if pledgedSrcSize>0, it will enable contentSizeFlag */ 3406 * if pledgedSrcSize>0, it will enable contentSizeFlag */
2812 size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) 3407 size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
2813 { 3408 {
2814 ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; 3409 ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
2815 DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag); 3410 DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
2816 return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0); 3411 return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);
2817 } 3412 }
2818 3413
2819 size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, 3414 size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
2820 void* dst, size_t dstCapacity, 3415 void* dst, size_t dstCapacity,
2821 const void* src, size_t srcSize, 3416 const void* src, size_t srcSize,
2878 } 3473 }
2879 3474
2880 static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx, 3475 static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
2881 const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType, 3476 const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType,
2882 const ZSTD_CDict* const cdict, 3477 const ZSTD_CDict* const cdict,
2883 ZSTD_CCtx_params const params, unsigned long long const pledgedSrcSize) 3478 ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize)
2884 { 3479 {
2885 DEBUGLOG(4, "ZSTD_resetCStream_internal (disableLiteralCompression=%i)", 3480 DEBUGLOG(4, "ZSTD_resetCStream_internal");
2886 params.disableLiteralCompression); 3481 /* Finalize the compression parameters */
3482 params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
2887 /* params are supposed to be fully validated at this point */ 3483 /* params are supposed to be fully validated at this point */
2888 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); 3484 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
2889 assert(!((dict) && (cdict))); /* either dict or cdict, not both */ 3485 assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2890 3486
2891 CHECK_F( ZSTD_compressBegin_internal(cctx, 3487 CHECK_F( ZSTD_compressBegin_internal(cctx,
2892 dict, dictSize, dictContentType, 3488 dict, dictSize, dictContentType, ZSTD_dtlm_fast,
2893 cdict, 3489 cdict,
2894 params, pledgedSrcSize, 3490 params, pledgedSrcSize,
2895 ZSTDb_buffered) ); 3491 ZSTDb_buffered) );
2896 3492
2897 cctx->inToCompress = 0; 3493 cctx->inToCompress = 0;
2910 { 3506 {
2911 ZSTD_CCtx_params params = zcs->requestedParams; 3507 ZSTD_CCtx_params params = zcs->requestedParams;
2912 DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (U32)pledgedSrcSize); 3508 DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (U32)pledgedSrcSize);
2913 if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; 3509 if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
2914 params.fParams.contentSizeFlag = 1; 3510 params.fParams.contentSizeFlag = 1;
2915 params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, 0);
2916 return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize); 3511 return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
2917 } 3512 }
2918 3513
2919 /*! ZSTD_initCStream_internal() : 3514 /*! ZSTD_initCStream_internal() :
2920 * Note : for lib/compress only. Used by zstdmt_compress.c. 3515 * Note : for lib/compress only. Used by zstdmt_compress.c.
2923 size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, 3518 size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
2924 const void* dict, size_t dictSize, const ZSTD_CDict* cdict, 3519 const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
2925 ZSTD_CCtx_params params, unsigned long long pledgedSrcSize) 3520 ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
2926 { 3521 {
2927 DEBUGLOG(4, "ZSTD_initCStream_internal"); 3522 DEBUGLOG(4, "ZSTD_initCStream_internal");
3523 params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
2928 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); 3524 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
2929 assert(!((dict) && (cdict))); /* either dict or cdict, not both */ 3525 assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2930 3526
2931 if (dict && dictSize >= 8) { 3527 if (dict && dictSize >= 8) {
2932 DEBUGLOG(4, "loading dictionary of size %u", (U32)dictSize); 3528 DEBUGLOG(4, "loading dictionary of size %u", (U32)dictSize);
2989 { 3585 {
2990 DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u", 3586 DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u",
2991 (U32)pledgedSrcSize, params.fParams.contentSizeFlag); 3587 (U32)pledgedSrcSize, params.fParams.contentSizeFlag);
2992 CHECK_F( ZSTD_checkCParams(params.cParams) ); 3588 CHECK_F( ZSTD_checkCParams(params.cParams) );
2993 if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */ 3589 if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
2994 { ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params); 3590 zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2995 return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, cctxParams, pledgedSrcSize); 3591 return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, zcs->requestedParams, pledgedSrcSize);
2996 }
2997 } 3592 }
2998 3593
2999 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel) 3594 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3000 { 3595 {
3001 ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize); 3596 ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
3002 ZSTD_CCtx_params const cctxParams = 3597 return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, zcs->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN);
3003 ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3004 return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
3005 } 3598 }
3006 3599
3007 size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss) 3600 size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
3008 { 3601 {
3009 U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */ 3602 U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */
3010 ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0); 3603 ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
3011 ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params); 3604 return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, zcs->requestedParams, pledgedSrcSize);
3012 return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, cctxParams, pledgedSrcSize);
3013 } 3605 }
3014 3606
3015 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) 3607 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
3016 { 3608 {
3017 DEBUGLOG(4, "ZSTD_initCStream"); 3609 DEBUGLOG(4, "ZSTD_initCStream");
3071 DEBUGLOG(4, "ZSTD_compressEnd : %u", (U32)cSize); 3663 DEBUGLOG(4, "ZSTD_compressEnd : %u", (U32)cSize);
3072 if (ZSTD_isError(cSize)) return cSize; 3664 if (ZSTD_isError(cSize)) return cSize;
3073 ip = iend; 3665 ip = iend;
3074 op += cSize; 3666 op += cSize;
3075 zcs->frameEnded = 1; 3667 zcs->frameEnded = 1;
3076 ZSTD_startNewCompression(zcs); 3668 ZSTD_CCtx_reset(zcs);
3077 someMoreWork = 0; break; 3669 someMoreWork = 0; break;
3078 } 3670 }
3079 /* complete loading into inBuffer */ 3671 /* complete loading into inBuffer */
3080 { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; 3672 { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
3081 size_t const loaded = ZSTD_limitCopy( 3673 size_t const loaded = ZSTD_limitCopy(
3124 if (cDst == op) { /* no need to flush */ 3716 if (cDst == op) { /* no need to flush */
3125 op += cSize; 3717 op += cSize;
3126 if (zcs->frameEnded) { 3718 if (zcs->frameEnded) {
3127 DEBUGLOG(5, "Frame completed directly in outBuffer"); 3719 DEBUGLOG(5, "Frame completed directly in outBuffer");
3128 someMoreWork = 0; 3720 someMoreWork = 0;
3129 ZSTD_startNewCompression(zcs); 3721 ZSTD_CCtx_reset(zcs);
3130 } 3722 }
3131 break; 3723 break;
3132 } 3724 }
3133 zcs->outBuffContentSize = cSize; 3725 zcs->outBuffContentSize = cSize;
3134 zcs->outBuffFlushedSize = 0; 3726 zcs->outBuffFlushedSize = 0;
3152 } 3744 }
3153 zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; 3745 zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
3154 if (zcs->frameEnded) { 3746 if (zcs->frameEnded) {
3155 DEBUGLOG(5, "Frame completed on flush"); 3747 DEBUGLOG(5, "Frame completed on flush");
3156 someMoreWork = 0; 3748 someMoreWork = 0;
3157 ZSTD_startNewCompression(zcs); 3749 ZSTD_CCtx_reset(zcs);
3158 break; 3750 break;
3159 } 3751 }
3160 zcs->streamStage = zcss_load; 3752 zcs->streamStage = zcss_load;
3161 break; 3753 break;
3162 } 3754 }
3205 DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage"); 3797 DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
3206 if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */ 3798 if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
3207 params.cParams = ZSTD_getCParamsFromCCtxParams( 3799 params.cParams = ZSTD_getCParamsFromCCtxParams(
3208 &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/); 3800 &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
3209 3801
3802
3210 #ifdef ZSTD_MULTITHREAD 3803 #ifdef ZSTD_MULTITHREAD
3211 if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) { 3804 if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
3212 params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ 3805 params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
3213 } 3806 }
3214 if (params.nbWorkers > 0) { 3807 if (params.nbWorkers > 0) {
3215 /* mt context creation */ 3808 /* mt context creation */
3216 if (cctx->mtctx == NULL || (params.nbWorkers != ZSTDMT_getNbWorkers(cctx->mtctx))) { 3809 if (cctx->mtctx == NULL) {
3217 DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbWorkers=%u", 3810 DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbWorkers=%u",
3218 params.nbWorkers); 3811 params.nbWorkers);
3219 if (cctx->mtctx != NULL)
3220 DEBUGLOG(4, "ZSTD_compress_generic: previous nbWorkers was %u",
3221 ZSTDMT_getNbWorkers(cctx->mtctx));
3222 ZSTDMT_freeCCtx(cctx->mtctx);
3223 cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem); 3812 cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
3224 if (cctx->mtctx == NULL) return ERROR(memory_allocation); 3813 if (cctx->mtctx == NULL) return ERROR(memory_allocation);
3225 } 3814 }
3226 /* mt compression */ 3815 /* mt compression */
3227 DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); 3816 DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
3249 cctx->cParamsChanged = 0; 3838 cctx->cParamsChanged = 0;
3250 } 3839 }
3251 { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); 3840 { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
3252 if ( ZSTD_isError(flushMin) 3841 if ( ZSTD_isError(flushMin)
3253 || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ 3842 || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
3254 ZSTD_startNewCompression(cctx); 3843 ZSTD_CCtx_reset(cctx);
3255 } 3844 }
3845 DEBUGLOG(5, "completed ZSTD_compress_generic delegating to ZSTDMT_compressStream_generic");
3256 return flushMin; 3846 return flushMin;
3257 } } 3847 } }
3258 #endif 3848 #endif
3259 CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) ); 3849 CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
3260 DEBUGLOG(5, "completed ZSTD_compress_generic"); 3850 DEBUGLOG(5, "completed ZSTD_compress_generic");
3306 3896
3307 /*-===== Pre-defined compression levels =====-*/ 3897 /*-===== Pre-defined compression levels =====-*/
3308 3898
3309 #define ZSTD_MAX_CLEVEL 22 3899 #define ZSTD_MAX_CLEVEL 22
3310 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } 3900 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
3901 int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
3311 3902
3312 static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { 3903 static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
3313 { /* "default" - guarantees a monotonically increasing memory budget */ 3904 { /* "default" - guarantees a monotonically increasing memory budget */
3314 /* W, C, H, S, L, TL, strat */ 3905 /* W, C, H, S, L, TL, strat */
3315 { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ 3906 { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
3316 { 19, 13, 14, 1, 7, 1, ZSTD_fast }, /* level 1 */ 3907 { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
3317 { 19, 15, 16, 1, 6, 1, ZSTD_fast }, /* level 2 */ 3908 { 19, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
3318 { 20, 16, 17, 1, 5, 8, ZSTD_dfast }, /* level 3 */ 3909 { 20, 16, 17, 1, 5, 1, ZSTD_dfast }, /* level 3 */
3319 { 20, 17, 18, 1, 5, 8, ZSTD_dfast }, /* level 4 */ 3910 { 20, 18, 18, 1, 5, 1, ZSTD_dfast }, /* level 4 */
3320 { 20, 17, 18, 2, 5, 16, ZSTD_greedy }, /* level 5 */ 3911 { 20, 18, 18, 2, 5, 2, ZSTD_greedy }, /* level 5 */
3321 { 21, 17, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */ 3912 { 21, 18, 19, 2, 5, 4, ZSTD_lazy }, /* level 6 */
3322 { 21, 18, 19, 3, 5, 16, ZSTD_lazy }, /* level 7 */ 3913 { 21, 18, 19, 3, 5, 8, ZSTD_lazy2 }, /* level 7 */
3323 { 21, 18, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */ 3914 { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */
3324 { 21, 19, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 9 */ 3915 { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */
3325 { 21, 19, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */ 3916 { 21, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
3326 { 22, 20, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */ 3917 { 21, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
3327 { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */ 3918 { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
3328 { 22, 21, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */ 3919 { 22, 21, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
3329 { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ 3920 { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
3330 { 22, 22, 22, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ 3921 { 22, 22, 22, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
3331 { 22, 21, 22, 4, 5, 48, ZSTD_btopt }, /* level 16 */ 3922 { 22, 21, 22, 4, 5, 48, ZSTD_btopt }, /* level 16 */
3332 { 23, 22, 22, 4, 4, 48, ZSTD_btopt }, /* level 17 */ 3923 { 23, 22, 22, 4, 4, 64, ZSTD_btopt }, /* level 17 */
3333 { 23, 22, 22, 5, 3, 64, ZSTD_btopt }, /* level 18 */ 3924 { 23, 23, 22, 6, 3,256, ZSTD_btopt }, /* level 18 */
3334 { 23, 23, 22, 7, 3,128, ZSTD_btopt }, /* level 19 */ 3925 { 23, 24, 22, 7, 3,256, ZSTD_btultra }, /* level 19 */
3335 { 25, 25, 23, 7, 3,128, ZSTD_btultra }, /* level 20 */ 3926 { 25, 25, 23, 7, 3,256, ZSTD_btultra }, /* level 20 */
3336 { 26, 26, 24, 7, 3,256, ZSTD_btultra }, /* level 21 */ 3927 { 26, 26, 24, 7, 3,512, ZSTD_btultra }, /* level 21 */
3337 { 27, 27, 25, 9, 3,512, ZSTD_btultra }, /* level 22 */ 3928 { 27, 27, 25, 9, 3,999, ZSTD_btultra }, /* level 22 */
3338 }, 3929 },
3339 { /* for srcSize <= 256 KB */ 3930 { /* for srcSize <= 256 KB */
3340 /* W, C, H, S, L, T, strat */ 3931 /* W, C, H, S, L, T, strat */
3341 { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ 3932 { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
3342 { 18, 13, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */ 3933 { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
3343 { 18, 14, 13, 1, 5, 8, ZSTD_dfast }, /* level 2 */ 3934 { 18, 14, 14, 1, 5, 1, ZSTD_dfast }, /* level 2 */
3344 { 18, 16, 15, 1, 5, 8, ZSTD_dfast }, /* level 3 */ 3935 { 18, 16, 16, 1, 4, 1, ZSTD_dfast }, /* level 3 */
3345 { 18, 15, 17, 1, 5, 8, ZSTD_greedy }, /* level 4.*/ 3936 { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
3346 { 18, 16, 17, 4, 5, 8, ZSTD_greedy }, /* level 5.*/ 3937 { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
3347 { 18, 16, 17, 3, 5, 8, ZSTD_lazy }, /* level 6.*/ 3938 { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
3348 { 18, 17, 17, 4, 4, 8, ZSTD_lazy }, /* level 7 */ 3939 { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */
3349 { 18, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ 3940 { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
3350 { 18, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ 3941 { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
3351 { 18, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ 3942 { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
3352 { 18, 18, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 11.*/ 3943 { 18, 18, 19, 5, 4, 16, ZSTD_btlazy2 }, /* level 11.*/
3353 { 18, 18, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 12.*/ 3944 { 18, 19, 19, 6, 4, 16, ZSTD_btlazy2 }, /* level 12.*/
3354 { 18, 19, 17, 7, 4, 8, ZSTD_btlazy2 }, /* level 13 */ 3945 { 18, 19, 19, 8, 4, 16, ZSTD_btlazy2 }, /* level 13 */
3355 { 18, 18, 18, 4, 4, 16, ZSTD_btopt }, /* level 14.*/ 3946 { 18, 18, 19, 4, 4, 24, ZSTD_btopt }, /* level 14.*/
3356 { 18, 18, 18, 4, 3, 16, ZSTD_btopt }, /* level 15.*/ 3947 { 18, 18, 19, 4, 3, 24, ZSTD_btopt }, /* level 15.*/
3357 { 18, 19, 18, 6, 3, 32, ZSTD_btopt }, /* level 16.*/ 3948 { 18, 19, 19, 6, 3, 64, ZSTD_btopt }, /* level 16.*/
3358 { 18, 19, 18, 8, 3, 64, ZSTD_btopt }, /* level 17.*/ 3949 { 18, 19, 19, 8, 3,128, ZSTD_btopt }, /* level 17.*/
3359 { 18, 19, 18, 9, 3,128, ZSTD_btopt }, /* level 18.*/ 3950 { 18, 19, 19, 10, 3,256, ZSTD_btopt }, /* level 18.*/
3360 { 18, 19, 18, 10, 3,256, ZSTD_btopt }, /* level 19.*/ 3951 { 18, 19, 19, 10, 3,256, ZSTD_btultra }, /* level 19.*/
3361 { 18, 19, 18, 11, 3,512, ZSTD_btultra }, /* level 20.*/ 3952 { 18, 19, 19, 11, 3,512, ZSTD_btultra }, /* level 20.*/
3362 { 18, 19, 18, 12, 3,512, ZSTD_btultra }, /* level 21.*/ 3953 { 18, 19, 19, 12, 3,512, ZSTD_btultra }, /* level 21.*/
3363 { 18, 19, 18, 13, 3,512, ZSTD_btultra }, /* level 22.*/ 3954 { 18, 19, 19, 13, 3,999, ZSTD_btultra }, /* level 22.*/
3364 }, 3955 },
3365 { /* for srcSize <= 128 KB */ 3956 { /* for srcSize <= 128 KB */
3366 /* W, C, H, S, L, T, strat */ 3957 /* W, C, H, S, L, T, strat */
3367 { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* level 0 - not used */ 3958 { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
3368 { 17, 12, 13, 1, 6, 1, ZSTD_fast }, /* level 1 */ 3959 { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
3369 { 17, 13, 16, 1, 5, 1, ZSTD_fast }, /* level 2 */ 3960 { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
3370 { 17, 16, 16, 2, 5, 8, ZSTD_dfast }, /* level 3 */ 3961 { 17, 15, 16, 2, 5, 1, ZSTD_dfast }, /* level 3 */
3371 { 17, 13, 15, 3, 4, 8, ZSTD_greedy }, /* level 4 */ 3962 { 17, 17, 17, 2, 4, 1, ZSTD_dfast }, /* level 4 */
3372 { 17, 15, 17, 4, 4, 8, ZSTD_greedy }, /* level 5 */ 3963 { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
3373 { 17, 16, 17, 3, 4, 8, ZSTD_lazy }, /* level 6 */ 3964 { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
3374 { 17, 15, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 7 */ 3965 { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
3375 { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ 3966 { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
3376 { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ 3967 { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
3377 { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ 3968 { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
3378 { 17, 17, 17, 7, 4, 8, ZSTD_lazy2 }, /* level 11 */ 3969 { 17, 17, 17, 7, 4, 8, ZSTD_lazy2 }, /* level 11 */
3379 { 17, 17, 17, 8, 4, 8, ZSTD_lazy2 }, /* level 12 */ 3970 { 17, 18, 17, 6, 4, 16, ZSTD_btlazy2 }, /* level 12 */
3380 { 17, 18, 17, 6, 4, 8, ZSTD_btlazy2 }, /* level 13.*/ 3971 { 17, 18, 17, 8, 4, 16, ZSTD_btlazy2 }, /* level 13.*/
3381 { 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/ 3972 { 17, 18, 17, 4, 4, 32, ZSTD_btopt }, /* level 14.*/
3382 { 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/ 3973 { 17, 18, 17, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
3383 { 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/ 3974 { 17, 18, 17, 7, 3,128, ZSTD_btopt }, /* level 16.*/
3384 { 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/ 3975 { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 17.*/
3385 { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/ 3976 { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 18.*/
3386 { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/ 3977 { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 19.*/
3387 { 17, 18, 17, 9, 3,256, ZSTD_btultra }, /* level 20.*/ 3978 { 17, 18, 17, 9, 3,256, ZSTD_btultra }, /* level 20.*/
3388 { 17, 18, 17, 10, 3,256, ZSTD_btultra }, /* level 21.*/ 3979 { 17, 18, 17, 10, 3,256, ZSTD_btultra }, /* level 21.*/
3389 { 17, 18, 17, 11, 3,512, ZSTD_btultra }, /* level 22.*/ 3980 { 17, 18, 17, 11, 3,512, ZSTD_btultra }, /* level 22.*/
3390 }, 3981 },
3391 { /* for srcSize <= 16 KB */ 3982 { /* for srcSize <= 16 KB */
3392 /* W, C, H, S, L, T, strat */ 3983 /* W, C, H, S, L, T, strat */
3393 { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ 3984 { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
3394 { 14, 14, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */ 3985 { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
3395 { 14, 14, 14, 1, 4, 1, ZSTD_fast }, /* level 2 */ 3986 { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
3396 { 14, 14, 14, 1, 4, 6, ZSTD_dfast }, /* level 3.*/ 3987 { 14, 14, 14, 2, 4, 1, ZSTD_dfast }, /* level 3.*/
3397 { 14, 14, 14, 4, 4, 6, ZSTD_greedy }, /* level 4.*/ 3988 { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4.*/
3398 { 14, 14, 14, 3, 4, 6, ZSTD_lazy }, /* level 5.*/ 3989 { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
3399 { 14, 14, 14, 4, 4, 6, ZSTD_lazy2 }, /* level 6 */ 3990 { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
3400 { 14, 14, 14, 5, 4, 6, ZSTD_lazy2 }, /* level 7 */ 3991 { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */
3401 { 14, 14, 14, 6, 4, 6, ZSTD_lazy2 }, /* level 8.*/ 3992 { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/
3402 { 14, 15, 14, 6, 4, 6, ZSTD_btlazy2 }, /* level 9.*/ 3993 { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/
3403 { 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/ 3994 { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/
3404 { 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/ 3995 { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/
3405 { 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/ 3996 { 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
3406 { 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/ 3997 { 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
3407 { 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/ 3998 { 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
3408 { 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/ 3999 { 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
3409 { 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/ 4000 { 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
3410 { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/ 4001 { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
3411 { 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/ 4002 { 14, 15, 15, 8, 3,256, ZSTD_btopt }, /* level 18.*/
3412 { 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/ 4003 { 14, 15, 15, 6, 3,256, ZSTD_btultra }, /* level 19.*/
3413 { 14, 15, 15, 8, 3,256, ZSTD_btultra }, /* level 20.*/ 4004 { 14, 15, 15, 8, 3,256, ZSTD_btultra }, /* level 20.*/
3414 { 14, 15, 15, 9, 3,256, ZSTD_btultra }, /* level 21.*/ 4005 { 14, 15, 15, 9, 3,256, ZSTD_btultra }, /* level 21.*/
3415 { 14, 15, 15, 10, 3,256, ZSTD_btultra }, /* level 22.*/ 4006 { 14, 15, 15, 10, 3,512, ZSTD_btultra }, /* level 22.*/
3416 }, 4007 },
3417 }; 4008 };
3418 4009
3419 /*! ZSTD_getCParams() : 4010 /*! ZSTD_getCParams() :
3420 * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. 4011 * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.