comparison contrib/python-zstandard/zstd/compress/zstd_compress.c @ 42937:69de49c4e39c

zstandard: vendor python-zstandard 0.12 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. test-repo-compengines.t was updated to reflect a change in behavior of the zstd library. The project contains a vendored copy of zstandard 1.4.3. The old version was 1.3.8. This should result in some minor performance wins. # no-check-commit because 3rd party code has different style guidelines Differential Revision: https://phab.mercurial-scm.org/D6858
author Gregory Szorc <gregory.szorc@gmail.com>
date Sun, 15 Sep 2019 20:04:00 -0700
parents 675775c33ab6
children de7838053207
comparison
equal deleted inserted replaced
42936:2da754532dd3 42937:69de49c4e39c
19 #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ 19 #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
20 #include "fse.h" 20 #include "fse.h"
21 #define HUF_STATIC_LINKING_ONLY 21 #define HUF_STATIC_LINKING_ONLY
22 #include "huf.h" 22 #include "huf.h"
23 #include "zstd_compress_internal.h" 23 #include "zstd_compress_internal.h"
24 #include "zstd_compress_sequences.h"
25 #include "zstd_compress_literals.h"
24 #include "zstd_fast.h" 26 #include "zstd_fast.h"
25 #include "zstd_double_fast.h" 27 #include "zstd_double_fast.h"
26 #include "zstd_lazy.h" 28 #include "zstd_lazy.h"
27 #include "zstd_opt.h" 29 #include "zstd_opt.h"
28 #include "zstd_ldm.h" 30 #include "zstd_ldm.h"
101 } 103 }
102 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); 104 cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
103 return cctx; 105 return cctx;
104 } 106 }
105 107
108 /**
109 * Clears and frees all of the dictionaries in the CCtx.
110 */
111 static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
112 {
113 ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
114 ZSTD_freeCDict(cctx->localDict.cdict);
115 memset(&cctx->localDict, 0, sizeof(cctx->localDict));
116 memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
117 cctx->cdict = NULL;
118 }
119
120 static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
121 {
122 size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
123 size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
124 return bufferSize + cdictSize;
125 }
126
106 static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx) 127 static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
107 { 128 {
108 assert(cctx != NULL); 129 assert(cctx != NULL);
109 assert(cctx->staticSize == 0); 130 assert(cctx->staticSize == 0);
110 ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL; 131 ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
111 ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL; 132 ZSTD_clearAllDicts(cctx);
112 #ifdef ZSTD_MULTITHREAD 133 #ifdef ZSTD_MULTITHREAD
113 ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL; 134 ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
114 #endif 135 #endif
115 } 136 }
116 137
117 size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) 138 size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
118 { 139 {
119 if (cctx==NULL) return 0; /* support free on NULL */ 140 if (cctx==NULL) return 0; /* support free on NULL */
120 if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */ 141 RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
142 "not compatible with static CCtx");
121 ZSTD_freeCCtxContent(cctx); 143 ZSTD_freeCCtxContent(cctx);
122 ZSTD_free(cctx, cctx->customMem); 144 ZSTD_free(cctx, cctx->customMem);
123 return 0; 145 return 0;
124 } 146 }
125 147
137 159
138 size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx) 160 size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
139 { 161 {
140 if (cctx==NULL) return 0; /* support sizeof on NULL */ 162 if (cctx==NULL) return 0; /* support sizeof on NULL */
141 return sizeof(*cctx) + cctx->workSpaceSize 163 return sizeof(*cctx) + cctx->workSpaceSize
142 + ZSTD_sizeof_CDict(cctx->cdictLocal) 164 + ZSTD_sizeof_localDict(cctx->localDict)
143 + ZSTD_sizeof_mtctx(cctx); 165 + ZSTD_sizeof_mtctx(cctx);
144 } 166 }
145 167
146 size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) 168 size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
147 { 169 {
193 { 215 {
194 return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT); 216 return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
195 } 217 }
196 218
197 size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) { 219 size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
198 if (!cctxParams) { return ERROR(GENERIC); } 220 RETURN_ERROR_IF(!cctxParams, GENERIC);
199 memset(cctxParams, 0, sizeof(*cctxParams)); 221 memset(cctxParams, 0, sizeof(*cctxParams));
200 cctxParams->compressionLevel = compressionLevel; 222 cctxParams->compressionLevel = compressionLevel;
201 cctxParams->fParams.contentSizeFlag = 1; 223 cctxParams->fParams.contentSizeFlag = 1;
202 return 0; 224 return 0;
203 } 225 }
204 226
205 size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) 227 size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
206 { 228 {
207 if (!cctxParams) { return ERROR(GENERIC); } 229 RETURN_ERROR_IF(!cctxParams, GENERIC);
208 CHECK_F( ZSTD_checkCParams(params.cParams) ); 230 FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
209 memset(cctxParams, 0, sizeof(*cctxParams)); 231 memset(cctxParams, 0, sizeof(*cctxParams));
210 cctxParams->cParams = params.cParams; 232 cctxParams->cParams = params.cParams;
211 cctxParams->fParams = params.fParams; 233 cctxParams->fParams = params.fParams;
212 cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ 234 cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
213 assert(!ZSTD_checkCParams(params.cParams)); 235 assert(!ZSTD_checkCParams(params.cParams));
357 ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy); 379 ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy);
358 bounds.lowerBound = ZSTD_dictDefaultAttach; 380 bounds.lowerBound = ZSTD_dictDefaultAttach;
359 bounds.upperBound = ZSTD_dictForceCopy; /* note : how to ensure at compile time that this is the highest value enum ? */ 381 bounds.upperBound = ZSTD_dictForceCopy; /* note : how to ensure at compile time that this is the highest value enum ? */
360 return bounds; 382 return bounds;
361 383
384 case ZSTD_c_literalCompressionMode:
385 ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
386 bounds.lowerBound = ZSTD_lcm_auto;
387 bounds.upperBound = ZSTD_lcm_uncompressed;
388 return bounds;
389
390 case ZSTD_c_targetCBlockSize:
391 bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;
392 bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;
393 return bounds;
394
362 default: 395 default:
363 { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 }; 396 { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 };
364 return boundError; 397 return boundError;
365 } 398 }
366 } 399 }
367 } 400 }
368 401
369 /* ZSTD_cParam_withinBounds: 402 /* ZSTD_cParam_clampBounds:
370 * @return 1 if value is within cParam bounds, 403 * Clamps the value into the bounded range.
371 * 0 otherwise */ 404 */
372 static int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value) 405 static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
373 { 406 {
374 ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); 407 ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
375 if (ZSTD_isError(bounds.error)) return 0; 408 if (ZSTD_isError(bounds.error)) return bounds.error;
376 if (value < bounds.lowerBound) return 0; 409 if (*value < bounds.lowerBound) *value = bounds.lowerBound;
377 if (value > bounds.upperBound) return 0; 410 if (*value > bounds.upperBound) *value = bounds.upperBound;
378 return 1; 411 return 0;
379 } 412 }
380 413
381 #define BOUNDCHECK(cParam, val) { \ 414 #define BOUNDCHECK(cParam, val) { \
382 if (!ZSTD_cParam_withinBounds(cParam,val)) { \ 415 RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
383 return ERROR(parameter_outOfBound); \ 416 parameter_outOfBound); \
384 } } 417 }
385 418
386 419
387 static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) 420 static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
388 { 421 {
389 switch(param) 422 switch(param)
411 case ZSTD_c_ldmHashLog: 444 case ZSTD_c_ldmHashLog:
412 case ZSTD_c_ldmMinMatch: 445 case ZSTD_c_ldmMinMatch:
413 case ZSTD_c_ldmBucketSizeLog: 446 case ZSTD_c_ldmBucketSizeLog:
414 case ZSTD_c_ldmHashRateLog: 447 case ZSTD_c_ldmHashRateLog:
415 case ZSTD_c_forceAttachDict: 448 case ZSTD_c_forceAttachDict:
449 case ZSTD_c_literalCompressionMode:
450 case ZSTD_c_targetCBlockSize:
416 default: 451 default:
417 return 0; 452 return 0;
418 } 453 }
419 } 454 }
420 455
423 DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value); 458 DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value);
424 if (cctx->streamStage != zcss_init) { 459 if (cctx->streamStage != zcss_init) {
425 if (ZSTD_isUpdateAuthorized(param)) { 460 if (ZSTD_isUpdateAuthorized(param)) {
426 cctx->cParamsChanged = 1; 461 cctx->cParamsChanged = 1;
427 } else { 462 } else {
428 return ERROR(stage_wrong); 463 RETURN_ERROR(stage_wrong);
429 } } 464 } }
430 465
431 switch(param) 466 switch(param)
432 { 467 {
433 case ZSTD_c_format : 468 case ZSTD_c_nbWorkers:
434 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 469 RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
470 "MT not compatible with static alloc");
471 break;
435 472
436 case ZSTD_c_compressionLevel: 473 case ZSTD_c_compressionLevel:
437 if (cctx->cdict) return ERROR(stage_wrong);
438 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
439
440 case ZSTD_c_windowLog: 474 case ZSTD_c_windowLog:
441 case ZSTD_c_hashLog: 475 case ZSTD_c_hashLog:
442 case ZSTD_c_chainLog: 476 case ZSTD_c_chainLog:
443 case ZSTD_c_searchLog: 477 case ZSTD_c_searchLog:
444 case ZSTD_c_minMatch: 478 case ZSTD_c_minMatch:
445 case ZSTD_c_targetLength: 479 case ZSTD_c_targetLength:
446 case ZSTD_c_strategy: 480 case ZSTD_c_strategy:
447 if (cctx->cdict) return ERROR(stage_wrong); 481 case ZSTD_c_ldmHashRateLog:
448 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 482 case ZSTD_c_format:
449
450 case ZSTD_c_contentSizeFlag: 483 case ZSTD_c_contentSizeFlag:
451 case ZSTD_c_checksumFlag: 484 case ZSTD_c_checksumFlag:
452 case ZSTD_c_dictIDFlag: 485 case ZSTD_c_dictIDFlag:
453 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 486 case ZSTD_c_forceMaxWindow:
454
455 case ZSTD_c_forceMaxWindow : /* Force back-references to remain < windowSize,
456 * even when referencing into Dictionary content.
457 * default : 0 when using a CDict, 1 when using a Prefix */
458 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
459
460 case ZSTD_c_forceAttachDict: 487 case ZSTD_c_forceAttachDict:
461 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 488 case ZSTD_c_literalCompressionMode:
462
463 case ZSTD_c_nbWorkers:
464 if ((value!=0) && cctx->staticSize) {
465 return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
466 }
467 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
468
469 case ZSTD_c_jobSize: 489 case ZSTD_c_jobSize:
470 case ZSTD_c_overlapLog: 490 case ZSTD_c_overlapLog:
471 case ZSTD_c_rsyncable: 491 case ZSTD_c_rsyncable:
472 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
473
474 case ZSTD_c_enableLongDistanceMatching: 492 case ZSTD_c_enableLongDistanceMatching:
475 case ZSTD_c_ldmHashLog: 493 case ZSTD_c_ldmHashLog:
476 case ZSTD_c_ldmMinMatch: 494 case ZSTD_c_ldmMinMatch:
477 case ZSTD_c_ldmBucketSizeLog: 495 case ZSTD_c_ldmBucketSizeLog:
478 case ZSTD_c_ldmHashRateLog: 496 case ZSTD_c_targetCBlockSize:
479 if (cctx->cdict) return ERROR(stage_wrong); 497 break;
480 return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value); 498
481 499 default: RETURN_ERROR(parameter_unsupported);
482 default: return ERROR(parameter_unsupported); 500 }
483 } 501 return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
484 } 502 }
485 503
486 size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams, 504 size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
487 ZSTD_cParameter param, int value) 505 ZSTD_cParameter param, int value)
488 { 506 {
489 DEBUGLOG(4, "ZSTD_CCtxParam_setParameter (%i, %i)", (int)param, value); 507 DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
490 switch(param) 508 switch(param)
491 { 509 {
492 case ZSTD_c_format : 510 case ZSTD_c_format :
493 BOUNDCHECK(ZSTD_c_format, value); 511 BOUNDCHECK(ZSTD_c_format, value);
494 CCtxParams->format = (ZSTD_format_e)value; 512 CCtxParams->format = (ZSTD_format_e)value;
495 return (size_t)CCtxParams->format; 513 return (size_t)CCtxParams->format;
496 514
497 case ZSTD_c_compressionLevel : { 515 case ZSTD_c_compressionLevel : {
498 int cLevel = value; 516 FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
499 if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); 517 if (value) { /* 0 : does not change current level */
500 if (cLevel < ZSTD_minCLevel()) cLevel = ZSTD_minCLevel(); 518 CCtxParams->compressionLevel = value;
501 if (cLevel) { /* 0 : does not change current level */
502 CCtxParams->compressionLevel = cLevel;
503 } 519 }
504 if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel; 520 if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
505 return 0; /* return type (size_t) cannot represent negative values */ 521 return 0; /* return type (size_t) cannot represent negative values */
506 } 522 }
507 523
571 BOUNDCHECK(ZSTD_c_forceAttachDict, pref); 587 BOUNDCHECK(ZSTD_c_forceAttachDict, pref);
572 CCtxParams->attachDictPref = pref; 588 CCtxParams->attachDictPref = pref;
573 return CCtxParams->attachDictPref; 589 return CCtxParams->attachDictPref;
574 } 590 }
575 591
592 case ZSTD_c_literalCompressionMode : {
593 const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
594 BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
595 CCtxParams->literalCompressionMode = lcm;
596 return CCtxParams->literalCompressionMode;
597 }
598
576 case ZSTD_c_nbWorkers : 599 case ZSTD_c_nbWorkers :
577 #ifndef ZSTD_MULTITHREAD 600 #ifndef ZSTD_MULTITHREAD
578 if (value!=0) return ERROR(parameter_unsupported); 601 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
579 return 0; 602 return 0;
580 #else 603 #else
581 return ZSTDMT_CCtxParam_setNbWorkers(CCtxParams, value); 604 FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
605 CCtxParams->nbWorkers = value;
606 return CCtxParams->nbWorkers;
582 #endif 607 #endif
583 608
584 case ZSTD_c_jobSize : 609 case ZSTD_c_jobSize :
585 #ifndef ZSTD_MULTITHREAD 610 #ifndef ZSTD_MULTITHREAD
586 return ERROR(parameter_unsupported); 611 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
612 return 0;
587 #else 613 #else
588 return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value); 614 /* Adjust to the minimum non-default value. */
615 if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
616 value = ZSTDMT_JOBSIZE_MIN;
617 FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
618 assert(value >= 0);
619 CCtxParams->jobSize = value;
620 return CCtxParams->jobSize;
589 #endif 621 #endif
590 622
591 case ZSTD_c_overlapLog : 623 case ZSTD_c_overlapLog :
592 #ifndef ZSTD_MULTITHREAD 624 #ifndef ZSTD_MULTITHREAD
593 return ERROR(parameter_unsupported); 625 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
626 return 0;
594 #else 627 #else
595 return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapLog, value); 628 FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
629 CCtxParams->overlapLog = value;
630 return CCtxParams->overlapLog;
596 #endif 631 #endif
597 632
598 case ZSTD_c_rsyncable : 633 case ZSTD_c_rsyncable :
599 #ifndef ZSTD_MULTITHREAD 634 #ifndef ZSTD_MULTITHREAD
600 return ERROR(parameter_unsupported); 635 RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
636 return 0;
601 #else 637 #else
602 return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_rsyncable, value); 638 FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
639 CCtxParams->rsyncable = value;
640 return CCtxParams->rsyncable;
603 #endif 641 #endif
604 642
605 case ZSTD_c_enableLongDistanceMatching : 643 case ZSTD_c_enableLongDistanceMatching :
606 CCtxParams->ldmParams.enableLdm = (value!=0); 644 CCtxParams->ldmParams.enableLdm = (value!=0);
607 return CCtxParams->ldmParams.enableLdm; 645 return CCtxParams->ldmParams.enableLdm;
623 BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value); 661 BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value);
624 CCtxParams->ldmParams.bucketSizeLog = value; 662 CCtxParams->ldmParams.bucketSizeLog = value;
625 return CCtxParams->ldmParams.bucketSizeLog; 663 return CCtxParams->ldmParams.bucketSizeLog;
626 664
627 case ZSTD_c_ldmHashRateLog : 665 case ZSTD_c_ldmHashRateLog :
628 if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) 666 RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
629 return ERROR(parameter_outOfBound); 667 parameter_outOfBound);
630 CCtxParams->ldmParams.hashRateLog = value; 668 CCtxParams->ldmParams.hashRateLog = value;
631 return CCtxParams->ldmParams.hashRateLog; 669 return CCtxParams->ldmParams.hashRateLog;
632 670
633 default: return ERROR(parameter_unsupported); 671 case ZSTD_c_targetCBlockSize :
672 if (value!=0) /* 0 ==> default */
673 BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
674 CCtxParams->targetCBlockSize = value;
675 return CCtxParams->targetCBlockSize;
676
677 default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
634 } 678 }
635 } 679 }
636 680
637 size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value) 681 size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
638 { 682 {
639 return ZSTD_CCtxParam_getParameter(&cctx->requestedParams, param, value); 683 return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
640 } 684 }
641 685
642 size_t ZSTD_CCtxParam_getParameter( 686 size_t ZSTD_CCtxParams_getParameter(
643 ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value) 687 ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
644 { 688 {
645 switch(param) 689 switch(param)
646 { 690 {
647 case ZSTD_c_format : 691 case ZSTD_c_format :
649 break; 693 break;
650 case ZSTD_c_compressionLevel : 694 case ZSTD_c_compressionLevel :
651 *value = CCtxParams->compressionLevel; 695 *value = CCtxParams->compressionLevel;
652 break; 696 break;
653 case ZSTD_c_windowLog : 697 case ZSTD_c_windowLog :
654 *value = CCtxParams->cParams.windowLog; 698 *value = (int)CCtxParams->cParams.windowLog;
655 break; 699 break;
656 case ZSTD_c_hashLog : 700 case ZSTD_c_hashLog :
657 *value = CCtxParams->cParams.hashLog; 701 *value = (int)CCtxParams->cParams.hashLog;
658 break; 702 break;
659 case ZSTD_c_chainLog : 703 case ZSTD_c_chainLog :
660 *value = CCtxParams->cParams.chainLog; 704 *value = (int)CCtxParams->cParams.chainLog;
661 break; 705 break;
662 case ZSTD_c_searchLog : 706 case ZSTD_c_searchLog :
663 *value = CCtxParams->cParams.searchLog; 707 *value = CCtxParams->cParams.searchLog;
664 break; 708 break;
665 case ZSTD_c_minMatch : 709 case ZSTD_c_minMatch :
684 *value = CCtxParams->forceWindow; 728 *value = CCtxParams->forceWindow;
685 break; 729 break;
686 case ZSTD_c_forceAttachDict : 730 case ZSTD_c_forceAttachDict :
687 *value = CCtxParams->attachDictPref; 731 *value = CCtxParams->attachDictPref;
688 break; 732 break;
733 case ZSTD_c_literalCompressionMode :
734 *value = CCtxParams->literalCompressionMode;
735 break;
689 case ZSTD_c_nbWorkers : 736 case ZSTD_c_nbWorkers :
690 #ifndef ZSTD_MULTITHREAD 737 #ifndef ZSTD_MULTITHREAD
691 assert(CCtxParams->nbWorkers == 0); 738 assert(CCtxParams->nbWorkers == 0);
692 #endif 739 #endif
693 *value = CCtxParams->nbWorkers; 740 *value = CCtxParams->nbWorkers;
694 break; 741 break;
695 case ZSTD_c_jobSize : 742 case ZSTD_c_jobSize :
696 #ifndef ZSTD_MULTITHREAD 743 #ifndef ZSTD_MULTITHREAD
697 return ERROR(parameter_unsupported); 744 RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
698 #else 745 #else
699 assert(CCtxParams->jobSize <= INT_MAX); 746 assert(CCtxParams->jobSize <= INT_MAX);
700 *value = (int)CCtxParams->jobSize; 747 *value = (int)CCtxParams->jobSize;
701 break; 748 break;
702 #endif 749 #endif
703 case ZSTD_c_overlapLog : 750 case ZSTD_c_overlapLog :
704 #ifndef ZSTD_MULTITHREAD 751 #ifndef ZSTD_MULTITHREAD
705 return ERROR(parameter_unsupported); 752 RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
706 #else 753 #else
707 *value = CCtxParams->overlapLog; 754 *value = CCtxParams->overlapLog;
708 break; 755 break;
709 #endif 756 #endif
710 case ZSTD_c_rsyncable : 757 case ZSTD_c_rsyncable :
711 #ifndef ZSTD_MULTITHREAD 758 #ifndef ZSTD_MULTITHREAD
712 return ERROR(parameter_unsupported); 759 RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
713 #else 760 #else
714 *value = CCtxParams->rsyncable; 761 *value = CCtxParams->rsyncable;
715 break; 762 break;
716 #endif 763 #endif
717 case ZSTD_c_enableLongDistanceMatching : 764 case ZSTD_c_enableLongDistanceMatching :
727 *value = CCtxParams->ldmParams.bucketSizeLog; 774 *value = CCtxParams->ldmParams.bucketSizeLog;
728 break; 775 break;
729 case ZSTD_c_ldmHashRateLog : 776 case ZSTD_c_ldmHashRateLog :
730 *value = CCtxParams->ldmParams.hashRateLog; 777 *value = CCtxParams->ldmParams.hashRateLog;
731 break; 778 break;
732 default: return ERROR(parameter_unsupported); 779 case ZSTD_c_targetCBlockSize :
780 *value = (int)CCtxParams->targetCBlockSize;
781 break;
782 default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
733 } 783 }
734 return 0; 784 return 0;
735 } 785 }
736 786
737 /** ZSTD_CCtx_setParametersUsingCCtxParams() : 787 /** ZSTD_CCtx_setParametersUsingCCtxParams() :
743 */ 793 */
744 size_t ZSTD_CCtx_setParametersUsingCCtxParams( 794 size_t ZSTD_CCtx_setParametersUsingCCtxParams(
745 ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params) 795 ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
746 { 796 {
747 DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams"); 797 DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
748 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); 798 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
749 if (cctx->cdict) return ERROR(stage_wrong); 799 RETURN_ERROR_IF(cctx->cdict, stage_wrong);
750 800
751 cctx->requestedParams = *params; 801 cctx->requestedParams = *params;
752 return 0; 802 return 0;
753 } 803 }
754 804
755 ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize) 805 ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
756 { 806 {
757 DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize); 807 DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
758 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); 808 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
759 cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1; 809 cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
810 return 0;
811 }
812
813 /**
814 * Initializes the local dict using the requested parameters.
815 * NOTE: This does not use the pledged src size, because it may be used for more
816 * than one compression.
817 */
818 static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
819 {
820 ZSTD_localDict* const dl = &cctx->localDict;
821 ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
822 &cctx->requestedParams, 0, dl->dictSize);
823 if (dl->dict == NULL) {
824 /* No local dictionary. */
825 assert(dl->dictBuffer == NULL);
826 assert(dl->cdict == NULL);
827 assert(dl->dictSize == 0);
828 return 0;
829 }
830 if (dl->cdict != NULL) {
831 assert(cctx->cdict == dl->cdict);
832 /* Local dictionary already initialized. */
833 return 0;
834 }
835 assert(dl->dictSize > 0);
836 assert(cctx->cdict == NULL);
837 assert(cctx->prefixDict.dict == NULL);
838
839 dl->cdict = ZSTD_createCDict_advanced(
840 dl->dict,
841 dl->dictSize,
842 ZSTD_dlm_byRef,
843 dl->dictContentType,
844 cParams,
845 cctx->customMem);
846 RETURN_ERROR_IF(!dl->cdict, memory_allocation);
847 cctx->cdict = dl->cdict;
760 return 0; 848 return 0;
761 } 849 }
762 850
763 size_t ZSTD_CCtx_loadDictionary_advanced( 851 size_t ZSTD_CCtx_loadDictionary_advanced(
764 ZSTD_CCtx* cctx, const void* dict, size_t dictSize, 852 ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
765 ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType) 853 ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
766 { 854 {
767 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); 855 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
768 if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */ 856 RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
857 "no malloc for static CCtx");
769 DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize); 858 DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
770 ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */ 859 ZSTD_clearAllDicts(cctx); /* in case one already exists */
771 if (dict==NULL || dictSize==0) { /* no dictionary mode */ 860 if (dict == NULL || dictSize == 0) /* no dictionary mode */
772 cctx->cdictLocal = NULL; 861 return 0;
773 cctx->cdict = NULL; 862 if (dictLoadMethod == ZSTD_dlm_byRef) {
863 cctx->localDict.dict = dict;
774 } else { 864 } else {
775 ZSTD_compressionParameters const cParams = 865 void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
776 ZSTD_getCParamsFromCCtxParams(&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize); 866 RETURN_ERROR_IF(!dictBuffer, memory_allocation);
777 cctx->cdictLocal = ZSTD_createCDict_advanced( 867 memcpy(dictBuffer, dict, dictSize);
778 dict, dictSize, 868 cctx->localDict.dictBuffer = dictBuffer;
779 dictLoadMethod, dictContentType, 869 cctx->localDict.dict = dictBuffer;
780 cParams, cctx->customMem); 870 }
781 cctx->cdict = cctx->cdictLocal; 871 cctx->localDict.dictSize = dictSize;
782 if (cctx->cdictLocal == NULL) 872 cctx->localDict.dictContentType = dictContentType;
783 return ERROR(memory_allocation);
784 }
785 return 0; 873 return 0;
786 } 874 }
787 875
788 ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference( 876 ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
789 ZSTD_CCtx* cctx, const void* dict, size_t dictSize) 877 ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
799 } 887 }
800 888
801 889
802 size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) 890 size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
803 { 891 {
804 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); 892 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
893 /* Free the existing local cdict (if any) to save memory. */
894 ZSTD_clearAllDicts(cctx);
805 cctx->cdict = cdict; 895 cctx->cdict = cdict;
806 memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
807 return 0; 896 return 0;
808 } 897 }
809 898
810 size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize) 899 size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
811 { 900 {
813 } 902 }
814 903
815 size_t ZSTD_CCtx_refPrefix_advanced( 904 size_t ZSTD_CCtx_refPrefix_advanced(
816 ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) 905 ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
817 { 906 {
818 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); 907 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
819 cctx->cdict = NULL; /* prefix discards any prior cdict */ 908 ZSTD_clearAllDicts(cctx);
820 cctx->prefixDict.dict = prefix; 909 cctx->prefixDict.dict = prefix;
821 cctx->prefixDict.dictSize = prefixSize; 910 cctx->prefixDict.dictSize = prefixSize;
822 cctx->prefixDict.dictContentType = dictContentType; 911 cctx->prefixDict.dictContentType = dictContentType;
823 return 0; 912 return 0;
824 } 913 }
832 cctx->streamStage = zcss_init; 921 cctx->streamStage = zcss_init;
833 cctx->pledgedSrcSizePlusOne = 0; 922 cctx->pledgedSrcSizePlusOne = 0;
834 } 923 }
835 if ( (reset == ZSTD_reset_parameters) 924 if ( (reset == ZSTD_reset_parameters)
836 || (reset == ZSTD_reset_session_and_parameters) ) { 925 || (reset == ZSTD_reset_session_and_parameters) ) {
837 if (cctx->streamStage != zcss_init) return ERROR(stage_wrong); 926 RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
838 cctx->cdict = NULL; 927 ZSTD_clearAllDicts(cctx);
839 return ZSTD_CCtxParams_reset(&cctx->requestedParams); 928 return ZSTD_CCtxParams_reset(&cctx->requestedParams);
840 } 929 }
841 return 0; 930 return 0;
842 } 931 }
843 932
845 /** ZSTD_checkCParams() : 934 /** ZSTD_checkCParams() :
846 control CParam values remain within authorized range. 935 control CParam values remain within authorized range.
847 @return : 0, or an error code if one value is beyond authorized range */ 936 @return : 0, or an error code if one value is beyond authorized range */
848 size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) 937 size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
849 { 938 {
850 BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog); 939 BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);
851 BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog); 940 BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog);
852 BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog); 941 BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog);
853 BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog); 942 BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);
854 BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch); 943 BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch);
855 BOUNDCHECK(ZSTD_c_targetLength,cParams.targetLength); 944 BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);
856 BOUNDCHECK(ZSTD_c_strategy, cParams.strategy); 945 BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
857 return 0; 946 return 0;
858 } 947 }
859 948
860 /** ZSTD_clampCParams() : 949 /** ZSTD_clampCParams() :
866 # define CLAMP_TYPE(cParam, val, type) { \ 955 # define CLAMP_TYPE(cParam, val, type) { \
867 ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \ 956 ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \
868 if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \ 957 if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
869 else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \ 958 else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
870 } 959 }
871 # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, int) 960 # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
872 CLAMP(ZSTD_c_windowLog, cParams.windowLog); 961 CLAMP(ZSTD_c_windowLog, cParams.windowLog);
873 CLAMP(ZSTD_c_chainLog, cParams.chainLog); 962 CLAMP(ZSTD_c_chainLog, cParams.chainLog);
874 CLAMP(ZSTD_c_hashLog, cParams.hashLog); 963 CLAMP(ZSTD_c_hashLog, cParams.hashLog);
875 CLAMP(ZSTD_c_searchLog, cParams.searchLog); 964 CLAMP(ZSTD_c_searchLog, cParams.searchLog);
876 CLAMP(ZSTD_c_minMatch, cParams.minMatch); 965 CLAMP(ZSTD_c_minMatch, cParams.minMatch);
886 U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2); 975 U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
887 return hashLog - btScale; 976 return hashLog - btScale;
888 } 977 }
889 978
890 /** ZSTD_adjustCParams_internal() : 979 /** ZSTD_adjustCParams_internal() :
891 optimize `cPar` for a given input (`srcSize` and `dictSize`). 980 * optimize `cPar` for a specified input (`srcSize` and `dictSize`).
892 mostly downsizing to reduce memory consumption and initialization latency. 981 * mostly downsize to reduce memory consumption and initialization latency.
893 Both `srcSize` and `dictSize` are optional (use 0 if unknown). 982 * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
894 Note : cPar is assumed validated. Use ZSTD_checkCParams() to ensure this condition. */ 983 * note : for the time being, `srcSize==0` means "unknown" too, for compatibility with older convention.
984 * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
895 static ZSTD_compressionParameters 985 static ZSTD_compressionParameters
896 ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, 986 ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
897 unsigned long long srcSize, 987 unsigned long long srcSize,
898 size_t dictSize) 988 size_t dictSize)
899 { 989 {
900 static const U64 minSrcSize = 513; /* (1<<9) + 1 */ 990 static const U64 minSrcSize = 513; /* (1<<9) + 1 */
901 static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); 991 static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
902 assert(ZSTD_checkCParams(cPar)==0); 992 assert(ZSTD_checkCParams(cPar)==0);
903 993
904 if (dictSize && (srcSize+1<2) /* srcSize unknown */ ) 994 if (dictSize && (srcSize+1<2) /* ZSTD_CONTENTSIZE_UNKNOWN and 0 mean "unknown" */ )
905 srcSize = minSrcSize; /* presumed small when there is a dictionary */ 995 srcSize = minSrcSize; /* presumed small when there is a dictionary */
906 else if (srcSize == 0) 996 else if (srcSize == 0)
907 srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */ 997 srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
908 998
909 /* resize windowLog if input is small enough, to use less memory */ 999 /* resize windowLog if input is small enough, to use less memory */
920 if (cycleLog > cPar.windowLog) 1010 if (cycleLog > cPar.windowLog)
921 cPar.chainLog -= (cycleLog - cPar.windowLog); 1011 cPar.chainLog -= (cycleLog - cPar.windowLog);
922 } 1012 }
923 1013
924 if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) 1014 if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
925 cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */ 1015 cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */
926 1016
927 return cPar; 1017 return cPar;
928 } 1018 }
929 1019
930 ZSTD_compressionParameters 1020 ZSTD_compressionParameters
931 ZSTD_adjustCParams(ZSTD_compressionParameters cPar, 1021 ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
932 unsigned long long srcSize, 1022 unsigned long long srcSize,
933 size_t dictSize) 1023 size_t dictSize)
934 { 1024 {
935 cPar = ZSTD_clampCParams(cPar); 1025 cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
936 return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize); 1026 return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
937 } 1027 }
938 1028
939 ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( 1029 ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
940 const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize) 1030 const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
971 return tableSpace + optSpace; 1061 return tableSpace + optSpace;
972 } 1062 }
973 1063
974 size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) 1064 size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
975 { 1065 {
976 /* Estimate CCtx size is supported for single-threaded compression only. */ 1066 RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
977 if (params->nbWorkers > 0) { return ERROR(GENERIC); }
978 { ZSTD_compressionParameters const cParams = 1067 { ZSTD_compressionParameters const cParams =
979 ZSTD_getCParamsFromCCtxParams(params, 0, 0); 1068 ZSTD_getCParamsFromCCtxParams(params, 0, 0);
980 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); 1069 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
981 U32 const divider = (cParams.minMatch==3) ? 3 : 4; 1070 U32 const divider = (cParams.minMatch==3) ? 3 : 4;
982 size_t const maxNbSeq = blockSize / divider; 1071 size_t const maxNbSeq = blockSize / divider;
1020 return memBudget; 1109 return memBudget;
1021 } 1110 }
1022 1111
1023 size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) 1112 size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1024 { 1113 {
1025 if (params->nbWorkers > 0) { return ERROR(GENERIC); } 1114 RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
1026 { size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); 1115 { ZSTD_compressionParameters const cParams =
1027 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog); 1116 ZSTD_getCParamsFromCCtxParams(params, 0, 0);
1028 size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize; 1117 size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
1118 size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
1119 size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
1029 size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; 1120 size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
1030 size_t const streamingSize = inBuffSize + outBuffSize; 1121 size_t const streamingSize = inBuffSize + outBuffSize;
1031 1122
1032 return CCtxSize + streamingSize; 1123 return CCtxSize + streamingSize;
1033 } 1124 }
1195 bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none; 1286 bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;
1196 bs->entropy.fse.litlength_repeatMode = FSE_repeat_none; 1287 bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;
1197 } 1288 }
1198 1289
1199 /*! ZSTD_invalidateMatchState() 1290 /*! ZSTD_invalidateMatchState()
1200 * Invalidate all the matches in the match finder tables. 1291 * Invalidate all the matches in the match finder tables.
1201 * Requires nextSrc and base to be set (can be NULL). 1292 * Requires nextSrc and base to be set (can be NULL).
1202 */ 1293 */
1203 static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) 1294 static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
1204 { 1295 {
1205 ZSTD_window_clear(&ms->window); 1296 ZSTD_window_clear(&ms->window);
1206 1297
1207 ms->nextToUpdate = ms->window.dictLimit; 1298 ms->nextToUpdate = ms->window.dictLimit;
1208 ms->nextToUpdate3 = ms->window.dictLimit;
1209 ms->loadedDictEnd = 0; 1299 ms->loadedDictEnd = 0;
1210 ms->opt.litLengthSum = 0; /* force reset of btopt stats */ 1300 ms->opt.litLengthSum = 0; /* force reset of btopt stats */
1211 ms->dictMatchState = NULL; 1301 ms->dictMatchState = NULL;
1212 } 1302 }
1213 1303
1240 return 0; 1330 return 0;
1241 } 1331 }
1242 1332
1243 typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e; 1333 typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
1244 1334
1335 typedef enum { ZSTD_resetTarget_CDict, ZSTD_resetTarget_CCtx } ZSTD_resetTarget_e;
1336
1245 static void* 1337 static void*
1246 ZSTD_reset_matchState(ZSTD_matchState_t* ms, 1338 ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1247 void* ptr, 1339 void* ptr,
1248 const ZSTD_compressionParameters* cParams, 1340 const ZSTD_compressionParameters* cParams,
1249 ZSTD_compResetPolicy_e const crp, U32 const forCCtx) 1341 ZSTD_compResetPolicy_e const crp, ZSTD_resetTarget_e const forWho)
1250 { 1342 {
1251 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); 1343 size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
1252 size_t const hSize = ((size_t)1) << cParams->hashLog; 1344 size_t const hSize = ((size_t)1) << cParams->hashLog;
1253 U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; 1345 U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
1254 size_t const h3Size = ((size_t)1) << hashLog3; 1346 size_t const h3Size = ((size_t)1) << hashLog3;
1255 size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); 1347 size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
1256 1348
1257 assert(((size_t)ptr & 3) == 0); 1349 assert(((size_t)ptr & 3) == 0);
1258 1350
1262 ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */ 1354 ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
1263 ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */ 1355 ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
1264 ZSTD_invalidateMatchState(ms); 1356 ZSTD_invalidateMatchState(ms);
1265 1357
1266 /* opt parser space */ 1358 /* opt parser space */
1267 if (forCCtx && (cParams->strategy >= ZSTD_btopt)) { 1359 if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
1268 DEBUGLOG(4, "reserving optimal parser space"); 1360 DEBUGLOG(4, "reserving optimal parser space");
1269 ms->opt.litFreq = (unsigned*)ptr; 1361 ms->opt.litFreq = (unsigned*)ptr;
1270 ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits); 1362 ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits);
1271 ms->opt.matchLengthFreq = ms->opt.litLengthFreq + (MaxLL+1); 1363 ms->opt.matchLengthFreq = ms->opt.litLengthFreq + (MaxLL+1);
1272 ms->opt.offCodeFreq = ms->opt.matchLengthFreq + (MaxML+1); 1364 ms->opt.offCodeFreq = ms->opt.matchLengthFreq + (MaxML+1);
1290 1382
1291 assert(((size_t)ptr & 3) == 0); 1383 assert(((size_t)ptr & 3) == 0);
1292 return ptr; 1384 return ptr;
1293 } 1385 }
1294 1386
1387 /* ZSTD_indexTooCloseToMax() :
1388 * minor optimization : prefer memset() rather than reduceIndex()
1389 * which is measurably slow in some circumstances (reported for Visual Studio).
1390 * Works when re-using a context for a lot of smallish inputs :
1391 * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN,
1392 * memset() will be triggered before reduceIndex().
1393 */
1394 #define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)
1395 static int ZSTD_indexTooCloseToMax(ZSTD_window_t w)
1396 {
1397 return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
1398 }
1399
1295 #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */ 1400 #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */
1296 #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large 1401 #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large
1297 * during at least this number of times, 1402 * during at least this number of times,
1298 * context's memory usage is considered wasteful, 1403 * context's memory usage is considered wasteful,
1299 * because it's sized to handle a worst case scenario which rarely happens. 1404 * because it's sized to handle a worst case scenario which rarely happens.
1301 1406
1302 /*! ZSTD_resetCCtx_internal() : 1407 /*! ZSTD_resetCCtx_internal() :
1303 note : `params` are assumed fully validated at this stage */ 1408 note : `params` are assumed fully validated at this stage */
1304 static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, 1409 static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1305 ZSTD_CCtx_params params, 1410 ZSTD_CCtx_params params,
1306 U64 pledgedSrcSize, 1411 U64 const pledgedSrcSize,
1307 ZSTD_compResetPolicy_e const crp, 1412 ZSTD_compResetPolicy_e const crp,
1308 ZSTD_buffered_policy_e const zbuff) 1413 ZSTD_buffered_policy_e const zbuff)
1309 { 1414 {
1310 DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u", 1415 DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
1311 (U32)pledgedSrcSize, params.cParams.windowLog); 1416 (U32)pledgedSrcSize, params.cParams.windowLog);
1313 1418
1314 if (crp == ZSTDcrp_continue) { 1419 if (crp == ZSTDcrp_continue) {
1315 if (ZSTD_equivalentParams(zc->appliedParams, params, 1420 if (ZSTD_equivalentParams(zc->appliedParams, params,
1316 zc->inBuffSize, 1421 zc->inBuffSize,
1317 zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit, 1422 zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
1318 zbuff, pledgedSrcSize)) { 1423 zbuff, pledgedSrcSize) ) {
1319 DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)", 1424 DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> consider continue mode");
1320 zc->appliedParams.cParams.windowLog, zc->blockSize);
1321 zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */ 1425 zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
1322 if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION) 1426 if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION) {
1427 DEBUGLOG(4, "continue mode confirmed (wLog1=%u, blockSize1=%zu)",
1428 zc->appliedParams.cParams.windowLog, zc->blockSize);
1429 if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) {
1430 /* prefer a reset, faster than a rescale */
1431 ZSTD_reset_matchState(&zc->blockState.matchState,
1432 zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32,
1433 &params.cParams,
1434 crp, ZSTD_resetTarget_CCtx);
1435 }
1323 return ZSTD_continueCCtx(zc, params, pledgedSrcSize); 1436 return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
1324 } } 1437 } } }
1325 DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx"); 1438 DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
1326 1439
1327 if (params.ldmParams.enableLdm) { 1440 if (params.ldmParams.enableLdm) {
1328 /* Adjust long distance matching parameters */ 1441 /* Adjust long distance matching parameters */
1329 ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams); 1442 ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
1362 DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers", 1475 DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
1363 neededSpace>>10, matchStateSize>>10, bufferSpace>>10); 1476 neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
1364 DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize); 1477 DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
1365 1478
1366 if (workSpaceTooSmall || workSpaceWasteful) { 1479 if (workSpaceTooSmall || workSpaceWasteful) {
1367 DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB", 1480 DEBUGLOG(4, "Resize workSpaceSize from %zuKB to %zuKB",
1368 zc->workSpaceSize >> 10, 1481 zc->workSpaceSize >> 10,
1369 neededSpace >> 10); 1482 neededSpace >> 10);
1370 /* static cctx : no resize, error out */ 1483
1371 if (zc->staticSize) return ERROR(memory_allocation); 1484 RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
1372 1485
1373 zc->workSpaceSize = 0; 1486 zc->workSpaceSize = 0;
1374 ZSTD_free(zc->workSpace, zc->customMem); 1487 ZSTD_free(zc->workSpace, zc->customMem);
1375 zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem); 1488 zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
1376 if (zc->workSpace == NULL) return ERROR(memory_allocation); 1489 RETURN_ERROR_IF(zc->workSpace == NULL, memory_allocation);
1377 zc->workSpaceSize = neededSpace; 1490 zc->workSpaceSize = neededSpace;
1378 zc->workSpaceOversizedDuration = 0; 1491 zc->workSpaceOversizedDuration = 0;
1379 1492
1380 /* Statically sized space. 1493 /* Statically sized space.
1381 * entropyWorkspace never moves, 1494 * entropyWorkspace never moves,
1404 zc->stage = ZSTDcs_init; 1517 zc->stage = ZSTDcs_init;
1405 zc->dictID = 0; 1518 zc->dictID = 0;
1406 1519
1407 ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock); 1520 ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
1408 1521
1409 ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32; 1522 ptr = ZSTD_reset_matchState(&zc->blockState.matchState,
1523 zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32,
1524 &params.cParams,
1525 crp, ZSTD_resetTarget_CCtx);
1410 1526
1411 /* ldm hash table */ 1527 /* ldm hash table */
1412 /* initialize bucketOffsets table later for pointer alignment */ 1528 /* initialize bucketOffsets table later for pointer alignment */
1413 if (params.ldmParams.enableLdm) { 1529 if (params.ldmParams.enableLdm) {
1414 size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog; 1530 size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
1421 zc->maxNbLdmSequences = maxNbLdmSeq; 1537 zc->maxNbLdmSequences = maxNbLdmSeq;
1422 1538
1423 memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window)); 1539 memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window));
1424 } 1540 }
1425 assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */ 1541 assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1426
1427 ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
1428 1542
1429 /* sequences storage */ 1543 /* sequences storage */
1430 zc->seqStore.maxNbSeq = maxNbSeq; 1544 zc->seqStore.maxNbSeq = maxNbSeq;
1431 zc->seqStore.sequencesStart = (seqDef*)ptr; 1545 zc->seqStore.sequencesStart = (seqDef*)ptr;
1432 ptr = zc->seqStore.sequencesStart + maxNbSeq; 1546 ptr = zc->seqStore.sequencesStart + maxNbSeq;
1500 && params.attachDictPref != ZSTD_dictForceCopy 1614 && params.attachDictPref != ZSTD_dictForceCopy
1501 && !params.forceWindow; /* dictMatchState isn't correctly 1615 && !params.forceWindow; /* dictMatchState isn't correctly
1502 * handled in _enforceMaxDist */ 1616 * handled in _enforceMaxDist */
1503 } 1617 }
1504 1618
1505 static size_t ZSTD_resetCCtx_byAttachingCDict( 1619 static size_t
1506 ZSTD_CCtx* cctx, 1620 ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
1507 const ZSTD_CDict* cdict, 1621 const ZSTD_CDict* cdict,
1508 ZSTD_CCtx_params params, 1622 ZSTD_CCtx_params params,
1509 U64 pledgedSrcSize, 1623 U64 pledgedSrcSize,
1510 ZSTD_buffered_policy_e zbuff) 1624 ZSTD_buffered_policy_e zbuff)
1511 { 1625 {
1512 { 1626 { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams;
1513 const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1514 unsigned const windowLog = params.cParams.windowLog; 1627 unsigned const windowLog = params.cParams.windowLog;
1515 assert(windowLog != 0); 1628 assert(windowLog != 0);
1516 /* Resize working context table params for input only, since the dict 1629 /* Resize working context table params for input only, since the dict
1517 * has its own tables. */ 1630 * has its own tables. */
1518 params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0); 1631 params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
1520 ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, 1633 ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1521 ZSTDcrp_continue, zbuff); 1634 ZSTDcrp_continue, zbuff);
1522 assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); 1635 assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1523 } 1636 }
1524 1637
1525 { 1638 { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1526 const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1527 - cdict->matchState.window.base); 1639 - cdict->matchState.window.base);
1528 const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit; 1640 const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
1529 if (cdictLen == 0) { 1641 if (cdictLen == 0) {
1530 /* don't even attach dictionaries with no contents */ 1642 /* don't even attach dictionaries with no contents */
1531 DEBUGLOG(4, "skipping attaching empty dictionary"); 1643 DEBUGLOG(4, "skipping attaching empty dictionary");
1538 if (cctx->blockState.matchState.window.dictLimit < cdictEnd) { 1650 if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {
1539 cctx->blockState.matchState.window.nextSrc = 1651 cctx->blockState.matchState.window.nextSrc =
1540 cctx->blockState.matchState.window.base + cdictEnd; 1652 cctx->blockState.matchState.window.base + cdictEnd;
1541 ZSTD_window_clear(&cctx->blockState.matchState.window); 1653 ZSTD_window_clear(&cctx->blockState.matchState.window);
1542 } 1654 }
1655 /* loadedDictEnd is expressed within the referential of the active context */
1543 cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit; 1656 cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
1544 } 1657 } }
1545 }
1546 1658
1547 cctx->dictID = cdict->dictID; 1659 cctx->dictID = cdict->dictID;
1548 1660
1549 /* copy block state */ 1661 /* copy block state */
1550 memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); 1662 memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
1594 /* copy dictionary offsets */ 1706 /* copy dictionary offsets */
1595 { ZSTD_matchState_t const* srcMatchState = &cdict->matchState; 1707 { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1596 ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState; 1708 ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1597 dstMatchState->window = srcMatchState->window; 1709 dstMatchState->window = srcMatchState->window;
1598 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; 1710 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1599 dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1600 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; 1711 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1601 } 1712 }
1602 1713
1603 cctx->dictID = cdict->dictID; 1714 cctx->dictID = cdict->dictID;
1604 1715
1642 ZSTD_frameParameters fParams, 1753 ZSTD_frameParameters fParams,
1643 U64 pledgedSrcSize, 1754 U64 pledgedSrcSize,
1644 ZSTD_buffered_policy_e zbuff) 1755 ZSTD_buffered_policy_e zbuff)
1645 { 1756 {
1646 DEBUGLOG(5, "ZSTD_copyCCtx_internal"); 1757 DEBUGLOG(5, "ZSTD_copyCCtx_internal");
1647 if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong); 1758 RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong);
1648 1759
1649 memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); 1760 memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
1650 { ZSTD_CCtx_params params = dstCCtx->requestedParams; 1761 { ZSTD_CCtx_params params = dstCCtx->requestedParams;
1651 /* Copy only compression parameters related to tables. */ 1762 /* Copy only compression parameters related to tables. */
1652 params.cParams = srcCCtx->appliedParams.cParams; 1763 params.cParams = srcCCtx->appliedParams.cParams;
1674 { 1785 {
1675 const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState; 1786 const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
1676 ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState; 1787 ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
1677 dstMatchState->window = srcMatchState->window; 1788 dstMatchState->window = srcMatchState->window;
1678 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; 1789 dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1679 dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1680 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; 1790 dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1681 } 1791 }
1682 dstCCtx->dictID = srcCCtx->dictID; 1792 dstCCtx->dictID = srcCCtx->dictID;
1683 1793
1684 /* copy block state */ 1794 /* copy block state */
1744 ZSTD_reduceTable_internal(table, size, reducerValue, 1); 1854 ZSTD_reduceTable_internal(table, size, reducerValue, 1);
1745 } 1855 }
1746 1856
1747 /*! ZSTD_reduceIndex() : 1857 /*! ZSTD_reduceIndex() :
1748 * rescale all indexes to avoid future overflow (indexes are U32) */ 1858 * rescale all indexes to avoid future overflow (indexes are U32) */
1749 static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue) 1859 static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
1750 { 1860 {
1751 ZSTD_matchState_t* const ms = &zc->blockState.matchState; 1861 { U32 const hSize = (U32)1 << params->cParams.hashLog;
1752 { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
1753 ZSTD_reduceTable(ms->hashTable, hSize, reducerValue); 1862 ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
1754 } 1863 }
1755 1864
1756 if (zc->appliedParams.cParams.strategy != ZSTD_fast) { 1865 if (params->cParams.strategy != ZSTD_fast) {
1757 U32 const chainSize = (U32)1 << zc->appliedParams.cParams.chainLog; 1866 U32 const chainSize = (U32)1 << params->cParams.chainLog;
1758 if (zc->appliedParams.cParams.strategy == ZSTD_btlazy2) 1867 if (params->cParams.strategy == ZSTD_btlazy2)
1759 ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue); 1868 ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
1760 else 1869 else
1761 ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue); 1870 ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
1762 } 1871 }
1763 1872
1775 /* See doc/zstd_compression_format.md for detailed format description */ 1884 /* See doc/zstd_compression_format.md for detailed format description */
1776 1885
1777 static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock) 1886 static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
1778 { 1887 {
1779 U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3); 1888 U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
1780 if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall); 1889 RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
1890 dstSize_tooSmall);
1781 MEM_writeLE24(dst, cBlockHeader24); 1891 MEM_writeLE24(dst, cBlockHeader24);
1782 memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); 1892 memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
1783 return ZSTD_blockHeaderSize + srcSize; 1893 return ZSTD_blockHeaderSize + srcSize;
1784 } 1894 }
1785
1786 static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1787 {
1788 BYTE* const ostart = (BYTE* const)dst;
1789 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
1790
1791 if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
1792
1793 switch(flSize)
1794 {
1795 case 1: /* 2 - 1 - 5 */
1796 ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3));
1797 break;
1798 case 2: /* 2 - 2 - 12 */
1799 MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));
1800 break;
1801 case 3: /* 2 - 2 - 20 */
1802 MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));
1803 break;
1804 default: /* not necessary : flSize is {1,2,3} */
1805 assert(0);
1806 }
1807
1808 memcpy(ostart + flSize, src, srcSize);
1809 return srcSize + flSize;
1810 }
1811
1812 static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1813 {
1814 BYTE* const ostart = (BYTE* const)dst;
1815 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
1816
1817 (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
1818
1819 switch(flSize)
1820 {
1821 case 1: /* 2 - 1 - 5 */
1822 ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3));
1823 break;
1824 case 2: /* 2 - 2 - 12 */
1825 MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));
1826 break;
1827 case 3: /* 2 - 2 - 20 */
1828 MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));
1829 break;
1830 default: /* not necessary : flSize is {1,2,3} */
1831 assert(0);
1832 }
1833
1834 ostart[flSize] = *(const BYTE*)src;
1835 return flSize+1;
1836 }
1837
1838
1839 /* ZSTD_minGain() :
1840 * minimum compression required
1841 * to generate a compress block or a compressed literals section.
1842 * note : use same formula for both situations */
1843 static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
1844 {
1845 U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
1846 ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
1847 assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
1848 return (srcSize >> minlog) + 2;
1849 }
1850
1851 static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
1852 ZSTD_hufCTables_t* nextHuf,
1853 ZSTD_strategy strategy, int disableLiteralCompression,
1854 void* dst, size_t dstCapacity,
1855 const void* src, size_t srcSize,
1856 void* workspace, size_t wkspSize,
1857 const int bmi2)
1858 {
1859 size_t const minGain = ZSTD_minGain(srcSize, strategy);
1860 size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
1861 BYTE* const ostart = (BYTE*)dst;
1862 U32 singleStream = srcSize < 256;
1863 symbolEncodingType_e hType = set_compressed;
1864 size_t cLitSize;
1865
1866 DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
1867 disableLiteralCompression);
1868
1869 /* Prepare nextEntropy assuming reusing the existing table */
1870 memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1871
1872 if (disableLiteralCompression)
1873 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1874
1875 /* small ? don't even attempt compression (speed opt) */
1876 # define COMPRESS_LITERALS_SIZE_MIN 63
1877 { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
1878 if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1879 }
1880
1881 if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
1882 { HUF_repeat repeat = prevHuf->repeatMode;
1883 int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
1884 if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
1885 cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1886 workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
1887 : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1888 workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
1889 if (repeat != HUF_repeat_none) {
1890 /* reused the existing table */
1891 hType = set_repeat;
1892 }
1893 }
1894
1895 if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
1896 memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1897 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1898 }
1899 if (cLitSize==1) {
1900 memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1901 return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
1902 }
1903
1904 if (hType == set_compressed) {
1905 /* using a newly constructed table */
1906 nextHuf->repeatMode = HUF_repeat_check;
1907 }
1908
1909 /* Build header */
1910 switch(lhSize)
1911 {
1912 case 3: /* 2 - 2 - 10 - 10 */
1913 { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
1914 MEM_writeLE24(ostart, lhc);
1915 break;
1916 }
1917 case 4: /* 2 - 2 - 14 - 14 */
1918 { U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);
1919 MEM_writeLE32(ostart, lhc);
1920 break;
1921 }
1922 case 5: /* 2 - 2 - 18 - 18 */
1923 { U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
1924 MEM_writeLE32(ostart, lhc);
1925 ostart[4] = (BYTE)(cLitSize >> 10);
1926 break;
1927 }
1928 default: /* not possible : lhSize is {3,4,5} */
1929 assert(0);
1930 }
1931 return lhSize+cLitSize;
1932 }
1933
1934 1895
1935 void ZSTD_seqToCodes(const seqStore_t* seqStorePtr) 1896 void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1936 { 1897 {
1937 const seqDef* const sequences = seqStorePtr->sequencesStart; 1898 const seqDef* const sequences = seqStorePtr->sequencesStart;
1938 BYTE* const llCodeTable = seqStorePtr->llCode; 1899 BYTE* const llCodeTable = seqStorePtr->llCode;
1952 llCodeTable[seqStorePtr->longLengthPos] = MaxLL; 1913 llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
1953 if (seqStorePtr->longLengthID==2) 1914 if (seqStorePtr->longLengthID==2)
1954 mlCodeTable[seqStorePtr->longLengthPos] = MaxML; 1915 mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
1955 } 1916 }
1956 1917
1957 1918 static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
1958 /** 1919 {
1959 * -log2(x / 256) lookup table for x in [0, 256). 1920 switch (cctxParams->literalCompressionMode) {
1960 * If x == 0: Return 0 1921 case ZSTD_lcm_huffman:
1961 * Else: Return floor(-log2(x / 256) * 256) 1922 return 0;
1962 */ 1923 case ZSTD_lcm_uncompressed:
1963 static unsigned const kInverseProbabiltyLog256[256] = {
1964 0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
1965 1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
1966 874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
1967 724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
1968 618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
1969 535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
1970 468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
1971 411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
1972 362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
1973 318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
1974 279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
1975 244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
1976 212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
1977 182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
1978 155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
1979 130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
1980 106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
1981 83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
1982 62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
1983 42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
1984 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
1985 5, 4, 2, 1,
1986 };
1987
1988
1989 /**
1990 * Returns the cost in bits of encoding the distribution described by count
1991 * using the entropy bound.
1992 */
1993 static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
1994 {
1995 unsigned cost = 0;
1996 unsigned s;
1997 for (s = 0; s <= max; ++s) {
1998 unsigned norm = (unsigned)((256 * count[s]) / total);
1999 if (count[s] != 0 && norm == 0)
2000 norm = 1;
2001 assert(count[s] < total);
2002 cost += count[s] * kInverseProbabiltyLog256[norm];
2003 }
2004 return cost >> 8;
2005 }
2006
2007
2008 /**
2009 * Returns the cost in bits of encoding the distribution in count using the
2010 * table described by norm. The max symbol support by norm is assumed >= max.
2011 * norm must be valid for every symbol with non-zero probability in count.
2012 */
2013 static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
2014 unsigned const* count, unsigned const max)
2015 {
2016 unsigned const shift = 8 - accuracyLog;
2017 size_t cost = 0;
2018 unsigned s;
2019 assert(accuracyLog <= 8);
2020 for (s = 0; s <= max; ++s) {
2021 unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
2022 unsigned const norm256 = normAcc << shift;
2023 assert(norm256 > 0);
2024 assert(norm256 < 256);
2025 cost += count[s] * kInverseProbabiltyLog256[norm256];
2026 }
2027 return cost >> 8;
2028 }
2029
2030
2031 static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
2032 void const* ptr = ctable;
2033 U16 const* u16ptr = (U16 const*)ptr;
2034 U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
2035 return maxSymbolValue;
2036 }
2037
2038
2039 /**
2040 * Returns the cost in bits of encoding the distribution in count using ctable.
2041 * Returns an error if ctable cannot represent all the symbols in count.
2042 */
2043 static size_t ZSTD_fseBitCost(
2044 FSE_CTable const* ctable,
2045 unsigned const* count,
2046 unsigned const max)
2047 {
2048 unsigned const kAccuracyLog = 8;
2049 size_t cost = 0;
2050 unsigned s;
2051 FSE_CState_t cstate;
2052 FSE_initCState(&cstate, ctable);
2053 if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {
2054 DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u",
2055 ZSTD_getFSEMaxSymbolValue(ctable), max);
2056 return ERROR(GENERIC);
2057 }
2058 for (s = 0; s <= max; ++s) {
2059 unsigned const tableLog = cstate.stateLog;
2060 unsigned const badCost = (tableLog + 1) << kAccuracyLog;
2061 unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
2062 if (count[s] == 0)
2063 continue;
2064 if (bitCost >= badCost) {
2065 DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s);
2066 return ERROR(GENERIC);
2067 }
2068 cost += count[s] * bitCost;
2069 }
2070 return cost >> kAccuracyLog;
2071 }
2072
2073 /**
2074 * Returns the cost in bytes of encoding the normalized count header.
2075 * Returns an error if any of the helper functions return an error.
2076 */
2077 static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
2078 size_t const nbSeq, unsigned const FSELog)
2079 {
2080 BYTE wksp[FSE_NCOUNTBOUND];
2081 S16 norm[MaxSeq + 1];
2082 const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
2083 CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
2084 return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
2085 }
2086
2087
2088 typedef enum {
2089 ZSTD_defaultDisallowed = 0,
2090 ZSTD_defaultAllowed = 1
2091 } ZSTD_defaultPolicy_e;
2092
2093 MEM_STATIC symbolEncodingType_e
2094 ZSTD_selectEncodingType(
2095 FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
2096 size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
2097 FSE_CTable const* prevCTable,
2098 short const* defaultNorm, U32 defaultNormLog,
2099 ZSTD_defaultPolicy_e const isDefaultAllowed,
2100 ZSTD_strategy const strategy)
2101 {
2102 ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
2103 if (mostFrequent == nbSeq) {
2104 *repeatMode = FSE_repeat_none;
2105 if (isDefaultAllowed && nbSeq <= 2) {
2106 /* Prefer set_basic over set_rle when there are 2 or less symbols,
2107 * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
2108 * If basic encoding isn't possible, always choose RLE.
2109 */
2110 DEBUGLOG(5, "Selected set_basic");
2111 return set_basic;
2112 }
2113 DEBUGLOG(5, "Selected set_rle");
2114 return set_rle;
2115 }
2116 if (strategy < ZSTD_lazy) {
2117 if (isDefaultAllowed) {
2118 size_t const staticFse_nbSeq_max = 1000;
2119 size_t const mult = 10 - strategy;
2120 size_t const baseLog = 3;
2121 size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
2122 assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
2123 assert(mult <= 9 && mult >= 7);
2124 if ( (*repeatMode == FSE_repeat_valid)
2125 && (nbSeq < staticFse_nbSeq_max) ) {
2126 DEBUGLOG(5, "Selected set_repeat");
2127 return set_repeat;
2128 }
2129 if ( (nbSeq < dynamicFse_nbSeq_min)
2130 || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
2131 DEBUGLOG(5, "Selected set_basic");
2132 /* The format allows default tables to be repeated, but it isn't useful.
2133 * When using simple heuristics to select encoding type, we don't want
2134 * to confuse these tables with dictionaries. When running more careful
2135 * analysis, we don't need to waste time checking both repeating tables
2136 * and default tables.
2137 */
2138 *repeatMode = FSE_repeat_none;
2139 return set_basic;
2140 }
2141 }
2142 } else {
2143 size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
2144 size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
2145 size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
2146 size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
2147
2148 if (isDefaultAllowed) {
2149 assert(!ZSTD_isError(basicCost));
2150 assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
2151 }
2152 assert(!ZSTD_isError(NCountCost));
2153 assert(compressedCost < ERROR(maxCode));
2154 DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
2155 (unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);
2156 if (basicCost <= repeatCost && basicCost <= compressedCost) {
2157 DEBUGLOG(5, "Selected set_basic");
2158 assert(isDefaultAllowed);
2159 *repeatMode = FSE_repeat_none;
2160 return set_basic;
2161 }
2162 if (repeatCost <= compressedCost) {
2163 DEBUGLOG(5, "Selected set_repeat");
2164 assert(!ZSTD_isError(repeatCost));
2165 return set_repeat;
2166 }
2167 assert(compressedCost < basicCost && compressedCost < repeatCost);
2168 }
2169 DEBUGLOG(5, "Selected set_compressed");
2170 *repeatMode = FSE_repeat_check;
2171 return set_compressed;
2172 }
2173
2174 MEM_STATIC size_t
2175 ZSTD_buildCTable(void* dst, size_t dstCapacity,
2176 FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
2177 unsigned* count, U32 max,
2178 const BYTE* codeTable, size_t nbSeq,
2179 const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
2180 const FSE_CTable* prevCTable, size_t prevCTableSize,
2181 void* workspace, size_t workspaceSize)
2182 {
2183 BYTE* op = (BYTE*)dst;
2184 const BYTE* const oend = op + dstCapacity;
2185 DEBUGLOG(6, "ZSTD_buildCTable (dstCapacity=%u)", (unsigned)dstCapacity);
2186
2187 switch (type) {
2188 case set_rle:
2189 CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
2190 if (dstCapacity==0) return ERROR(dstSize_tooSmall);
2191 *op = codeTable[0];
2192 return 1; 1924 return 1;
2193 case set_repeat: 1925 default:
2194 memcpy(nextCTable, prevCTable, prevCTableSize); 1926 assert(0 /* impossible: pre-validated */);
2195 return 0; 1927 /* fall-through */
2196 case set_basic: 1928 case ZSTD_lcm_auto:
2197 CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */ 1929 return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
2198 return 0; 1930 }
2199 case set_compressed: {
2200 S16 norm[MaxSeq + 1];
2201 size_t nbSeq_1 = nbSeq;
2202 const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
2203 if (count[codeTable[nbSeq-1]] > 1) {
2204 count[codeTable[nbSeq-1]]--;
2205 nbSeq_1--;
2206 }
2207 assert(nbSeq_1 > 1);
2208 CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
2209 { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
2210 if (FSE_isError(NCountSize)) return NCountSize;
2211 CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
2212 return NCountSize;
2213 }
2214 }
2215 default: return assert(0), ERROR(GENERIC);
2216 }
2217 }
2218
2219 FORCE_INLINE_TEMPLATE size_t
2220 ZSTD_encodeSequences_body(
2221 void* dst, size_t dstCapacity,
2222 FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2223 FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2224 FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2225 seqDef const* sequences, size_t nbSeq, int longOffsets)
2226 {
2227 BIT_CStream_t blockStream;
2228 FSE_CState_t stateMatchLength;
2229 FSE_CState_t stateOffsetBits;
2230 FSE_CState_t stateLitLength;
2231
2232 CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
2233 DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
2234 (int)(blockStream.endPtr - blockStream.startPtr),
2235 (unsigned)dstCapacity);
2236
2237 /* first symbols */
2238 FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
2239 FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
2240 FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
2241 BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
2242 if (MEM_32bits()) BIT_flushBits(&blockStream);
2243 BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
2244 if (MEM_32bits()) BIT_flushBits(&blockStream);
2245 if (longOffsets) {
2246 U32 const ofBits = ofCodeTable[nbSeq-1];
2247 int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
2248 if (extraBits) {
2249 BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
2250 BIT_flushBits(&blockStream);
2251 }
2252 BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
2253 ofBits - extraBits);
2254 } else {
2255 BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
2256 }
2257 BIT_flushBits(&blockStream);
2258
2259 { size_t n;
2260 for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
2261 BYTE const llCode = llCodeTable[n];
2262 BYTE const ofCode = ofCodeTable[n];
2263 BYTE const mlCode = mlCodeTable[n];
2264 U32 const llBits = LL_bits[llCode];
2265 U32 const ofBits = ofCode;
2266 U32 const mlBits = ML_bits[mlCode];
2267 DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
2268 (unsigned)sequences[n].litLength,
2269 (unsigned)sequences[n].matchLength + MINMATCH,
2270 (unsigned)sequences[n].offset);
2271 /* 32b*/ /* 64b*/
2272 /* (7)*/ /* (7)*/
2273 FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
2274 FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
2275 if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
2276 FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
2277 if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
2278 BIT_flushBits(&blockStream); /* (7)*/
2279 BIT_addBits(&blockStream, sequences[n].litLength, llBits);
2280 if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
2281 BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
2282 if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
2283 if (longOffsets) {
2284 int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
2285 if (extraBits) {
2286 BIT_addBits(&blockStream, sequences[n].offset, extraBits);
2287 BIT_flushBits(&blockStream); /* (7)*/
2288 }
2289 BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
2290 ofBits - extraBits); /* 31 */
2291 } else {
2292 BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
2293 }
2294 BIT_flushBits(&blockStream); /* (7)*/
2295 DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
2296 } }
2297
2298 DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
2299 FSE_flushCState(&blockStream, &stateMatchLength);
2300 DEBUGLOG(6, "ZSTD_encodeSequences: flushing Off state with %u bits", stateOffsetBits.stateLog);
2301 FSE_flushCState(&blockStream, &stateOffsetBits);
2302 DEBUGLOG(6, "ZSTD_encodeSequences: flushing LL state with %u bits", stateLitLength.stateLog);
2303 FSE_flushCState(&blockStream, &stateLitLength);
2304
2305 { size_t const streamSize = BIT_closeCStream(&blockStream);
2306 if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
2307 return streamSize;
2308 }
2309 }
2310
2311 static size_t
2312 ZSTD_encodeSequences_default(
2313 void* dst, size_t dstCapacity,
2314 FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2315 FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2316 FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2317 seqDef const* sequences, size_t nbSeq, int longOffsets)
2318 {
2319 return ZSTD_encodeSequences_body(dst, dstCapacity,
2320 CTable_MatchLength, mlCodeTable,
2321 CTable_OffsetBits, ofCodeTable,
2322 CTable_LitLength, llCodeTable,
2323 sequences, nbSeq, longOffsets);
2324 }
2325
2326
2327 #if DYNAMIC_BMI2
2328
2329 static TARGET_ATTRIBUTE("bmi2") size_t
2330 ZSTD_encodeSequences_bmi2(
2331 void* dst, size_t dstCapacity,
2332 FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2333 FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2334 FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2335 seqDef const* sequences, size_t nbSeq, int longOffsets)
2336 {
2337 return ZSTD_encodeSequences_body(dst, dstCapacity,
2338 CTable_MatchLength, mlCodeTable,
2339 CTable_OffsetBits, ofCodeTable,
2340 CTable_LitLength, llCodeTable,
2341 sequences, nbSeq, longOffsets);
2342 }
2343
2344 #endif
2345
2346 static size_t ZSTD_encodeSequences(
2347 void* dst, size_t dstCapacity,
2348 FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2349 FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2350 FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2351 seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
2352 {
2353 DEBUGLOG(5, "ZSTD_encodeSequences: dstCapacity = %u", (unsigned)dstCapacity);
2354 #if DYNAMIC_BMI2
2355 if (bmi2) {
2356 return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
2357 CTable_MatchLength, mlCodeTable,
2358 CTable_OffsetBits, ofCodeTable,
2359 CTable_LitLength, llCodeTable,
2360 sequences, nbSeq, longOffsets);
2361 }
2362 #endif
2363 (void)bmi2;
2364 return ZSTD_encodeSequences_default(dst, dstCapacity,
2365 CTable_MatchLength, mlCodeTable,
2366 CTable_OffsetBits, ofCodeTable,
2367 CTable_LitLength, llCodeTable,
2368 sequences, nbSeq, longOffsets);
2369 } 1931 }
2370 1932
2371 /* ZSTD_compressSequences_internal(): 1933 /* ZSTD_compressSequences_internal():
2372 * actually compresses both literals and sequences */ 1934 * actually compresses both literals and sequences */
2373 MEM_STATIC size_t 1935 MEM_STATIC size_t
2391 const BYTE* const llCodeTable = seqStorePtr->llCode; 1953 const BYTE* const llCodeTable = seqStorePtr->llCode;
2392 const BYTE* const mlCodeTable = seqStorePtr->mlCode; 1954 const BYTE* const mlCodeTable = seqStorePtr->mlCode;
2393 BYTE* const ostart = (BYTE*)dst; 1955 BYTE* const ostart = (BYTE*)dst;
2394 BYTE* const oend = ostart + dstCapacity; 1956 BYTE* const oend = ostart + dstCapacity;
2395 BYTE* op = ostart; 1957 BYTE* op = ostart;
2396 size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; 1958 size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
2397 BYTE* seqHead; 1959 BYTE* seqHead;
2398 BYTE* lastNCount = NULL; 1960 BYTE* lastNCount = NULL;
2399 1961
1962 DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq);
2400 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog))); 1963 ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
2401 DEBUGLOG(5, "ZSTD_compressSequences_internal");
2402 1964
2403 /* Compress literals */ 1965 /* Compress literals */
2404 { const BYTE* const literals = seqStorePtr->litStart; 1966 { const BYTE* const literals = seqStorePtr->litStart;
2405 size_t const litSize = seqStorePtr->lit - literals; 1967 size_t const litSize = (size_t)(seqStorePtr->lit - literals);
2406 int const disableLiteralCompression = (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
2407 size_t const cSize = ZSTD_compressLiterals( 1968 size_t const cSize = ZSTD_compressLiterals(
2408 &prevEntropy->huf, &nextEntropy->huf, 1969 &prevEntropy->huf, &nextEntropy->huf,
2409 cctxParams->cParams.strategy, disableLiteralCompression, 1970 cctxParams->cParams.strategy,
1971 ZSTD_disableLiteralsCompression(cctxParams),
2410 op, dstCapacity, 1972 op, dstCapacity,
2411 literals, litSize, 1973 literals, litSize,
2412 workspace, wkspSize, 1974 workspace, wkspSize,
2413 bmi2); 1975 bmi2);
2414 if (ZSTD_isError(cSize)) 1976 FORWARD_IF_ERROR(cSize);
2415 return cSize;
2416 assert(cSize <= dstCapacity); 1977 assert(cSize <= dstCapacity);
2417 op += cSize; 1978 op += cSize;
2418 } 1979 }
2419 1980
2420 /* Sequences Header */ 1981 /* Sequences Header */
2421 if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/) return ERROR(dstSize_tooSmall); 1982 RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
1983 dstSize_tooSmall);
2422 if (nbSeq < 0x7F) 1984 if (nbSeq < 0x7F)
2423 *op++ = (BYTE)nbSeq; 1985 *op++ = (BYTE)nbSeq;
2424 else if (nbSeq < LONGNBSEQ) 1986 else if (nbSeq < LONGNBSEQ)
2425 op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2; 1987 op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
2426 else 1988 else
2427 op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3; 1989 op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1990 assert(op <= oend);
2428 if (nbSeq==0) { 1991 if (nbSeq==0) {
2429 /* Copy the old tables over as if we repeated them */ 1992 /* Copy the old tables over as if we repeated them */
2430 memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); 1993 memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
2431 return op - ostart; 1994 return (size_t)(op - ostart);
2432 } 1995 }
2433 1996
2434 /* seqHead : flags for FSE encoding type */ 1997 /* seqHead : flags for FSE encoding type */
2435 seqHead = op++; 1998 seqHead = op++;
1999 assert(op <= oend);
2436 2000
2437 /* convert length/distances into codes */ 2001 /* convert length/distances into codes */
2438 ZSTD_seqToCodes(seqStorePtr); 2002 ZSTD_seqToCodes(seqStorePtr);
2439 /* build CTable for Literal Lengths */ 2003 /* build CTable for Literal Lengths */
2440 { unsigned max = MaxLL; 2004 { unsigned max = MaxLL;
2446 LLFSELog, prevEntropy->fse.litlengthCTable, 2010 LLFSELog, prevEntropy->fse.litlengthCTable,
2447 LL_defaultNorm, LL_defaultNormLog, 2011 LL_defaultNorm, LL_defaultNormLog,
2448 ZSTD_defaultAllowed, strategy); 2012 ZSTD_defaultAllowed, strategy);
2449 assert(set_basic < set_compressed && set_rle < set_compressed); 2013 assert(set_basic < set_compressed && set_rle < set_compressed);
2450 assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ 2014 assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2451 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype, 2015 { size_t const countSize = ZSTD_buildCTable(op, (size_t)(oend - op), CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
2452 count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL, 2016 count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
2453 prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable), 2017 prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
2454 workspace, wkspSize); 2018 workspace, wkspSize);
2455 if (ZSTD_isError(countSize)) return countSize; 2019 FORWARD_IF_ERROR(countSize);
2456 if (LLtype == set_compressed) 2020 if (LLtype == set_compressed)
2457 lastNCount = op; 2021 lastNCount = op;
2458 op += countSize; 2022 op += countSize;
2023 assert(op <= oend);
2459 } } 2024 } }
2460 /* build CTable for Offsets */ 2025 /* build CTable for Offsets */
2461 { unsigned max = MaxOff; 2026 { unsigned max = MaxOff;
2462 size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ 2027 size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
2463 /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ 2028 /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
2468 count, max, mostFrequent, nbSeq, 2033 count, max, mostFrequent, nbSeq,
2469 OffFSELog, prevEntropy->fse.offcodeCTable, 2034 OffFSELog, prevEntropy->fse.offcodeCTable,
2470 OF_defaultNorm, OF_defaultNormLog, 2035 OF_defaultNorm, OF_defaultNormLog,
2471 defaultPolicy, strategy); 2036 defaultPolicy, strategy);
2472 assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ 2037 assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2473 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype, 2038 { size_t const countSize = ZSTD_buildCTable(op, (size_t)(oend - op), CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
2474 count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, 2039 count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
2475 prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable), 2040 prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
2476 workspace, wkspSize); 2041 workspace, wkspSize);
2477 if (ZSTD_isError(countSize)) return countSize; 2042 FORWARD_IF_ERROR(countSize);
2478 if (Offtype == set_compressed) 2043 if (Offtype == set_compressed)
2479 lastNCount = op; 2044 lastNCount = op;
2480 op += countSize; 2045 op += countSize;
2046 assert(op <= oend);
2481 } } 2047 } }
2482 /* build CTable for MatchLengths */ 2048 /* build CTable for MatchLengths */
2483 { unsigned max = MaxML; 2049 { unsigned max = MaxML;
2484 size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ 2050 size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
2485 DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op)); 2051 DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
2488 count, max, mostFrequent, nbSeq, 2054 count, max, mostFrequent, nbSeq,
2489 MLFSELog, prevEntropy->fse.matchlengthCTable, 2055 MLFSELog, prevEntropy->fse.matchlengthCTable,
2490 ML_defaultNorm, ML_defaultNormLog, 2056 ML_defaultNorm, ML_defaultNormLog,
2491 ZSTD_defaultAllowed, strategy); 2057 ZSTD_defaultAllowed, strategy);
2492 assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ 2058 assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2493 { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype, 2059 { size_t const countSize = ZSTD_buildCTable(op, (size_t)(oend - op), CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
2494 count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML, 2060 count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
2495 prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable), 2061 prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
2496 workspace, wkspSize); 2062 workspace, wkspSize);
2497 if (ZSTD_isError(countSize)) return countSize; 2063 FORWARD_IF_ERROR(countSize);
2498 if (MLtype == set_compressed) 2064 if (MLtype == set_compressed)
2499 lastNCount = op; 2065 lastNCount = op;
2500 op += countSize; 2066 op += countSize;
2067 assert(op <= oend);
2501 } } 2068 } }
2502 2069
2503 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); 2070 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
2504 2071
2505 { size_t const bitstreamSize = ZSTD_encodeSequences( 2072 { size_t const bitstreamSize = ZSTD_encodeSequences(
2506 op, oend - op, 2073 op, (size_t)(oend - op),
2507 CTable_MatchLength, mlCodeTable, 2074 CTable_MatchLength, mlCodeTable,
2508 CTable_OffsetBits, ofCodeTable, 2075 CTable_OffsetBits, ofCodeTable,
2509 CTable_LitLength, llCodeTable, 2076 CTable_LitLength, llCodeTable,
2510 sequences, nbSeq, 2077 sequences, nbSeq,
2511 longOffsets, bmi2); 2078 longOffsets, bmi2);
2512 if (ZSTD_isError(bitstreamSize)) return bitstreamSize; 2079 FORWARD_IF_ERROR(bitstreamSize);
2513 op += bitstreamSize; 2080 op += bitstreamSize;
2081 assert(op <= oend);
2514 /* zstd versions <= 1.3.4 mistakenly report corruption when 2082 /* zstd versions <= 1.3.4 mistakenly report corruption when
2515 * FSE_readNCount() recieves a buffer < 4 bytes. 2083 * FSE_readNCount() receives a buffer < 4 bytes.
2516 * Fixed by https://github.com/facebook/zstd/pull/1146. 2084 * Fixed by https://github.com/facebook/zstd/pull/1146.
2517 * This can happen when the last set_compressed table present is 2 2085 * This can happen when the last set_compressed table present is 2
2518 * bytes and the bitstream is only one byte. 2086 * bytes and the bitstream is only one byte.
2519 * In this exceedingly rare case, we will simply emit an uncompressed 2087 * In this exceedingly rare case, we will simply emit an uncompressed
2520 * block, since it isn't worth optimizing. 2088 * block, since it isn't worth optimizing.
2527 return 0; 2095 return 0;
2528 } 2096 }
2529 } 2097 }
2530 2098
2531 DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart)); 2099 DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
2532 return op - ostart; 2100 return (size_t)(op - ostart);
2533 } 2101 }
2534 2102
2535 MEM_STATIC size_t 2103 MEM_STATIC size_t
2536 ZSTD_compressSequences(seqStore_t* seqStorePtr, 2104 ZSTD_compressSequences(seqStore_t* seqStorePtr,
2537 const ZSTD_entropyCTables_t* prevEntropy, 2105 const ZSTD_entropyCTables_t* prevEntropy,
2550 /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block. 2118 /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
2551 * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block. 2119 * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
2552 */ 2120 */
2553 if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) 2121 if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
2554 return 0; /* block not compressed */ 2122 return 0; /* block not compressed */
2555 if (ZSTD_isError(cSize)) return cSize; 2123 FORWARD_IF_ERROR(cSize);
2556 2124
2557 /* Check compressibility */ 2125 /* Check compressibility */
2558 { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); 2126 { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
2559 if (cSize >= maxCSize) return 0; /* block not compressed */ 2127 if (cSize >= maxCSize) return 0; /* block not compressed */
2560 } 2128 }
2620 ssPtr->lit = ssPtr->litStart; 2188 ssPtr->lit = ssPtr->litStart;
2621 ssPtr->sequences = ssPtr->sequencesStart; 2189 ssPtr->sequences = ssPtr->sequencesStart;
2622 ssPtr->longLengthID = 0; 2190 ssPtr->longLengthID = 0;
2623 } 2191 }
2624 2192
2625 static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, 2193 typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
2626 void* dst, size_t dstCapacity, 2194
2627 const void* src, size_t srcSize) 2195 static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
2628 { 2196 {
2629 ZSTD_matchState_t* const ms = &zc->blockState.matchState; 2197 ZSTD_matchState_t* const ms = &zc->blockState.matchState;
2630 size_t cSize; 2198 DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
2631 DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
2632 (unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate);
2633 assert(srcSize <= ZSTD_BLOCKSIZE_MAX); 2199 assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
2634
2635 /* Assert that we have correctly flushed the ctx params into the ms's copy */ 2200 /* Assert that we have correctly flushed the ctx params into the ms's copy */
2636 ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams); 2201 ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
2637
2638 if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) { 2202 if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
2639 ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); 2203 ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
2640 cSize = 0; 2204 return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
2641 goto out; /* don't even attempt compression below a certain srcSize */
2642 } 2205 }
2643 ZSTD_resetSeqStore(&(zc->seqStore)); 2206 ZSTD_resetSeqStore(&(zc->seqStore));
2644 ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* required for optimal parser to read stats from dictionary */ 2207 /* required for optimal parser to read stats from dictionary */
2645 2208 ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
2209 /* tell the optimal parser how we expect to compress literals */
2210 ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
2646 /* a gap between an attached dict and the current window is not safe, 2211 /* a gap between an attached dict and the current window is not safe,
2647 * they must remain adjacent, 2212 * they must remain adjacent,
2648 * and when that stops being the case, the dict must be unset */ 2213 * and when that stops being the case, the dict must be unset */
2649 assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit); 2214 assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);
2650 2215
2677 rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0}; 2242 rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
2678 2243
2679 ldmSeqStore.seq = zc->ldmSequences; 2244 ldmSeqStore.seq = zc->ldmSequences;
2680 ldmSeqStore.capacity = zc->maxNbLdmSequences; 2245 ldmSeqStore.capacity = zc->maxNbLdmSequences;
2681 /* Updates ldmSeqStore.size */ 2246 /* Updates ldmSeqStore.size */
2682 CHECK_F(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore, 2247 FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
2683 &zc->appliedParams.ldmParams, 2248 &zc->appliedParams.ldmParams,
2684 src, srcSize)); 2249 src, srcSize));
2685 /* Updates ldmSeqStore.pos */ 2250 /* Updates ldmSeqStore.pos */
2686 lastLLSize = 2251 lastLLSize =
2687 ZSTD_ldm_blockCompress(&ldmSeqStore, 2252 ZSTD_ldm_blockCompress(&ldmSeqStore,
2694 lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize); 2259 lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
2695 } 2260 }
2696 { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; 2261 { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
2697 ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize); 2262 ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
2698 } } 2263 } }
2264 return ZSTDbss_compress;
2265 }
2266
2267 static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2268 void* dst, size_t dstCapacity,
2269 const void* src, size_t srcSize)
2270 {
2271 size_t cSize;
2272 DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
2273 (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
2274 (unsigned)zc->blockState.matchState.nextToUpdate);
2275
2276 { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
2277 FORWARD_IF_ERROR(bss);
2278 if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
2279 }
2699 2280
2700 /* encode sequences and literals */ 2281 /* encode sequences and literals */
2701 cSize = ZSTD_compressSequences(&zc->seqStore, 2282 cSize = ZSTD_compressSequences(&zc->seqStore,
2702 &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, 2283 &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
2703 &zc->appliedParams, 2284 &zc->appliedParams,
2719 */ 2300 */
2720 if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) 2301 if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
2721 zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; 2302 zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
2722 2303
2723 return cSize; 2304 return cSize;
2305 }
2306
2307
2308 static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, void const* ip, void const* iend)
2309 {
2310 if (ZSTD_window_needOverflowCorrection(ms->window, iend)) {
2311 U32 const maxDist = (U32)1 << params->cParams.windowLog;
2312 U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
2313 U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
2314 ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2315 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2316 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2317 ZSTD_reduceIndex(ms, params, correction);
2318 if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2319 else ms->nextToUpdate -= correction;
2320 /* invalidate dictionaries on overflow correction */
2321 ms->loadedDictEnd = 0;
2322 ms->dictMatchState = NULL;
2323 }
2724 } 2324 }
2725 2325
2726 2326
2727 /*! ZSTD_compress_frameChunk() : 2327 /*! ZSTD_compress_frameChunk() :
2728 * Compress a chunk of data into one or multiple blocks. 2328 * Compress a chunk of data into one or multiple blocks.
2740 size_t remaining = srcSize; 2340 size_t remaining = srcSize;
2741 const BYTE* ip = (const BYTE*)src; 2341 const BYTE* ip = (const BYTE*)src;
2742 BYTE* const ostart = (BYTE*)dst; 2342 BYTE* const ostart = (BYTE*)dst;
2743 BYTE* op = ostart; 2343 BYTE* op = ostart;
2744 U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; 2344 U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
2745 assert(cctx->appliedParams.cParams.windowLog <= 31); 2345 assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
2746 2346
2747 DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); 2347 DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
2748 if (cctx->appliedParams.fParams.checksumFlag && srcSize) 2348 if (cctx->appliedParams.fParams.checksumFlag && srcSize)
2749 XXH64_update(&cctx->xxhState, src, srcSize); 2349 XXH64_update(&cctx->xxhState, src, srcSize);
2750 2350
2751 while (remaining) { 2351 while (remaining) {
2752 ZSTD_matchState_t* const ms = &cctx->blockState.matchState; 2352 ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
2753 U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); 2353 U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
2754 2354
2755 if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) 2355 RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
2756 return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */ 2356 dstSize_tooSmall,
2357 "not enough space to store compressed block");
2757 if (remaining < blockSize) blockSize = remaining; 2358 if (remaining < blockSize) blockSize = remaining;
2758 2359
2759 if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) { 2360 ZSTD_overflowCorrectIfNeeded(ms, &cctx->appliedParams, ip, ip + blockSize);
2760 U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy); 2361 ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2761 U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); 2362
2762 ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); 2363 /* Ensure hash/chain table insertion resumes no sooner than lowlimit */
2763 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2764 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2765 ZSTD_reduceIndex(cctx, correction);
2766 if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2767 else ms->nextToUpdate -= correction;
2768 ms->loadedDictEnd = 0;
2769 ms->dictMatchState = NULL;
2770 }
2771 ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2772 if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; 2364 if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
2773 2365
2774 { size_t cSize = ZSTD_compressBlock_internal(cctx, 2366 { size_t cSize = ZSTD_compressBlock_internal(cctx,
2775 op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, 2367 op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
2776 ip, blockSize); 2368 ip, blockSize);
2777 if (ZSTD_isError(cSize)) return cSize; 2369 FORWARD_IF_ERROR(cSize);
2778 2370
2779 if (cSize == 0) { /* block is not compressible */ 2371 if (cSize == 0) { /* block is not compressible */
2780 cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); 2372 cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
2781 if (ZSTD_isError(cSize)) return cSize; 2373 FORWARD_IF_ERROR(cSize);
2782 } else { 2374 } else {
2783 U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); 2375 U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
2784 MEM_writeLE24(op, cBlockHeader24); 2376 MEM_writeLE24(op, cBlockHeader24);
2785 cSize += ZSTD_blockHeaderSize; 2377 cSize += ZSTD_blockHeaderSize;
2786 } 2378 }
2794 DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u", 2386 DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
2795 (unsigned)cSize); 2387 (unsigned)cSize);
2796 } } 2388 } }
2797 2389
2798 if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending; 2390 if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
2799 return op-ostart; 2391 return (size_t)(op-ostart);
2800 } 2392 }
2801 2393
2802 2394
2803 static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, 2395 static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2804 ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID) 2396 ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
2809 U32 const windowSize = (U32)1 << params.cParams.windowLog; 2401 U32 const windowSize = (U32)1 << params.cParams.windowLog;
2810 U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); 2402 U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
2811 BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); 2403 BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2812 U32 const fcsCode = params.fParams.contentSizeFlag ? 2404 U32 const fcsCode = params.fParams.contentSizeFlag ?
2813 (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */ 2405 (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
2814 BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); 2406 BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2815 size_t pos=0; 2407 size_t pos=0;
2816 2408
2817 assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)); 2409 assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
2818 if (dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX) return ERROR(dstSize_tooSmall); 2410 RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall);
2819 DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", 2411 DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2820 !params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode); 2412 !params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
2821 2413
2822 if (params.format == ZSTD_f_zstd1) { 2414 if (params.format == ZSTD_f_zstd1) {
2823 MEM_writeLE32(dst, ZSTD_MAGICNUMBER); 2415 MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2824 pos = 4; 2416 pos = 4;
2825 } 2417 }
2826 op[pos++] = frameHeaderDecriptionByte; 2418 op[pos++] = frameHeaderDescriptionByte;
2827 if (!singleSegment) op[pos++] = windowLogByte; 2419 if (!singleSegment) op[pos++] = windowLogByte;
2828 switch(dictIDSizeCode) 2420 switch(dictIDSizeCode)
2829 { 2421 {
2830 default: assert(0); /* impossible */ 2422 default: assert(0); /* impossible */
2831 case 0 : break; 2423 case 0 : break;
2845 } 2437 }
2846 2438
2847 /* ZSTD_writeLastEmptyBlock() : 2439 /* ZSTD_writeLastEmptyBlock() :
2848 * output an empty Block with end-of-frame mark to complete a frame 2440 * output an empty Block with end-of-frame mark to complete a frame
2849 * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h)) 2441 * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
2850 * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize) 2442 * or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
2851 */ 2443 */
2852 size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity) 2444 size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
2853 { 2445 {
2854 if (dstCapacity < ZSTD_blockHeaderSize) return ERROR(dstSize_tooSmall); 2446 RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall);
2855 { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */ 2447 { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
2856 MEM_writeLE24(dst, cBlockHeader24); 2448 MEM_writeLE24(dst, cBlockHeader24);
2857 return ZSTD_blockHeaderSize; 2449 return ZSTD_blockHeaderSize;
2858 } 2450 }
2859 } 2451 }
2860 2452
2861 size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq) 2453 size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
2862 { 2454 {
2863 if (cctx->stage != ZSTDcs_init) 2455 RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong);
2864 return ERROR(stage_wrong); 2456 RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
2865 if (cctx->appliedParams.ldmParams.enableLdm) 2457 parameter_unsupported);
2866 return ERROR(parameter_unsupported);
2867 cctx->externSeqStore.seq = seq; 2458 cctx->externSeqStore.seq = seq;
2868 cctx->externSeqStore.size = nbSeq; 2459 cctx->externSeqStore.size = nbSeq;
2869 cctx->externSeqStore.capacity = nbSeq; 2460 cctx->externSeqStore.capacity = nbSeq;
2870 cctx->externSeqStore.pos = 0; 2461 cctx->externSeqStore.pos = 0;
2871 return 0; 2462 return 0;
2880 ZSTD_matchState_t* const ms = &cctx->blockState.matchState; 2471 ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
2881 size_t fhSize = 0; 2472 size_t fhSize = 0;
2882 2473
2883 DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u", 2474 DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
2884 cctx->stage, (unsigned)srcSize); 2475 cctx->stage, (unsigned)srcSize);
2885 if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */ 2476 RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
2477 "missing init (ZSTD_compressBegin)");
2886 2478
2887 if (frame && (cctx->stage==ZSTDcs_init)) { 2479 if (frame && (cctx->stage==ZSTDcs_init)) {
2888 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 2480 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
2889 cctx->pledgedSrcSizePlusOne-1, cctx->dictID); 2481 cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
2890 if (ZSTD_isError(fhSize)) return fhSize; 2482 FORWARD_IF_ERROR(fhSize);
2483 assert(fhSize <= dstCapacity);
2891 dstCapacity -= fhSize; 2484 dstCapacity -= fhSize;
2892 dst = (char*)dst + fhSize; 2485 dst = (char*)dst + fhSize;
2893 cctx->stage = ZSTDcs_ongoing; 2486 cctx->stage = ZSTDcs_ongoing;
2894 } 2487 }
2895 2488
2902 ZSTD_window_update(&cctx->ldmState.window, src, srcSize); 2495 ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
2903 } 2496 }
2904 2497
2905 if (!frame) { 2498 if (!frame) {
2906 /* overflow check and correction for block mode */ 2499 /* overflow check and correction for block mode */
2907 if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) { 2500 ZSTD_overflowCorrectIfNeeded(ms, &cctx->appliedParams, src, (BYTE const*)src + srcSize);
2908 U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2909 U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src);
2910 ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2911 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2912 ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2913 ZSTD_reduceIndex(cctx, correction);
2914 if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2915 else ms->nextToUpdate -= correction;
2916 ms->loadedDictEnd = 0;
2917 ms->dictMatchState = NULL;
2918 }
2919 } 2501 }
2920 2502
2921 DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize); 2503 DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
2922 { size_t const cSize = frame ? 2504 { size_t const cSize = frame ?
2923 ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : 2505 ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
2924 ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize); 2506 ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
2925 if (ZSTD_isError(cSize)) return cSize; 2507 FORWARD_IF_ERROR(cSize);
2926 cctx->consumedSrcSize += srcSize; 2508 cctx->consumedSrcSize += srcSize;
2927 cctx->producedCSize += (cSize + fhSize); 2509 cctx->producedCSize += (cSize + fhSize);
2928 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); 2510 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
2929 if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ 2511 if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
2930 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); 2512 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
2931 if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) { 2513 RETURN_ERROR_IF(
2932 DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u", 2514 cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
2933 (unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize); 2515 srcSize_wrong,
2934 return ERROR(srcSize_wrong); 2516 "error : pledgedSrcSize = %u, while realSrcSize >= %u",
2935 } 2517 (unsigned)cctx->pledgedSrcSizePlusOne-1,
2518 (unsigned)cctx->consumedSrcSize);
2936 } 2519 }
2937 return cSize + fhSize; 2520 return cSize + fhSize;
2938 } 2521 }
2939 } 2522 }
2940 2523
2954 return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog); 2537 return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
2955 } 2538 }
2956 2539
2957 size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) 2540 size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2958 { 2541 {
2959 size_t const blockSizeMax = ZSTD_getBlockSize(cctx); 2542 DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize);
2960 if (srcSize > blockSizeMax) return ERROR(srcSize_wrong); 2543 { size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
2544 RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong); }
2961 2545
2962 return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */); 2546 return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
2963 } 2547 }
2964 2548
2965 /*! ZSTD_loadDictionaryContent() : 2549 /*! ZSTD_loadDictionaryContent() :
2968 static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, 2552 static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
2969 ZSTD_CCtx_params const* params, 2553 ZSTD_CCtx_params const* params,
2970 const void* src, size_t srcSize, 2554 const void* src, size_t srcSize,
2971 ZSTD_dictTableLoadMethod_e dtlm) 2555 ZSTD_dictTableLoadMethod_e dtlm)
2972 { 2556 {
2973 const BYTE* const ip = (const BYTE*) src; 2557 const BYTE* ip = (const BYTE*) src;
2974 const BYTE* const iend = ip + srcSize; 2558 const BYTE* const iend = ip + srcSize;
2975 2559
2976 ZSTD_window_update(&ms->window, src, srcSize); 2560 ZSTD_window_update(&ms->window, src, srcSize);
2977 ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base); 2561 ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
2978 2562
2979 /* Assert that we the ms params match the params we're being given */ 2563 /* Assert that we the ms params match the params we're being given */
2980 ZSTD_assertEqualCParams(params->cParams, ms->cParams); 2564 ZSTD_assertEqualCParams(params->cParams, ms->cParams);
2981 2565
2982 if (srcSize <= HASH_READ_SIZE) return 0; 2566 if (srcSize <= HASH_READ_SIZE) return 0;
2983 2567
2984 switch(params->cParams.strategy) 2568 while (iend - ip > HASH_READ_SIZE) {
2985 { 2569 size_t const remaining = (size_t)(iend - ip);
2986 case ZSTD_fast: 2570 size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX);
2987 ZSTD_fillHashTable(ms, iend, dtlm); 2571 const BYTE* const ichunk = ip + chunk;
2988 break; 2572
2989 case ZSTD_dfast: 2573 ZSTD_overflowCorrectIfNeeded(ms, params, ip, ichunk);
2990 ZSTD_fillDoubleHashTable(ms, iend, dtlm); 2574
2991 break; 2575 switch(params->cParams.strategy)
2992 2576 {
2993 case ZSTD_greedy: 2577 case ZSTD_fast:
2994 case ZSTD_lazy: 2578 ZSTD_fillHashTable(ms, ichunk, dtlm);
2995 case ZSTD_lazy2: 2579 break;
2996 if (srcSize >= HASH_READ_SIZE) 2580 case ZSTD_dfast:
2997 ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE); 2581 ZSTD_fillDoubleHashTable(ms, ichunk, dtlm);
2998 break; 2582 break;
2999 2583
3000 case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ 2584 case ZSTD_greedy:
3001 case ZSTD_btopt: 2585 case ZSTD_lazy:
3002 case ZSTD_btultra: 2586 case ZSTD_lazy2:
3003 case ZSTD_btultra2: 2587 if (chunk >= HASH_READ_SIZE)
3004 if (srcSize >= HASH_READ_SIZE) 2588 ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
3005 ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend); 2589 break;
3006 break; 2590
3007 2591 case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
3008 default: 2592 case ZSTD_btopt:
3009 assert(0); /* not possible : not a valid strategy id */ 2593 case ZSTD_btultra:
2594 case ZSTD_btultra2:
2595 if (chunk >= HASH_READ_SIZE)
2596 ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk);
2597 break;
2598
2599 default:
2600 assert(0); /* not possible : not a valid strategy id */
2601 }
2602
2603 ip = ichunk;
3010 } 2604 }
3011 2605
3012 ms->nextToUpdate = (U32)(iend - ms->window.base); 2606 ms->nextToUpdate = (U32)(iend - ms->window.base);
3013 return 0; 2607 return 0;
3014 } 2608 }
3018 when FSE encoding. Refuse dictionaries that assign zero probability to symbols 2612 when FSE encoding. Refuse dictionaries that assign zero probability to symbols
3019 that we may encounter during compression. 2613 that we may encounter during compression.
3020 NOTE: This behavior is not standard and could be improved in the future. */ 2614 NOTE: This behavior is not standard and could be improved in the future. */
3021 static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) { 2615 static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
3022 U32 s; 2616 U32 s;
3023 if (dictMaxSymbolValue < maxSymbolValue) return ERROR(dictionary_corrupted); 2617 RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted);
3024 for (s = 0; s <= maxSymbolValue; ++s) { 2618 for (s = 0; s <= maxSymbolValue; ++s) {
3025 if (normalizedCounter[s] == 0) return ERROR(dictionary_corrupted); 2619 RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted);
3026 } 2620 }
3027 return 0; 2621 return 0;
3028 } 2622 }
3029 2623
3030 2624
3058 dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr); 2652 dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
3059 dictPtr += 4; 2653 dictPtr += 4;
3060 2654
3061 { unsigned maxSymbolValue = 255; 2655 { unsigned maxSymbolValue = 255;
3062 size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); 2656 size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
3063 if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted); 2657 RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted);
3064 if (maxSymbolValue < 255) return ERROR(dictionary_corrupted); 2658 RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted);
3065 dictPtr += hufHeaderSize; 2659 dictPtr += hufHeaderSize;
3066 } 2660 }
3067 2661
3068 { unsigned offcodeLog; 2662 { unsigned offcodeLog;
3069 size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); 2663 size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
3070 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted); 2664 RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
3071 if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted); 2665 RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
3072 /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ 2666 /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
3073 /* fill all offset symbols to avoid garbage at end of table */ 2667 /* fill all offset symbols to avoid garbage at end of table */
3074 CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.offcodeCTable, 2668 RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3075 offcodeNCount, MaxOff, offcodeLog, 2669 bs->entropy.fse.offcodeCTable,
3076 workspace, HUF_WORKSPACE_SIZE), 2670 offcodeNCount, MaxOff, offcodeLog,
3077 dictionary_corrupted); 2671 workspace, HUF_WORKSPACE_SIZE)),
2672 dictionary_corrupted);
3078 dictPtr += offcodeHeaderSize; 2673 dictPtr += offcodeHeaderSize;
3079 } 2674 }
3080 2675
3081 { short matchlengthNCount[MaxML+1]; 2676 { short matchlengthNCount[MaxML+1];
3082 unsigned matchlengthMaxValue = MaxML, matchlengthLog; 2677 unsigned matchlengthMaxValue = MaxML, matchlengthLog;
3083 size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); 2678 size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
3084 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted); 2679 RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
3085 if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted); 2680 RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
3086 /* Every match length code must have non-zero probability */ 2681 /* Every match length code must have non-zero probability */
3087 CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML)); 2682 FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
3088 CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.matchlengthCTable, 2683 RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3089 matchlengthNCount, matchlengthMaxValue, matchlengthLog, 2684 bs->entropy.fse.matchlengthCTable,
3090 workspace, HUF_WORKSPACE_SIZE), 2685 matchlengthNCount, matchlengthMaxValue, matchlengthLog,
3091 dictionary_corrupted); 2686 workspace, HUF_WORKSPACE_SIZE)),
2687 dictionary_corrupted);
3092 dictPtr += matchlengthHeaderSize; 2688 dictPtr += matchlengthHeaderSize;
3093 } 2689 }
3094 2690
3095 { short litlengthNCount[MaxLL+1]; 2691 { short litlengthNCount[MaxLL+1];
3096 unsigned litlengthMaxValue = MaxLL, litlengthLog; 2692 unsigned litlengthMaxValue = MaxLL, litlengthLog;
3097 size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); 2693 size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
3098 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted); 2694 RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
3099 if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted); 2695 RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
3100 /* Every literal length code must have non-zero probability */ 2696 /* Every literal length code must have non-zero probability */
3101 CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL)); 2697 FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
3102 CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.litlengthCTable, 2698 RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3103 litlengthNCount, litlengthMaxValue, litlengthLog, 2699 bs->entropy.fse.litlengthCTable,
3104 workspace, HUF_WORKSPACE_SIZE), 2700 litlengthNCount, litlengthMaxValue, litlengthLog,
3105 dictionary_corrupted); 2701 workspace, HUF_WORKSPACE_SIZE)),
2702 dictionary_corrupted);
3106 dictPtr += litlengthHeaderSize; 2703 dictPtr += litlengthHeaderSize;
3107 } 2704 }
3108 2705
3109 if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted); 2706 RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
3110 bs->rep[0] = MEM_readLE32(dictPtr+0); 2707 bs->rep[0] = MEM_readLE32(dictPtr+0);
3111 bs->rep[1] = MEM_readLE32(dictPtr+4); 2708 bs->rep[1] = MEM_readLE32(dictPtr+4);
3112 bs->rep[2] = MEM_readLE32(dictPtr+8); 2709 bs->rep[2] = MEM_readLE32(dictPtr+8);
3113 dictPtr += 12; 2710 dictPtr += 12;
3114 2711
3117 if (dictContentSize <= ((U32)-1) - 128 KB) { 2714 if (dictContentSize <= ((U32)-1) - 128 KB) {
3118 U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ 2715 U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
3119 offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ 2716 offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
3120 } 2717 }
3121 /* All offset values <= dictContentSize + 128 KB must be representable */ 2718 /* All offset values <= dictContentSize + 128 KB must be representable */
3122 CHECK_F (ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff))); 2719 FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
3123 /* All repCodes must be <= dictContentSize and != 0*/ 2720 /* All repCodes must be <= dictContentSize and != 0*/
3124 { U32 u; 2721 { U32 u;
3125 for (u=0; u<3; u++) { 2722 for (u=0; u<3; u++) {
3126 if (bs->rep[u] == 0) return ERROR(dictionary_corrupted); 2723 RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted);
3127 if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted); 2724 RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted);
3128 } } 2725 } }
3129 2726
3130 bs->entropy.huf.repeatMode = HUF_repeat_valid; 2727 bs->entropy.huf.repeatMode = HUF_repeat_valid;
3131 bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid; 2728 bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
3132 bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; 2729 bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
3133 bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; 2730 bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
3134 CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm)); 2731 FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
3135 return dictID; 2732 return dictID;
3136 } 2733 }
3137 } 2734 }
3138 2735
3139 /** ZSTD_compress_insertDictionary() : 2736 /** ZSTD_compress_insertDictionary() :
3159 if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) { 2756 if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
3160 if (dictContentType == ZSTD_dct_auto) { 2757 if (dictContentType == ZSTD_dct_auto) {
3161 DEBUGLOG(4, "raw content dictionary detected"); 2758 DEBUGLOG(4, "raw content dictionary detected");
3162 return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm); 2759 return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
3163 } 2760 }
3164 if (dictContentType == ZSTD_dct_fullDict) 2761 RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong);
3165 return ERROR(dictionary_wrong);
3166 assert(0); /* impossible */ 2762 assert(0); /* impossible */
3167 } 2763 }
3168 2764
3169 /* dict as full zstd dictionary */ 2765 /* dict as full zstd dictionary */
3170 return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, dtlm, workspace); 2766 return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, dtlm, workspace);
3187 2783
3188 if (cdict && cdict->dictContentSize>0) { 2784 if (cdict && cdict->dictContentSize>0) {
3189 return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff); 2785 return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
3190 } 2786 }
3191 2787
3192 CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, 2788 FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
3193 ZSTDcrp_continue, zbuff) ); 2789 ZSTDcrp_continue, zbuff) );
3194 { 2790 { size_t const dictID = ZSTD_compress_insertDictionary(
3195 size_t const dictID = ZSTD_compress_insertDictionary(
3196 cctx->blockState.prevCBlock, &cctx->blockState.matchState, 2791 cctx->blockState.prevCBlock, &cctx->blockState.matchState,
3197 &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace); 2792 &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
3198 if (ZSTD_isError(dictID)) return dictID; 2793 FORWARD_IF_ERROR(dictID);
3199 assert(dictID <= (size_t)(U32)-1); 2794 assert(dictID <= UINT_MAX);
3200 cctx->dictID = (U32)dictID; 2795 cctx->dictID = (U32)dictID;
3201 } 2796 }
3202 return 0; 2797 return 0;
3203 } 2798 }
3204 2799
3210 ZSTD_CCtx_params params, 2805 ZSTD_CCtx_params params,
3211 unsigned long long pledgedSrcSize) 2806 unsigned long long pledgedSrcSize)
3212 { 2807 {
3213 DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog); 2808 DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
3214 /* compression parameters verification and optimization */ 2809 /* compression parameters verification and optimization */
3215 CHECK_F( ZSTD_checkCParams(params.cParams) ); 2810 FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
3216 return ZSTD_compressBegin_internal(cctx, 2811 return ZSTD_compressBegin_internal(cctx,
3217 dict, dictSize, dictContentType, dtlm, 2812 dict, dictSize, dictContentType, dtlm,
3218 cdict, 2813 cdict,
3219 params, pledgedSrcSize, 2814 params, pledgedSrcSize,
3220 ZSTDb_not_buffered); 2815 ZSTDb_not_buffered);
3258 BYTE* const ostart = (BYTE*)dst; 2853 BYTE* const ostart = (BYTE*)dst;
3259 BYTE* op = ostart; 2854 BYTE* op = ostart;
3260 size_t fhSize = 0; 2855 size_t fhSize = 0;
3261 2856
3262 DEBUGLOG(4, "ZSTD_writeEpilogue"); 2857 DEBUGLOG(4, "ZSTD_writeEpilogue");
3263 if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */ 2858 RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
3264 2859
3265 /* special case : empty frame */ 2860 /* special case : empty frame */
3266 if (cctx->stage == ZSTDcs_init) { 2861 if (cctx->stage == ZSTDcs_init) {
3267 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0); 2862 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
3268 if (ZSTD_isError(fhSize)) return fhSize; 2863 FORWARD_IF_ERROR(fhSize);
3269 dstCapacity -= fhSize; 2864 dstCapacity -= fhSize;
3270 op += fhSize; 2865 op += fhSize;
3271 cctx->stage = ZSTDcs_ongoing; 2866 cctx->stage = ZSTDcs_ongoing;
3272 } 2867 }
3273 2868
3274 if (cctx->stage != ZSTDcs_ending) { 2869 if (cctx->stage != ZSTDcs_ending) {
3275 /* write one last empty block, make it the "last" block */ 2870 /* write one last empty block, make it the "last" block */
3276 U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0; 2871 U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
3277 if (dstCapacity<4) return ERROR(dstSize_tooSmall); 2872 RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
3278 MEM_writeLE32(op, cBlockHeader24); 2873 MEM_writeLE32(op, cBlockHeader24);
3279 op += ZSTD_blockHeaderSize; 2874 op += ZSTD_blockHeaderSize;
3280 dstCapacity -= ZSTD_blockHeaderSize; 2875 dstCapacity -= ZSTD_blockHeaderSize;
3281 } 2876 }
3282 2877
3283 if (cctx->appliedParams.fParams.checksumFlag) { 2878 if (cctx->appliedParams.fParams.checksumFlag) {
3284 U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); 2879 U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
3285 if (dstCapacity<4) return ERROR(dstSize_tooSmall); 2880 RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
3286 DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum); 2881 DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
3287 MEM_writeLE32(op, checksum); 2882 MEM_writeLE32(op, checksum);
3288 op += 4; 2883 op += 4;
3289 } 2884 }
3290 2885
3298 { 2893 {
3299 size_t endResult; 2894 size_t endResult;
3300 size_t const cSize = ZSTD_compressContinue_internal(cctx, 2895 size_t const cSize = ZSTD_compressContinue_internal(cctx,
3301 dst, dstCapacity, src, srcSize, 2896 dst, dstCapacity, src, srcSize,
3302 1 /* frame mode */, 1 /* last chunk */); 2897 1 /* frame mode */, 1 /* last chunk */);
3303 if (ZSTD_isError(cSize)) return cSize; 2898 FORWARD_IF_ERROR(cSize);
3304 endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); 2899 endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
3305 if (ZSTD_isError(endResult)) return endResult; 2900 FORWARD_IF_ERROR(endResult);
3306 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); 2901 assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
3307 if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ 2902 if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
3308 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); 2903 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
3309 DEBUGLOG(4, "end of frame : controlling src size"); 2904 DEBUGLOG(4, "end of frame : controlling src size");
3310 if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) { 2905 RETURN_ERROR_IF(
3311 DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u", 2906 cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
3312 (unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize); 2907 srcSize_wrong,
3313 return ERROR(srcSize_wrong); 2908 "error : pledgedSrcSize = %u, while realSrcSize = %u",
3314 } } 2909 (unsigned)cctx->pledgedSrcSizePlusOne-1,
2910 (unsigned)cctx->consumedSrcSize);
2911 }
3315 return cSize + endResult; 2912 return cSize + endResult;
3316 } 2913 }
3317 2914
3318 2915
3319 static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx, 2916 static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
3337 const void* src, size_t srcSize, 2934 const void* src, size_t srcSize,
3338 const void* dict,size_t dictSize, 2935 const void* dict,size_t dictSize,
3339 ZSTD_parameters params) 2936 ZSTD_parameters params)
3340 { 2937 {
3341 DEBUGLOG(4, "ZSTD_compress_advanced"); 2938 DEBUGLOG(4, "ZSTD_compress_advanced");
3342 CHECK_F(ZSTD_checkCParams(params.cParams)); 2939 FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams));
3343 return ZSTD_compress_internal(cctx, 2940 return ZSTD_compress_internal(cctx,
3344 dst, dstCapacity, 2941 dst, dstCapacity,
3345 src, srcSize, 2942 src, srcSize,
3346 dict, dictSize, 2943 dict, dictSize,
3347 params); 2944 params);
3354 const void* src, size_t srcSize, 2951 const void* src, size_t srcSize,
3355 const void* dict,size_t dictSize, 2952 const void* dict,size_t dictSize,
3356 ZSTD_CCtx_params params) 2953 ZSTD_CCtx_params params)
3357 { 2954 {
3358 DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize); 2955 DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
3359 CHECK_F( ZSTD_compressBegin_internal(cctx, 2956 FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
3360 dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, 2957 dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3361 params, srcSize, ZSTDb_not_buffered) ); 2958 params, srcSize, ZSTDb_not_buffered) );
3362 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); 2959 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3363 } 2960 }
3364 2961
3438 cdict->dictContent = dictBuffer; 3035 cdict->dictContent = dictBuffer;
3439 } else { 3036 } else {
3440 void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem); 3037 void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
3441 cdict->dictBuffer = internalBuffer; 3038 cdict->dictBuffer = internalBuffer;
3442 cdict->dictContent = internalBuffer; 3039 cdict->dictContent = internalBuffer;
3443 if (!internalBuffer) return ERROR(memory_allocation); 3040 RETURN_ERROR_IF(!internalBuffer, memory_allocation);
3444 memcpy(internalBuffer, dictBuffer, dictSize); 3041 memcpy(internalBuffer, dictBuffer, dictSize);
3445 } 3042 }
3446 cdict->dictContentSize = dictSize; 3043 cdict->dictContentSize = dictSize;
3447 3044
3448 /* Reset the state to no dictionary */ 3045 /* Reset the state to no dictionary */
3449 ZSTD_reset_compressedBlockState(&cdict->cBlockState); 3046 ZSTD_reset_compressedBlockState(&cdict->cBlockState);
3450 { void* const end = ZSTD_reset_matchState( 3047 { void* const end = ZSTD_reset_matchState(&cdict->matchState,
3451 &cdict->matchState, 3048 (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32,
3452 (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32, 3049 &cParams,
3453 &cParams, ZSTDcrp_continue, /* forCCtx */ 0); 3050 ZSTDcrp_continue, ZSTD_resetTarget_CDict);
3454 assert(end == (char*)cdict->workspace + cdict->workspaceSize); 3051 assert(end == (char*)cdict->workspace + cdict->workspaceSize);
3455 (void)end; 3052 (void)end;
3456 } 3053 }
3457 /* (Maybe) load the dictionary 3054 /* (Maybe) load the dictionary
3458 * Skips loading the dictionary if it is <= 8 bytes. 3055 * Skips loading the dictionary if it is <= 8 bytes.
3464 params.cParams = cParams; 3061 params.cParams = cParams;
3465 { size_t const dictID = ZSTD_compress_insertDictionary( 3062 { size_t const dictID = ZSTD_compress_insertDictionary(
3466 &cdict->cBlockState, &cdict->matchState, &params, 3063 &cdict->cBlockState, &cdict->matchState, &params,
3467 cdict->dictContent, cdict->dictContentSize, 3064 cdict->dictContent, cdict->dictContentSize,
3468 dictContentType, ZSTD_dtlm_full, cdict->workspace); 3065 dictContentType, ZSTD_dtlm_full, cdict->workspace);
3469 if (ZSTD_isError(dictID)) return dictID; 3066 FORWARD_IF_ERROR(dictID);
3470 assert(dictID <= (size_t)(U32)-1); 3067 assert(dictID <= (size_t)(U32)-1);
3471 cdict->dictID = (U32)dictID; 3068 cdict->dictID = (U32)dictID;
3472 } 3069 }
3473 } 3070 }
3474 3071
3594 size_t ZSTD_compressBegin_usingCDict_advanced( 3191 size_t ZSTD_compressBegin_usingCDict_advanced(
3595 ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, 3192 ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
3596 ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) 3193 ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
3597 { 3194 {
3598 DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced"); 3195 DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
3599 if (cdict==NULL) return ERROR(dictionary_wrong); 3196 RETURN_ERROR_IF(cdict==NULL, dictionary_wrong);
3600 { ZSTD_CCtx_params params = cctx->requestedParams; 3197 { ZSTD_CCtx_params params = cctx->requestedParams;
3601 params.cParams = ZSTD_getCParamsFromCDict(cdict); 3198 params.cParams = ZSTD_getCParamsFromCDict(cdict);
3602 /* Increase window log to fit the entire dictionary and source if the 3199 /* Increase window log to fit the entire dictionary and source if the
3603 * source size is known. Limit the increase to 19, which is the 3200 * source size is known. Limit the increase to 19, which is the
3604 * window log for compression level 1 with the largest source size. 3201 * window log for compression level 1 with the largest source size.
3630 size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, 3227 size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
3631 void* dst, size_t dstCapacity, 3228 void* dst, size_t dstCapacity,
3632 const void* src, size_t srcSize, 3229 const void* src, size_t srcSize,
3633 const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) 3230 const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
3634 { 3231 {
3635 CHECK_F (ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */ 3232 FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
3636 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); 3233 return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3637 } 3234 }
3638 3235
3639 /*! ZSTD_compress_usingCDict() : 3236 /*! ZSTD_compress_usingCDict() :
3640 * Compression using a digested Dictionary. 3237 * Compression using a digested Dictionary.
3698 params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize); 3295 params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
3699 /* params are supposed to be fully validated at this point */ 3296 /* params are supposed to be fully validated at this point */
3700 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); 3297 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3701 assert(!((dict) && (cdict))); /* either dict or cdict, not both */ 3298 assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3702 3299
3703 CHECK_F( ZSTD_compressBegin_internal(cctx, 3300 FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
3704 dict, dictSize, dictContentType, ZSTD_dtlm_fast, 3301 dict, dictSize, dictContentType, ZSTD_dtlm_fast,
3705 cdict, 3302 cdict,
3706 params, pledgedSrcSize, 3303 params, pledgedSrcSize,
3707 ZSTDb_buffered) ); 3304 ZSTDb_buffered) );
3708 3305
3716 return 0; /* ready to go */ 3313 return 0; /* ready to go */
3717 } 3314 }
3718 3315
3719 /* ZSTD_resetCStream(): 3316 /* ZSTD_resetCStream():
3720 * pledgedSrcSize == 0 means "unknown" */ 3317 * pledgedSrcSize == 0 means "unknown" */
3721 size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize) 3318 size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
3722 { 3319 {
3723 ZSTD_CCtx_params params = zcs->requestedParams; 3320 /* temporary : 0 interpreted as "unknown" during transition period.
3321 * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
3322 * 0 will be interpreted as "empty" in the future.
3323 */
3324 U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3724 DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize); 3325 DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
3725 if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; 3326 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3726 params.fParams.contentSizeFlag = 1; 3327 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3727 return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize); 3328 return 0;
3728 } 3329 }
3729 3330
3730 /*! ZSTD_initCStream_internal() : 3331 /*! ZSTD_initCStream_internal() :
3731 * Note : for lib/compress only. Used by zstdmt_compress.c. 3332 * Note : for lib/compress only. Used by zstdmt_compress.c.
3732 * Assumption 1 : params are valid 3333 * Assumption 1 : params are valid
3734 size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, 3335 size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3735 const void* dict, size_t dictSize, const ZSTD_CDict* cdict, 3336 const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3736 ZSTD_CCtx_params params, unsigned long long pledgedSrcSize) 3337 ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
3737 { 3338 {
3738 DEBUGLOG(4, "ZSTD_initCStream_internal"); 3339 DEBUGLOG(4, "ZSTD_initCStream_internal");
3739 params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize); 3340 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3341 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3740 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); 3342 assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3343 zcs->requestedParams = params;
3741 assert(!((dict) && (cdict))); /* either dict or cdict, not both */ 3344 assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3742 3345 if (dict) {
3743 if (dict && dictSize >= 8) { 3346 FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
3744 DEBUGLOG(4, "loading dictionary of size %u", (unsigned)dictSize);
3745 if (zcs->staticSize) { /* static CCtx : never uses malloc */
3746 /* incompatible with internal cdict creation */
3747 return ERROR(memory_allocation);
3748 }
3749 ZSTD_freeCDict(zcs->cdictLocal);
3750 zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
3751 ZSTD_dlm_byCopy, ZSTD_dct_auto,
3752 params.cParams, zcs->customMem);
3753 zcs->cdict = zcs->cdictLocal;
3754 if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
3755 } else { 3347 } else {
3756 if (cdict) { 3348 /* Dictionary is cleared if !cdict */
3757 params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict; it includes windowLog */ 3349 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
3758 } 3350 }
3759 ZSTD_freeCDict(zcs->cdictLocal); 3351 return 0;
3760 zcs->cdictLocal = NULL;
3761 zcs->cdict = cdict;
3762 }
3763
3764 return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
3765 } 3352 }
3766 3353
3767 /* ZSTD_initCStream_usingCDict_advanced() : 3354 /* ZSTD_initCStream_usingCDict_advanced() :
3768 * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */ 3355 * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
3769 size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, 3356 size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
3770 const ZSTD_CDict* cdict, 3357 const ZSTD_CDict* cdict,
3771 ZSTD_frameParameters fParams, 3358 ZSTD_frameParameters fParams,
3772 unsigned long long pledgedSrcSize) 3359 unsigned long long pledgedSrcSize)
3773 { 3360 {
3774 DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced"); 3361 DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
3775 if (!cdict) return ERROR(dictionary_wrong); /* cannot handle NULL cdict (does not know what to do) */ 3362 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3776 { ZSTD_CCtx_params params = zcs->requestedParams; 3363 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3777 params.cParams = ZSTD_getCParamsFromCDict(cdict); 3364 zcs->requestedParams.fParams = fParams;
3778 params.fParams = fParams; 3365 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
3779 return ZSTD_initCStream_internal(zcs, 3366 return 0;
3780 NULL, 0, cdict,
3781 params, pledgedSrcSize);
3782 }
3783 } 3367 }
3784 3368
3785 /* note : cdict must outlive compression session */ 3369 /* note : cdict must outlive compression session */
3786 size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict) 3370 size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
3787 { 3371 {
3788 ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksum */, 0 /* hideDictID */ };
3789 DEBUGLOG(4, "ZSTD_initCStream_usingCDict"); 3372 DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
3790 return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */ 3373 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3374 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
3375 return 0;
3791 } 3376 }
3792 3377
3793 3378
3794 /* ZSTD_initCStream_advanced() : 3379 /* ZSTD_initCStream_advanced() :
3795 * pledgedSrcSize must be exact. 3380 * pledgedSrcSize must be exact.
3796 * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. 3381 * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
3797 * dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */ 3382 * dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
3798 size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, 3383 size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
3799 const void* dict, size_t dictSize, 3384 const void* dict, size_t dictSize,
3800 ZSTD_parameters params, unsigned long long pledgedSrcSize) 3385 ZSTD_parameters params, unsigned long long pss)
3801 { 3386 {
3802 DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u", 3387 /* for compatibility with older programs relying on this behavior.
3803 (unsigned)pledgedSrcSize, params.fParams.contentSizeFlag); 3388 * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.
3804 CHECK_F( ZSTD_checkCParams(params.cParams) ); 3389 * This line will be removed in the future.
3805 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. */ 3390 */
3391 U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3392 DEBUGLOG(4, "ZSTD_initCStream_advanced");
3393 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3394 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3395 FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
3806 zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params); 3396 zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3807 return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, zcs->requestedParams, pledgedSrcSize); 3397 FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
3398 return 0;
3808 } 3399 }
3809 3400
3810 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel) 3401 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3811 { 3402 {
3812 ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel); 3403 DEBUGLOG(4, "ZSTD_initCStream_usingDict");
3813 return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, zcs->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN); 3404 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3405 FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
3406 FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
3407 return 0;
3814 } 3408 }
3815 3409
3816 size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss) 3410 size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
3817 { 3411 {
3818 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 */ 3412 /* temporary : 0 interpreted as "unknown" during transition period.
3819 ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel); 3413 * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
3820 return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, zcs->requestedParams, pledgedSrcSize); 3414 * 0 will be interpreted as "empty" in the future.
3415 */
3416 U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3417 DEBUGLOG(4, "ZSTD_initCStream_srcSize");
3418 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3419 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
3420 FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
3421 FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3422 return 0;
3821 } 3423 }
3822 3424
3823 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) 3425 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
3824 { 3426 {
3825 DEBUGLOG(4, "ZSTD_initCStream"); 3427 DEBUGLOG(4, "ZSTD_initCStream");
3826 return ZSTD_initCStream_srcSize(zcs, compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN); 3428 FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3429 FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
3430 FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
3431 return 0;
3827 } 3432 }
3828 3433
3829 /*====== Compression ======*/ 3434 /*====== Compression ======*/
3830 3435
3831 static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx) 3436 static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
3845 3450
3846 /** ZSTD_compressStream_generic(): 3451 /** ZSTD_compressStream_generic():
3847 * internal function for all *compressStream*() variants 3452 * internal function for all *compressStream*() variants
3848 * non-static, because can be called from zstdmt_compress.c 3453 * non-static, because can be called from zstdmt_compress.c
3849 * @return : hint size for next input */ 3454 * @return : hint size for next input */
3850 size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, 3455 static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3851 ZSTD_outBuffer* output, 3456 ZSTD_outBuffer* output,
3852 ZSTD_inBuffer* input, 3457 ZSTD_inBuffer* input,
3853 ZSTD_EndDirective const flushMode) 3458 ZSTD_EndDirective const flushMode)
3854 { 3459 {
3855 const char* const istart = (const char*)input->src; 3460 const char* const istart = (const char*)input->src;
3856 const char* const iend = istart + input->size; 3461 const char* const iend = istart + input->size;
3857 const char* ip = istart + input->pos; 3462 const char* ip = istart + input->pos;
3858 char* const ostart = (char*)output->dst; 3463 char* const ostart = (char*)output->dst;
3871 3476
3872 while (someMoreWork) { 3477 while (someMoreWork) {
3873 switch(zcs->streamStage) 3478 switch(zcs->streamStage)
3874 { 3479 {
3875 case zcss_init: 3480 case zcss_init:
3876 /* call ZSTD_initCStream() first ! */ 3481 RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
3877 return ERROR(init_missing);
3878 3482
3879 case zcss_load: 3483 case zcss_load:
3880 if ( (flushMode == ZSTD_e_end) 3484 if ( (flushMode == ZSTD_e_end)
3881 && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */ 3485 && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */
3882 && (zcs->inBuffPos == 0) ) { 3486 && (zcs->inBuffPos == 0) ) {
3883 /* shortcut to compression pass directly into output buffer */ 3487 /* shortcut to compression pass directly into output buffer */
3884 size_t const cSize = ZSTD_compressEnd(zcs, 3488 size_t const cSize = ZSTD_compressEnd(zcs,
3885 op, oend-op, ip, iend-ip); 3489 op, oend-op, ip, iend-ip);
3886 DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize); 3490 DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
3887 if (ZSTD_isError(cSize)) return cSize; 3491 FORWARD_IF_ERROR(cSize);
3888 ip = iend; 3492 ip = iend;
3889 op += cSize; 3493 op += cSize;
3890 zcs->frameEnded = 1; 3494 zcs->frameEnded = 1;
3891 ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); 3495 ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
3892 someMoreWork = 0; break; 3496 someMoreWork = 0; break;
3923 cSize = lastBlock ? 3527 cSize = lastBlock ?
3924 ZSTD_compressEnd(zcs, cDst, oSize, 3528 ZSTD_compressEnd(zcs, cDst, oSize,
3925 zcs->inBuff + zcs->inToCompress, iSize) : 3529 zcs->inBuff + zcs->inToCompress, iSize) :
3926 ZSTD_compressContinue(zcs, cDst, oSize, 3530 ZSTD_compressContinue(zcs, cDst, oSize,
3927 zcs->inBuff + zcs->inToCompress, iSize); 3531 zcs->inBuff + zcs->inToCompress, iSize);
3928 if (ZSTD_isError(cSize)) return cSize; 3532 FORWARD_IF_ERROR(cSize);
3929 zcs->frameEnded = lastBlock; 3533 zcs->frameEnded = lastBlock;
3930 /* prepare next block */ 3534 /* prepare next block */
3931 zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; 3535 zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
3932 if (zcs->inBuffTarget > zcs->inBuffSize) 3536 if (zcs->inBuffTarget > zcs->inBuffSize)
3933 zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; 3537 zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
3951 } 3555 }
3952 /* fall-through */ 3556 /* fall-through */
3953 case zcss_flush: 3557 case zcss_flush:
3954 DEBUGLOG(5, "flush stage"); 3558 DEBUGLOG(5, "flush stage");
3955 { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; 3559 { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
3956 size_t const flushed = ZSTD_limitCopy(op, oend-op, 3560 size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
3957 zcs->outBuff + zcs->outBuffFlushedSize, toFlush); 3561 zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
3958 DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u", 3562 DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
3959 (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed); 3563 (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
3960 op += flushed; 3564 op += flushed;
3961 zcs->outBuffFlushedSize += flushed; 3565 zcs->outBuffFlushedSize += flushed;
3999 3603
4000 } 3604 }
4001 3605
4002 size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input) 3606 size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
4003 { 3607 {
4004 CHECK_F( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) ); 3608 FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
4005 return ZSTD_nextInputSizeHint_MTorST(zcs); 3609 return ZSTD_nextInputSizeHint_MTorST(zcs);
4006 } 3610 }
4007 3611
4008 3612
4009 size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, 3613 size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4011 ZSTD_inBuffer* input, 3615 ZSTD_inBuffer* input,
4012 ZSTD_EndDirective endOp) 3616 ZSTD_EndDirective endOp)
4013 { 3617 {
4014 DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp); 3618 DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
4015 /* check conditions */ 3619 /* check conditions */
4016 if (output->pos > output->size) return ERROR(GENERIC); 3620 RETURN_ERROR_IF(output->pos > output->size, GENERIC);
4017 if (input->pos > input->size) return ERROR(GENERIC); 3621 RETURN_ERROR_IF(input->pos > input->size, GENERIC);
4018 assert(cctx!=NULL); 3622 assert(cctx!=NULL);
4019 3623
4020 /* transparent initialization stage */ 3624 /* transparent initialization stage */
4021 if (cctx->streamStage == zcss_init) { 3625 if (cctx->streamStage == zcss_init) {
4022 ZSTD_CCtx_params params = cctx->requestedParams; 3626 ZSTD_CCtx_params params = cctx->requestedParams;
4023 ZSTD_prefixDict const prefixDict = cctx->prefixDict; 3627 ZSTD_prefixDict const prefixDict = cctx->prefixDict;
3628 FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) ); /* Init the local dict if present. */
4024 memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ 3629 memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
4025 assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ 3630 assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
4026 DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); 3631 DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
4027 if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */ 3632 if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
4028 params.cParams = ZSTD_getCParamsFromCCtxParams( 3633 params.cParams = ZSTD_getCParamsFromCCtxParams(
4037 /* mt context creation */ 3642 /* mt context creation */
4038 if (cctx->mtctx == NULL) { 3643 if (cctx->mtctx == NULL) {
4039 DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", 3644 DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
4040 params.nbWorkers); 3645 params.nbWorkers);
4041 cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem); 3646 cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
4042 if (cctx->mtctx == NULL) return ERROR(memory_allocation); 3647 RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation);
4043 } 3648 }
4044 /* mt compression */ 3649 /* mt compression */
4045 DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); 3650 DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
4046 CHECK_F( ZSTDMT_initCStream_internal( 3651 FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
4047 cctx->mtctx, 3652 cctx->mtctx,
4048 prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent, 3653 prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
4049 cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) ); 3654 cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
4050 cctx->streamStage = zcss_load; 3655 cctx->streamStage = zcss_load;
4051 cctx->appliedParams.nbWorkers = params.nbWorkers; 3656 cctx->appliedParams.nbWorkers = params.nbWorkers;
4052 } else 3657 } else
4053 #endif 3658 #endif
4054 { CHECK_F( ZSTD_resetCStream_internal(cctx, 3659 { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
4055 prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, 3660 prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
4056 cctx->cdict, 3661 cctx->cdict,
4057 params, cctx->pledgedSrcSizePlusOne-1) ); 3662 params, cctx->pledgedSrcSizePlusOne-1) );
4058 assert(cctx->streamStage == zcss_load); 3663 assert(cctx->streamStage == zcss_load);
4059 assert(cctx->appliedParams.nbWorkers == 0); 3664 assert(cctx->appliedParams.nbWorkers == 0);
4061 /* end of transparent initialization stage */ 3666 /* end of transparent initialization stage */
4062 3667
4063 /* compression stage */ 3668 /* compression stage */
4064 #ifdef ZSTD_MULTITHREAD 3669 #ifdef ZSTD_MULTITHREAD
4065 if (cctx->appliedParams.nbWorkers > 0) { 3670 if (cctx->appliedParams.nbWorkers > 0) {
3671 int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
3672 size_t flushMin;
3673 assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
4066 if (cctx->cParamsChanged) { 3674 if (cctx->cParamsChanged) {
4067 ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams); 3675 ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
4068 cctx->cParamsChanged = 0; 3676 cctx->cParamsChanged = 0;
4069 } 3677 }
4070 { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); 3678 do {
3679 flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
4071 if ( ZSTD_isError(flushMin) 3680 if ( ZSTD_isError(flushMin)
4072 || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ 3681 || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
4073 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); 3682 ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
4074 } 3683 }
4075 DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic"); 3684 FORWARD_IF_ERROR(flushMin);
4076 return flushMin; 3685 } while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
4077 } } 3686 DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
3687 /* Either we don't require maximum forward progress, we've finished the
3688 * flush, or we are out of output space.
3689 */
3690 assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
3691 return flushMin;
3692 }
4078 #endif 3693 #endif
4079 CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) ); 3694 FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) );
4080 DEBUGLOG(5, "completed ZSTD_compressStream2"); 3695 DEBUGLOG(5, "completed ZSTD_compressStream2");
4081 return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */ 3696 return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
4082 } 3697 }
4083 3698
4084 size_t ZSTD_compressStream2_simpleArgs ( 3699 size_t ZSTD_compressStream2_simpleArgs (
4105 size_t iPos = 0; 3720 size_t iPos = 0;
4106 size_t const result = ZSTD_compressStream2_simpleArgs(cctx, 3721 size_t const result = ZSTD_compressStream2_simpleArgs(cctx,
4107 dst, dstCapacity, &oPos, 3722 dst, dstCapacity, &oPos,
4108 src, srcSize, &iPos, 3723 src, srcSize, &iPos,
4109 ZSTD_e_end); 3724 ZSTD_e_end);
4110 if (ZSTD_isError(result)) return result; 3725 FORWARD_IF_ERROR(result);
4111 if (result != 0) { /* compression not completed, due to lack of output space */ 3726 if (result != 0) { /* compression not completed, due to lack of output space */
4112 assert(oPos == dstCapacity); 3727 assert(oPos == dstCapacity);
4113 return ERROR(dstSize_tooSmall); 3728 RETURN_ERROR(dstSize_tooSmall);
4114 } 3729 }
4115 assert(iPos == srcSize); /* all input is expected consumed */ 3730 assert(iPos == srcSize); /* all input is expected consumed */
4116 return oPos; 3731 return oPos;
4117 } 3732 }
4118 } 3733 }
4130 3745
4131 size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) 3746 size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
4132 { 3747 {
4133 ZSTD_inBuffer input = { NULL, 0, 0 }; 3748 ZSTD_inBuffer input = { NULL, 0, 0 };
4134 size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end); 3749 size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
4135 CHECK_F( remainingToFlush ); 3750 FORWARD_IF_ERROR( remainingToFlush );
4136 if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */ 3751 if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
4137 /* single thread mode : attempt to calculate remaining to flush more precisely */ 3752 /* single thread mode : attempt to calculate remaining to flush more precisely */
4138 { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE; 3753 { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
4139 size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4; 3754 size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);
4140 size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize; 3755 size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
4141 DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush); 3756 DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
4142 return toFlush; 3757 return toFlush;
4143 } 3758 }
4144 } 3759 }
4149 #define ZSTD_MAX_CLEVEL 22 3764 #define ZSTD_MAX_CLEVEL 22
4150 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } 3765 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
4151 int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } 3766 int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
4152 3767
4153 static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { 3768 static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
4154 { /* "default" - guarantees a monotonically increasing memory budget */ 3769 { /* "default" - for any srcSize > 256 KB */
4155 /* W, C, H, S, L, TL, strat */ 3770 /* W, C, H, S, L, TL, strat */
4156 { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ 3771 { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
4157 { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ 3772 { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
4158 { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ 3773 { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
4159 { 21, 16, 17, 1, 5, 1, ZSTD_dfast }, /* level 3 */ 3774 { 21, 16, 17, 1, 5, 1, ZSTD_dfast }, /* level 3 */
4256 { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ 3871 { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/
4257 }, 3872 },
4258 }; 3873 };
4259 3874
4260 /*! ZSTD_getCParams() : 3875 /*! ZSTD_getCParams() :
4261 * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. 3876 * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
4262 * Size values are optional, provide 0 if not known or unused */ 3877 * Size values are optional, provide 0 if not known or unused */
4263 ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) 3878 ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
4264 { 3879 {
4265 size_t const addedSize = srcSizeHint ? 0 : 500; 3880 size_t const addedSize = srcSizeHint ? 0 : 500;
4266 U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1; 3881 U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : ZSTD_CONTENTSIZE_UNKNOWN; /* intentional overflow for srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN */
4267 U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */ 3882 U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
4268 int row = compressionLevel; 3883 int row = compressionLevel;
4269 DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel); 3884 DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
4270 if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ 3885 if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
4271 if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ 3886 if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
4272 if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; 3887 if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
4273 { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; 3888 { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
4274 if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */ 3889 if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
4275 return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); 3890 return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); /* refine parameters based on srcSize & dictSize */
4276 } 3891 }
4277 } 3892 }
4278 3893
4279 /*! ZSTD_getParams() : 3894 /*! ZSTD_getParams() :
4280 * same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`). 3895 * same idea as ZSTD_getCParams()
4281 * All fields of `ZSTD_frameParameters` are set to default (0) */ 3896 * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
3897 * Fields of `ZSTD_frameParameters` are set to default values */
4282 ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { 3898 ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
4283 ZSTD_parameters params; 3899 ZSTD_parameters params;
4284 ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize); 3900 ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
4285 DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); 3901 DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
4286 memset(&params, 0, sizeof(params)); 3902 memset(&params, 0, sizeof(params));