zstd-ruby 1.3.4.0 → 1.3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/Makefile +56 -10
  4. data/ext/zstdruby/libzstd/README.md +4 -0
  5. data/ext/zstdruby/libzstd/common/bitstream.h +6 -19
  6. data/ext/zstdruby/libzstd/common/compiler.h +3 -3
  7. data/ext/zstdruby/libzstd/common/cpu.h +1 -2
  8. data/ext/zstdruby/libzstd/common/debug.c +44 -0
  9. data/ext/zstdruby/libzstd/common/debug.h +123 -0
  10. data/ext/zstdruby/libzstd/common/entropy_common.c +16 -1
  11. data/ext/zstdruby/libzstd/common/fse.h +45 -41
  12. data/ext/zstdruby/libzstd/common/fse_decompress.c +1 -1
  13. data/ext/zstdruby/libzstd/common/huf.h +34 -27
  14. data/ext/zstdruby/libzstd/common/pool.c +89 -32
  15. data/ext/zstdruby/libzstd/common/pool.h +29 -19
  16. data/ext/zstdruby/libzstd/common/zstd_common.c +0 -5
  17. data/ext/zstdruby/libzstd/common/zstd_internal.h +3 -37
  18. data/ext/zstdruby/libzstd/compress/fse_compress.c +28 -163
  19. data/ext/zstdruby/libzstd/compress/hist.c +195 -0
  20. data/ext/zstdruby/libzstd/compress/hist.h +92 -0
  21. data/ext/zstdruby/libzstd/compress/huf_compress.c +14 -6
  22. data/ext/zstdruby/libzstd/compress/zstd_compress.c +798 -350
  23. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +120 -34
  24. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +247 -87
  25. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +4 -1
  26. data/ext/zstdruby/libzstd/compress/zstd_fast.c +177 -56
  27. data/ext/zstdruby/libzstd/compress/zstd_fast.h +4 -1
  28. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +331 -65
  29. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +13 -0
  30. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +15 -20
  31. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +1 -2
  32. data/ext/zstdruby/libzstd/compress/zstd_opt.c +503 -300
  33. data/ext/zstdruby/libzstd/compress/zstd_opt.h +7 -0
  34. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +122 -47
  35. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +5 -5
  36. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +325 -325
  37. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +80 -43
  38. data/ext/zstdruby/libzstd/dictBuilder/cover.c +9 -2
  39. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +5 -5
  40. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +12 -61
  41. data/ext/zstdruby/libzstd/zstd.h +137 -69
  42. data/lib/zstd-ruby/version.rb +1 -1
  43. metadata +7 -3
@@ -0,0 +1,92 @@
1
+ /* ******************************************************************
2
+ hist : Histogram functions
3
+ part of Finite State Entropy project
4
+ Copyright (C) 2013-present, Yann Collet.
5
+
6
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions are
10
+ met:
11
+
12
+ * Redistributions of source code must retain the above copyright
13
+ notice, this list of conditions and the following disclaimer.
14
+ * Redistributions in binary form must reproduce the above
15
+ copyright notice, this list of conditions and the following disclaimer
16
+ in the documentation and/or other materials provided with the
17
+ distribution.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ You can contact the author at :
32
+ - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
33
+ - Public forum : https://groups.google.com/forum/#!forum/lz4c
34
+ ****************************************************************** */
35
+
36
+ /* --- dependencies --- */
37
+ #include <stddef.h> /* size_t */
38
+
39
+
40
+ /* --- simple histogram functions --- */
41
+
42
+ /*! HIST_count():
43
+ * Provides the precise count of each byte within a table 'count'.
44
+ * 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1).
45
+ * Updates *maxSymbolValuePtr with actual largest symbol value detected.
46
+ * @return : count of the most frequent symbol (which isn't identified).
47
+ * or an error code, which can be tested using HIST_isError().
48
+ * note : if return == srcSize, there is only one symbol.
49
+ */
50
+ size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,
51
+ const void* src, size_t srcSize);
52
+
53
+ unsigned HIST_isError(size_t code); /*< tells if a return value is an error code */
54
+
55
+
56
+ /* --- advanced histogram functions --- */
57
+
58
+ #define HIST_WKSP_SIZE_U32 1024
59
+ /** HIST_count_wksp() :
60
+ * Same as HIST_count(), but using an externally provided scratch buffer.
61
+ * Benefit is this function will use very little stack space.
62
+ * `workSpace` must be a table of unsigned of size >= HIST_WKSP_SIZE_U32
63
+ */
64
+ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
65
+ const void* src, size_t srcSize,
66
+ unsigned* workSpace);
67
+
68
+ /** HIST_countFast() :
69
+ * same as HIST_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr.
70
+ * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr`
71
+ */
72
+ size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
73
+ const void* src, size_t srcSize);
74
+
75
+ /** HIST_countFast_wksp() :
76
+ * Same as HIST_countFast(), but using an externally provided scratch buffer.
77
+ * `workSpace` must be a table of unsigned of size >= HIST_WKSP_SIZE_U32
78
+ */
79
+ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
80
+ const void* src, size_t srcSize,
81
+ unsigned* workSpace);
82
+
83
+ /*! HIST_count_simple() :
84
+ * Same as HIST_countFast(), this function is unsafe,
85
+ * and will segfault if any value within `src` is `> *maxSymbolValuePtr`.
86
+ * It is also a bit slower for large inputs.
87
+ * However, it does not need any additional memory (not even on stack).
88
+ * @return : count of the most frequent symbol.
89
+ * Note this function doesn't produce any error (i.e. it must succeed).
90
+ */
91
+ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
92
+ const void* src, size_t srcSize);
@@ -45,8 +45,9 @@
45
45
  ****************************************************************/
46
46
  #include <string.h> /* memcpy, memset */
47
47
  #include <stdio.h> /* printf (debug) */
48
- #include "bitstream.h"
49
48
  #include "compiler.h"
49
+ #include "bitstream.h"
50
+ #include "hist.h"
50
51
  #define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */
51
52
  #include "fse.h" /* header compression */
52
53
  #define HUF_STATIC_LINKING_ONLY
@@ -58,7 +59,7 @@
58
59
  * Error Management
59
60
  ****************************************************************/
60
61
  #define HUF_isError ERR_isError
61
- #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
62
+ #define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */
62
63
  #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
63
64
  #define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
64
65
 
@@ -100,9 +101,9 @@ size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable,
100
101
  if (wtSize <= 1) return 0; /* Not compressible */
101
102
 
102
103
  /* Scan input and build symbol stats */
103
- { CHECK_V_F(maxCount, FSE_count_simple(count, &maxSymbolValue, weightTable, wtSize) );
104
+ { unsigned const maxCount = HIST_count_simple(count, &maxSymbolValue, weightTable, wtSize); /* never fails */
104
105
  if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
105
- if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
106
+ if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
106
107
  }
107
108
 
108
109
  tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
@@ -216,6 +217,13 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src
216
217
  return readSize;
217
218
  }
218
219
 
220
+ U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue)
221
+ {
222
+ const HUF_CElt* table = (const HUF_CElt*)symbolTable;
223
+ assert(symbolValue <= HUF_SYMBOLVALUE_MAX);
224
+ return table[symbolValue].nbBits;
225
+ }
226
+
219
227
 
220
228
  typedef struct nodeElt_s {
221
229
  U32 count;
@@ -660,9 +668,9 @@ static size_t HUF_compress_internal (
660
668
  }
661
669
 
662
670
  /* Scan input and build symbol stats */
663
- { CHECK_V_F(largest, FSE_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->count) );
671
+ { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->count) );
664
672
  if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
665
- if (largest <= (srcSize >> 7)+1) return 0; /* heuristic : probably not compressible enough */
673
+ if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */
666
674
  }
667
675
 
668
676
  /* Check validity of previous table */
@@ -8,21 +8,13 @@
8
8
  * You may select, at your option, one of the above-listed licenses.
9
9
  */
10
10
 
11
-
12
- /*-*************************************
13
- * Tuning parameters
14
- ***************************************/
15
- #ifndef ZSTD_CLEVEL_DEFAULT
16
- # define ZSTD_CLEVEL_DEFAULT 3
17
- #endif
18
-
19
-
20
11
  /*-*************************************
21
12
  * Dependencies
22
13
  ***************************************/
23
14
  #include <string.h> /* memset */
24
15
  #include "cpu.h"
25
16
  #include "mem.h"
17
+ #include "hist.h" /* HIST_countFast_wksp */
26
18
  #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
27
19
  #include "fse.h"
28
20
  #define HUF_STATIC_LINKING_ONLY
@@ -64,17 +56,26 @@ ZSTD_CCtx* ZSTD_createCCtx(void)
64
56
  return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
65
57
  }
66
58
 
59
+ static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
60
+ {
61
+ assert(cctx != NULL);
62
+ memset(cctx, 0, sizeof(*cctx));
63
+ cctx->customMem = memManager;
64
+ cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
65
+ { size_t const err = ZSTD_CCtx_resetParameters(cctx);
66
+ assert(!ZSTD_isError(err));
67
+ (void)err;
68
+ }
69
+ }
70
+
67
71
  ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
68
72
  {
69
73
  ZSTD_STATIC_ASSERT(zcss_init==0);
70
74
  ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
71
75
  if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
72
- { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
76
+ { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
73
77
  if (!cctx) return NULL;
74
- cctx->customMem = customMem;
75
- cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
76
- cctx->requestedParams.fParams.contentSizeFlag = 1;
77
- cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
78
+ ZSTD_initCCtx(cctx, customMem);
78
79
  return cctx;
79
80
  }
80
81
  }
@@ -102,17 +103,24 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
102
103
  return cctx;
103
104
  }
104
105
 
105
- size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
106
+ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
106
107
  {
107
- if (cctx==NULL) return 0; /* support free on NULL */
108
- if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
108
+ assert(cctx != NULL);
109
+ assert(cctx->staticSize == 0);
109
110
  ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
110
111
  ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
111
112
  #ifdef ZSTD_MULTITHREAD
112
113
  ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
113
114
  #endif
115
+ }
116
+
117
+ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
118
+ {
119
+ if (cctx==NULL) return 0; /* support free on NULL */
120
+ if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
121
+ ZSTD_freeCCtxContent(cctx);
114
122
  ZSTD_free(cctx, cctx->customMem);
115
- return 0; /* reserved as a potential error code in the future */
123
+ return 0;
116
124
  }
117
125
 
118
126
 
@@ -143,21 +151,6 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
143
151
  /* private API call, for dictBuilder only */
144
152
  const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
145
153
 
146
- ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
147
- const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
148
- {
149
- ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
150
- if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
151
- if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
152
- if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
153
- if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
154
- if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
155
- if (CCtxParams->cParams.searchLength) cParams.searchLength = CCtxParams->cParams.searchLength;
156
- if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
157
- if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
158
- return cParams;
159
- }
160
-
161
154
  static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
162
155
  ZSTD_compressionParameters cParams)
163
156
  {
@@ -251,7 +244,6 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
251
244
  case ZSTD_p_minMatch:
252
245
  case ZSTD_p_targetLength:
253
246
  case ZSTD_p_compressionStrategy:
254
- case ZSTD_p_compressLiterals:
255
247
  return 1;
256
248
 
257
249
  case ZSTD_p_format:
@@ -268,6 +260,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
268
260
  case ZSTD_p_ldmMinMatch:
269
261
  case ZSTD_p_ldmBucketSizeLog:
270
262
  case ZSTD_p_ldmHashEveryLog:
263
+ case ZSTD_p_forceAttachDict:
271
264
  default:
272
265
  return 0;
273
266
  }
@@ -302,7 +295,6 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
302
295
  if (cctx->cdict) return ERROR(stage_wrong);
303
296
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
304
297
 
305
- case ZSTD_p_compressLiterals:
306
298
  case ZSTD_p_contentSizeFlag:
307
299
  case ZSTD_p_checksumFlag:
308
300
  case ZSTD_p_dictIDFlag:
@@ -313,6 +305,9 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
313
305
  * default : 0 when using a CDict, 1 when using a Prefix */
314
306
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
315
307
 
308
+ case ZSTD_p_forceAttachDict:
309
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
310
+
316
311
  case ZSTD_p_nbWorkers:
317
312
  if ((value>0) && cctx->staticSize) {
318
313
  return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
@@ -351,7 +346,6 @@ size_t ZSTD_CCtxParam_setParameter(
351
346
  int cLevel = (int)value; /* cast expected to restore negative sign */
352
347
  if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
353
348
  if (cLevel) { /* 0 : does not change current level */
354
- CCtxParams->disableLiteralCompression = (cLevel<0); /* negative levels disable huffman */
355
349
  CCtxParams->compressionLevel = cLevel;
356
350
  }
357
351
  if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
@@ -399,10 +393,6 @@ size_t ZSTD_CCtxParam_setParameter(
399
393
  CCtxParams->cParams.strategy = (ZSTD_strategy)value;
400
394
  return (size_t)CCtxParams->cParams.strategy;
401
395
 
402
- case ZSTD_p_compressLiterals:
403
- CCtxParams->disableLiteralCompression = !value;
404
- return !CCtxParams->disableLiteralCompression;
405
-
406
396
  case ZSTD_p_contentSizeFlag :
407
397
  /* Content size written in frame header _when known_ (default:1) */
408
398
  DEBUGLOG(4, "set content size flag = %u", (value>0));
@@ -423,6 +413,12 @@ size_t ZSTD_CCtxParam_setParameter(
423
413
  CCtxParams->forceWindow = (value > 0);
424
414
  return CCtxParams->forceWindow;
425
415
 
416
+ case ZSTD_p_forceAttachDict :
417
+ CCtxParams->attachDictPref = value ?
418
+ (value > 0 ? ZSTD_dictForceAttach : ZSTD_dictForceCopy) :
419
+ ZSTD_dictDefaultAttach;
420
+ return CCtxParams->attachDictPref;
421
+
426
422
  case ZSTD_p_nbWorkers :
427
423
  #ifndef ZSTD_MULTITHREAD
428
424
  if (value>0) return ERROR(parameter_unsupported);
@@ -477,6 +473,98 @@ size_t ZSTD_CCtxParam_setParameter(
477
473
  }
478
474
  }
479
475
 
476
+ size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned* value)
477
+ {
478
+ return ZSTD_CCtxParam_getParameter(&cctx->requestedParams, param, value);
479
+ }
480
+
481
+ size_t ZSTD_CCtxParam_getParameter(
482
+ ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, unsigned* value)
483
+ {
484
+ switch(param)
485
+ {
486
+ case ZSTD_p_format :
487
+ *value = CCtxParams->format;
488
+ break;
489
+ case ZSTD_p_compressionLevel :
490
+ *value = CCtxParams->compressionLevel;
491
+ break;
492
+ case ZSTD_p_windowLog :
493
+ *value = CCtxParams->cParams.windowLog;
494
+ break;
495
+ case ZSTD_p_hashLog :
496
+ *value = CCtxParams->cParams.hashLog;
497
+ break;
498
+ case ZSTD_p_chainLog :
499
+ *value = CCtxParams->cParams.chainLog;
500
+ break;
501
+ case ZSTD_p_searchLog :
502
+ *value = CCtxParams->cParams.searchLog;
503
+ break;
504
+ case ZSTD_p_minMatch :
505
+ *value = CCtxParams->cParams.searchLength;
506
+ break;
507
+ case ZSTD_p_targetLength :
508
+ *value = CCtxParams->cParams.targetLength;
509
+ break;
510
+ case ZSTD_p_compressionStrategy :
511
+ *value = (unsigned)CCtxParams->cParams.strategy;
512
+ break;
513
+ case ZSTD_p_contentSizeFlag :
514
+ *value = CCtxParams->fParams.contentSizeFlag;
515
+ break;
516
+ case ZSTD_p_checksumFlag :
517
+ *value = CCtxParams->fParams.checksumFlag;
518
+ break;
519
+ case ZSTD_p_dictIDFlag :
520
+ *value = !CCtxParams->fParams.noDictIDFlag;
521
+ break;
522
+ case ZSTD_p_forceMaxWindow :
523
+ *value = CCtxParams->forceWindow;
524
+ break;
525
+ case ZSTD_p_forceAttachDict :
526
+ *value = CCtxParams->attachDictPref;
527
+ break;
528
+ case ZSTD_p_nbWorkers :
529
+ #ifndef ZSTD_MULTITHREAD
530
+ assert(CCtxParams->nbWorkers == 0);
531
+ #endif
532
+ *value = CCtxParams->nbWorkers;
533
+ break;
534
+ case ZSTD_p_jobSize :
535
+ #ifndef ZSTD_MULTITHREAD
536
+ return ERROR(parameter_unsupported);
537
+ #else
538
+ *value = CCtxParams->jobSize;
539
+ break;
540
+ #endif
541
+ case ZSTD_p_overlapSizeLog :
542
+ #ifndef ZSTD_MULTITHREAD
543
+ return ERROR(parameter_unsupported);
544
+ #else
545
+ *value = CCtxParams->overlapSizeLog;
546
+ break;
547
+ #endif
548
+ case ZSTD_p_enableLongDistanceMatching :
549
+ *value = CCtxParams->ldmParams.enableLdm;
550
+ break;
551
+ case ZSTD_p_ldmHashLog :
552
+ *value = CCtxParams->ldmParams.hashLog;
553
+ break;
554
+ case ZSTD_p_ldmMinMatch :
555
+ *value = CCtxParams->ldmParams.minMatchLength;
556
+ break;
557
+ case ZSTD_p_ldmBucketSizeLog :
558
+ *value = CCtxParams->ldmParams.bucketSizeLog;
559
+ break;
560
+ case ZSTD_p_ldmHashEveryLog :
561
+ *value = CCtxParams->ldmParams.hashEveryLog;
562
+ break;
563
+ default: return ERROR(parameter_unsupported);
564
+ }
565
+ return 0;
566
+ }
567
+
480
568
  /** ZSTD_CCtx_setParametersUsingCCtxParams() :
481
569
  * just applies `params` into `cctx`
482
570
  * no action is performed, parameters are merely stored.
@@ -487,6 +575,7 @@ size_t ZSTD_CCtxParam_setParameter(
487
575
  size_t ZSTD_CCtx_setParametersUsingCCtxParams(
488
576
  ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
489
577
  {
578
+ DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
490
579
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
491
580
  if (cctx->cdict) return ERROR(stage_wrong);
492
581
 
@@ -565,18 +654,19 @@ size_t ZSTD_CCtx_refPrefix_advanced(
565
654
  return 0;
566
655
  }
567
656
 
568
- static void ZSTD_startNewCompression(ZSTD_CCtx* cctx)
657
+ /*! ZSTD_CCtx_reset() :
658
+ * Also dumps dictionary */
659
+ void ZSTD_CCtx_reset(ZSTD_CCtx* cctx)
569
660
  {
570
661
  cctx->streamStage = zcss_init;
571
662
  cctx->pledgedSrcSizePlusOne = 0;
572
663
  }
573
664
 
574
- /*! ZSTD_CCtx_reset() :
575
- * Also dumps dictionary */
576
- void ZSTD_CCtx_reset(ZSTD_CCtx* cctx)
665
+ size_t ZSTD_CCtx_resetParameters(ZSTD_CCtx* cctx)
577
666
  {
578
- ZSTD_startNewCompression(cctx);
667
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
579
668
  cctx->cdict = NULL;
669
+ return ZSTD_CCtxParams_reset(&cctx->requestedParams);
580
670
  }
581
671
 
582
672
  /** ZSTD_checkCParams() :
@@ -589,8 +679,6 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
589
679
  CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
590
680
  CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
591
681
  CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
592
- if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN)
593
- return ERROR(parameter_unsupported);
594
682
  if ((U32)(cParams.strategy) > (U32)ZSTD_btultra)
595
683
  return ERROR(parameter_unsupported);
596
684
  return 0;
@@ -599,7 +687,8 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
599
687
  /** ZSTD_clampCParams() :
600
688
  * make CParam values within valid range.
601
689
  * @return : valid CParams */
602
- static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters cParams)
690
+ static ZSTD_compressionParameters
691
+ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
603
692
  {
604
693
  # define CLAMP(val,min,max) { \
605
694
  if (val<min) val=min; \
@@ -610,8 +699,7 @@ static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters c
610
699
  CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
611
700
  CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
612
701
  CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
613
- if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN) cParams.targetLength = ZSTD_TARGETLENGTH_MIN;
614
- if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) cParams.strategy = ZSTD_btultra;
702
+ CLAMP(cParams.strategy, ZSTD_fast, ZSTD_btultra);
615
703
  return cParams;
616
704
  }
617
705
 
@@ -627,8 +715,11 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
627
715
  optimize `cPar` for a given input (`srcSize` and `dictSize`).
628
716
  mostly downsizing to reduce memory consumption and initialization latency.
629
717
  Both `srcSize` and `dictSize` are optional (use 0 if unknown).
630
- Note : cPar is considered validated at this stage. Use ZSTD_checkCParams() to ensure that condition. */
631
- ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
718
+ Note : cPar is assumed validated. Use ZSTD_checkCParams() to ensure this condition. */
719
+ static ZSTD_compressionParameters
720
+ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
721
+ unsigned long long srcSize,
722
+ size_t dictSize)
632
723
  {
633
724
  static const U64 minSrcSize = 513; /* (1<<9) + 1 */
634
725
  static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
@@ -648,7 +739,7 @@ ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameter
648
739
  ZSTD_highbit32(tSize-1) + 1;
649
740
  if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
650
741
  }
651
- if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog;
742
+ if (cPar.hashLog > cPar.windowLog+1) cPar.hashLog = cPar.windowLog+1;
652
743
  { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
653
744
  if (cycleLog > cPar.windowLog)
654
745
  cPar.chainLog -= (cycleLog - cPar.windowLog);
@@ -660,13 +751,34 @@ ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameter
660
751
  return cPar;
661
752
  }
662
753
 
663
- ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
754
+ ZSTD_compressionParameters
755
+ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
756
+ unsigned long long srcSize,
757
+ size_t dictSize)
664
758
  {
665
759
  cPar = ZSTD_clampCParams(cPar);
666
760
  return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
667
761
  }
668
762
 
669
- static size_t ZSTD_sizeof_matchState(ZSTD_compressionParameters const* cParams, const U32 forCCtx)
763
+ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
764
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
765
+ {
766
+ ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
767
+ if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
768
+ if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
769
+ if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
770
+ if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
771
+ if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
772
+ if (CCtxParams->cParams.searchLength) cParams.searchLength = CCtxParams->cParams.searchLength;
773
+ if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
774
+ if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
775
+ assert(!ZSTD_checkCParams(cParams));
776
+ return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
777
+ }
778
+
779
+ static size_t
780
+ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
781
+ const U32 forCCtx)
670
782
  {
671
783
  size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
672
784
  size_t const hSize = ((size_t)1) << cParams->hashLog;
@@ -752,12 +864,14 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
752
864
  return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
753
865
  }
754
866
 
755
- static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) {
867
+ static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
868
+ {
756
869
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
757
870
  return ZSTD_estimateCStreamSize_usingCParams(cParams);
758
871
  }
759
872
 
760
- size_t ZSTD_estimateCStreamSize(int compressionLevel) {
873
+ size_t ZSTD_estimateCStreamSize(int compressionLevel)
874
+ {
761
875
  int level;
762
876
  size_t memBudget = 0;
763
877
  for (level=1; level<=compressionLevel; level++) {
@@ -851,10 +965,10 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
851
965
  int i;
852
966
  for (i = 0; i < ZSTD_REP_NUM; ++i)
853
967
  bs->rep[i] = repStartValue[i];
854
- bs->entropy.hufCTable_repeatMode = HUF_repeat_none;
855
- bs->entropy.offcode_repeatMode = FSE_repeat_none;
856
- bs->entropy.matchlength_repeatMode = FSE_repeat_none;
857
- bs->entropy.litlength_repeatMode = FSE_repeat_none;
968
+ bs->entropy.huf.repeatMode = HUF_repeat_none;
969
+ bs->entropy.fse.offcode_repeatMode = FSE_repeat_none;
970
+ bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;
971
+ bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;
858
972
  }
859
973
 
860
974
  /*! ZSTD_invalidateMatchState()
@@ -866,8 +980,10 @@ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
866
980
  ZSTD_window_clear(&ms->window);
867
981
 
868
982
  ms->nextToUpdate = ms->window.dictLimit + 1;
983
+ ms->nextToUpdate3 = ms->window.dictLimit + 1;
869
984
  ms->loadedDictEnd = 0;
870
985
  ms->opt.litLengthSum = 0; /* force reset of btopt stats */
986
+ ms->dictMatchState = NULL;
871
987
  }
872
988
 
873
989
  /*! ZSTD_continueCCtx() :
@@ -900,7 +1016,11 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pl
900
1016
 
901
1017
  typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
902
1018
 
903
- static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compressionParameters const* cParams, ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
1019
+ static void*
1020
+ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1021
+ void* ptr,
1022
+ const ZSTD_compressionParameters* cParams,
1023
+ ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
904
1024
  {
905
1025
  size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
906
1026
  size_t const hSize = ((size_t)1) << cParams->hashLog;
@@ -941,10 +1061,18 @@ static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compre
941
1061
  return ptr;
942
1062
  }
943
1063
 
1064
+ #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */
1065
+ #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large
1066
+ * during at least this number of times,
1067
+ * context's memory usage is considered wasteful,
1068
+ * because it's sized to handle a worst case scenario which rarely happens.
1069
+ * In which case, resize it down to free some memory */
1070
+
944
1071
  /*! ZSTD_resetCCtx_internal() :
945
1072
  note : `params` are assumed fully validated at this stage */
946
1073
  static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
947
- ZSTD_CCtx_params params, U64 pledgedSrcSize,
1074
+ ZSTD_CCtx_params params,
1075
+ U64 pledgedSrcSize,
948
1076
  ZSTD_compResetPolicy_e const crp,
949
1077
  ZSTD_buffered_policy_e const zbuff)
950
1078
  {
@@ -956,20 +1084,20 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
956
1084
  if (ZSTD_equivalentParams(zc->appliedParams, params,
957
1085
  zc->inBuffSize, zc->blockSize,
958
1086
  zbuff, pledgedSrcSize)) {
959
- DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%u)",
960
- zc->appliedParams.cParams.windowLog, (U32)zc->blockSize);
961
- return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
1087
+ DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
1088
+ zc->appliedParams.cParams.windowLog, zc->blockSize);
1089
+ zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
1090
+ if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
1091
+ return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
962
1092
  } }
963
1093
  DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
964
1094
 
965
1095
  if (params.ldmParams.enableLdm) {
966
1096
  /* Adjust long distance matching parameters */
967
- params.ldmParams.windowLog = params.cParams.windowLog;
968
1097
  ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
969
1098
  assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
970
1099
  assert(params.ldmParams.hashEveryLog < 32);
971
- zc->ldmState.hashPower =
972
- ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
1100
+ zc->ldmState.hashPower = ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
973
1101
  }
974
1102
 
975
1103
  { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
@@ -981,7 +1109,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
981
1109
  size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
982
1110
  size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
983
1111
  size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
984
- void* ptr;
1112
+ void* ptr; /* used to partition workSpace */
985
1113
 
986
1114
  /* Check if workSpace is large enough, alloc a new one if needed */
987
1115
  { size_t const entropySpace = HUF_WORKSPACE_SIZE;
@@ -993,14 +1121,20 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
993
1121
  size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
994
1122
  ldmSeqSpace + matchStateSize + tokenSpace +
995
1123
  bufferSpace;
996
- DEBUGLOG(4, "Need %uKB workspace, including %uKB for match state, and %uKB for buffers",
997
- (U32)(neededSpace>>10), (U32)(matchStateSize>>10), (U32)(bufferSpace>>10));
998
- DEBUGLOG(4, "windowSize: %u - blockSize: %u", (U32)windowSize, (U32)blockSize);
999
-
1000
- if (zc->workSpaceSize < neededSpace) { /* too small : resize */
1001
- DEBUGLOG(4, "Need to update workSpaceSize from %uK to %uK",
1002
- (unsigned)(zc->workSpaceSize>>10),
1003
- (unsigned)(neededSpace>>10));
1124
+
1125
+ int const workSpaceTooSmall = zc->workSpaceSize < neededSpace;
1126
+ int const workSpaceTooLarge = zc->workSpaceSize > ZSTD_WORKSPACETOOLARGE_FACTOR * neededSpace;
1127
+ int const workSpaceWasteful = workSpaceTooLarge && (zc->workSpaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION);
1128
+ zc->workSpaceOversizedDuration = workSpaceTooLarge ? zc->workSpaceOversizedDuration+1 : 0;
1129
+
1130
+ DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
1131
+ neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
1132
+ DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
1133
+
1134
+ if (workSpaceTooSmall || workSpaceWasteful) {
1135
+ DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB",
1136
+ zc->workSpaceSize >> 10,
1137
+ neededSpace >> 10);
1004
1138
  /* static cctx : no resize, error out */
1005
1139
  if (zc->staticSize) return ERROR(memory_allocation);
1006
1140
 
@@ -1009,9 +1143,12 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1009
1143
  zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
1010
1144
  if (zc->workSpace == NULL) return ERROR(memory_allocation);
1011
1145
  zc->workSpaceSize = neededSpace;
1146
+ zc->workSpaceOversizedDuration = 0;
1012
1147
  ptr = zc->workSpace;
1013
1148
 
1014
- /* Statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
1149
+ /* Statically sized space.
1150
+ * entropyWorkspace never moves,
1151
+ * though prev/next block swap places */
1015
1152
  assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */
1016
1153
  assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t));
1017
1154
  zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace;
@@ -1100,48 +1237,98 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
1100
1237
 
1101
1238
  static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1102
1239
  const ZSTD_CDict* cdict,
1103
- unsigned windowLog,
1104
- ZSTD_frameParameters fParams,
1240
+ ZSTD_CCtx_params params,
1105
1241
  U64 pledgedSrcSize,
1106
1242
  ZSTD_buffered_policy_e zbuff)
1107
1243
  {
1108
- { ZSTD_CCtx_params params = cctx->requestedParams;
1244
+ /* We have a choice between copying the dictionary context into the working
1245
+ * context, or referencing the dictionary context from the working context
1246
+ * in-place. We decide here which strategy to use. */
1247
+ const U64 attachDictSizeCutoffs[(unsigned)ZSTD_btultra+1] = {
1248
+ 8 KB, /* unused */
1249
+ 8 KB, /* ZSTD_fast */
1250
+ 16 KB, /* ZSTD_dfast */
1251
+ 32 KB, /* ZSTD_greedy */
1252
+ 32 KB, /* ZSTD_lazy */
1253
+ 32 KB, /* ZSTD_lazy2 */
1254
+ 32 KB, /* ZSTD_btlazy2 */
1255
+ 32 KB, /* ZSTD_btopt */
1256
+ 8 KB /* ZSTD_btultra */
1257
+ };
1258
+ const int attachDict = ( pledgedSrcSize <= attachDictSizeCutoffs[cdict->cParams.strategy]
1259
+ || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
1260
+ || params.attachDictPref == ZSTD_dictForceAttach )
1261
+ && params.attachDictPref != ZSTD_dictForceCopy
1262
+ && !params.forceWindow /* dictMatchState isn't correctly
1263
+ * handled in _enforceMaxDist */
1264
+ && ZSTD_equivalentCParams(cctx->appliedParams.cParams,
1265
+ cdict->cParams);
1266
+
1267
+ DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
1268
+
1269
+
1270
+ { unsigned const windowLog = params.cParams.windowLog;
1271
+ assert(windowLog != 0);
1109
1272
  /* Copy only compression parameters related to tables. */
1110
1273
  params.cParams = cdict->cParams;
1111
- if (windowLog) params.cParams.windowLog = windowLog;
1112
- params.fParams = fParams;
1274
+ params.cParams.windowLog = windowLog;
1113
1275
  ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1114
- ZSTDcrp_noMemset, zbuff);
1276
+ attachDict ? ZSTDcrp_continue : ZSTDcrp_noMemset,
1277
+ zbuff);
1115
1278
  assert(cctx->appliedParams.cParams.strategy == cdict->cParams.strategy);
1116
1279
  assert(cctx->appliedParams.cParams.hashLog == cdict->cParams.hashLog);
1117
1280
  assert(cctx->appliedParams.cParams.chainLog == cdict->cParams.chainLog);
1118
1281
  }
1119
1282
 
1120
- /* copy tables */
1121
- { size_t const chainSize = (cdict->cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict->cParams.chainLog);
1122
- size_t const hSize = (size_t)1 << cdict->cParams.hashLog;
1123
- size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
1124
- assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1125
- assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
1126
- assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
1127
- assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
1128
- memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1129
- }
1130
- /* Zero the hashTable3, since the cdict never fills it */
1131
- { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
1132
- assert(cdict->matchState.hashLog3 == 0);
1133
- memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1134
- }
1283
+ if (attachDict) {
1284
+ const U32 cdictLen = (U32)( cdict->matchState.window.nextSrc
1285
+ - cdict->matchState.window.base);
1286
+ if (cdictLen == 0) {
1287
+ /* don't even attach dictionaries with no contents */
1288
+ DEBUGLOG(4, "skipping attaching empty dictionary");
1289
+ } else {
1290
+ DEBUGLOG(4, "attaching dictionary into context");
1291
+ cctx->blockState.matchState.dictMatchState = &cdict->matchState;
1292
+
1293
+ /* prep working match state so dict matches never have negative indices
1294
+ * when they are translated to the working context's index space. */
1295
+ if (cctx->blockState.matchState.window.dictLimit < cdictLen) {
1296
+ cctx->blockState.matchState.window.nextSrc =
1297
+ cctx->blockState.matchState.window.base + cdictLen;
1298
+ ZSTD_window_clear(&cctx->blockState.matchState.window);
1299
+ }
1300
+ cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
1301
+ }
1302
+ } else {
1303
+ DEBUGLOG(4, "copying dictionary into context");
1304
+ /* copy tables */
1305
+ { size_t const chainSize = (cdict->cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict->cParams.chainLog);
1306
+ size_t const hSize = (size_t)1 << cdict->cParams.hashLog;
1307
+ size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
1308
+ assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1309
+ assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
1310
+ assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
1311
+ assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
1312
+ memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1313
+ }
1135
1314
 
1136
- /* copy dictionary offsets */
1137
- {
1138
- ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1139
- ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1140
- dstMatchState->window = srcMatchState->window;
1141
- dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1142
- dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1143
- dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1315
+ /* Zero the hashTable3, since the cdict never fills it */
1316
+ { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
1317
+ assert(cdict->matchState.hashLog3 == 0);
1318
+ memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1319
+ }
1320
+
1321
+ /* copy dictionary offsets */
1322
+ {
1323
+ ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1324
+ ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1325
+ dstMatchState->window = srcMatchState->window;
1326
+ dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1327
+ dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1328
+ dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1329
+ }
1144
1330
  }
1331
+
1145
1332
  cctx->dictID = cdict->dictID;
1146
1333
 
1147
1334
  /* copy block state */
@@ -1192,7 +1379,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1192
1379
 
1193
1380
  /* copy dictionary offsets */
1194
1381
  {
1195
- ZSTD_matchState_t const* srcMatchState = &srcCCtx->blockState.matchState;
1382
+ const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
1196
1383
  ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
1197
1384
  dstMatchState->window = srcMatchState->window;
1198
1385
  dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
@@ -1356,16 +1543,24 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
1356
1543
  }
1357
1544
 
1358
1545
 
1359
- static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
1546
+ /* ZSTD_minGain() :
1547
+ * minimum compression required
1548
+ * to generate a compress block or a compressed literals section.
1549
+ * note : use same formula for both situations */
1550
+ static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
1551
+ {
1552
+ U32 const minlog = (strat==ZSTD_btultra) ? 7 : 6;
1553
+ return (srcSize >> minlog) + 2;
1554
+ }
1360
1555
 
1361
- static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
1362
- ZSTD_entropyCTables_t* nextEntropy,
1556
+ static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
1557
+ ZSTD_hufCTables_t* nextHuf,
1363
1558
  ZSTD_strategy strategy, int disableLiteralCompression,
1364
1559
  void* dst, size_t dstCapacity,
1365
1560
  const void* src, size_t srcSize,
1366
1561
  U32* workspace, const int bmi2)
1367
1562
  {
1368
- size_t const minGain = ZSTD_minGain(srcSize);
1563
+ size_t const minGain = ZSTD_minGain(srcSize, strategy);
1369
1564
  size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
1370
1565
  BYTE* const ostart = (BYTE*)dst;
1371
1566
  U32 singleStream = srcSize < 256;
@@ -1376,27 +1571,25 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
1376
1571
  disableLiteralCompression);
1377
1572
 
1378
1573
  /* Prepare nextEntropy assuming reusing the existing table */
1379
- nextEntropy->hufCTable_repeatMode = prevEntropy->hufCTable_repeatMode;
1380
- memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable,
1381
- sizeof(prevEntropy->hufCTable));
1574
+ memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1382
1575
 
1383
1576
  if (disableLiteralCompression)
1384
1577
  return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1385
1578
 
1386
1579
  /* small ? don't even attempt compression (speed opt) */
1387
1580
  # define COMPRESS_LITERALS_SIZE_MIN 63
1388
- { size_t const minLitSize = (prevEntropy->hufCTable_repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
1581
+ { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
1389
1582
  if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1390
1583
  }
1391
1584
 
1392
1585
  if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
1393
- { HUF_repeat repeat = prevEntropy->hufCTable_repeatMode;
1586
+ { HUF_repeat repeat = prevHuf->repeatMode;
1394
1587
  int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
1395
1588
  if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
1396
1589
  cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1397
- workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2)
1590
+ workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
1398
1591
  : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1399
- workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2);
1592
+ workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
1400
1593
  if (repeat != HUF_repeat_none) {
1401
1594
  /* reused the existing table */
1402
1595
  hType = set_repeat;
@@ -1404,17 +1597,17 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
1404
1597
  }
1405
1598
 
1406
1599
  if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
1407
- memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
1600
+ memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1408
1601
  return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1409
1602
  }
1410
1603
  if (cLitSize==1) {
1411
- memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
1604
+ memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1412
1605
  return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
1413
1606
  }
1414
1607
 
1415
1608
  if (hType == set_compressed) {
1416
1609
  /* using a newly constructed table */
1417
- nextEntropy->hufCTable_repeatMode = HUF_repeat_check;
1610
+ nextHuf->repeatMode = HUF_repeat_check;
1418
1611
  }
1419
1612
 
1420
1613
  /* Build header */
@@ -1464,61 +1657,234 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1464
1657
  mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
1465
1658
  }
1466
1659
 
1660
+
1661
+ /**
1662
+ * -log2(x / 256) lookup table for x in [0, 256).
1663
+ * If x == 0: Return 0
1664
+ * Else: Return floor(-log2(x / 256) * 256)
1665
+ */
1666
+ static unsigned const kInverseProbabiltyLog256[256] = {
1667
+ 0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
1668
+ 1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
1669
+ 874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
1670
+ 724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
1671
+ 618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
1672
+ 535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
1673
+ 468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
1674
+ 411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
1675
+ 362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
1676
+ 318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
1677
+ 279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
1678
+ 244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
1679
+ 212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
1680
+ 182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
1681
+ 155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
1682
+ 130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
1683
+ 106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
1684
+ 83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
1685
+ 62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
1686
+ 42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
1687
+ 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
1688
+ 5, 4, 2, 1,
1689
+ };
1690
+
1691
+
1692
+ /**
1693
+ * Returns the cost in bits of encoding the distribution described by count
1694
+ * using the entropy bound.
1695
+ */
1696
+ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
1697
+ {
1698
+ unsigned cost = 0;
1699
+ unsigned s;
1700
+ for (s = 0; s <= max; ++s) {
1701
+ unsigned norm = (unsigned)((256 * count[s]) / total);
1702
+ if (count[s] != 0 && norm == 0)
1703
+ norm = 1;
1704
+ assert(count[s] < total);
1705
+ cost += count[s] * kInverseProbabiltyLog256[norm];
1706
+ }
1707
+ return cost >> 8;
1708
+ }
1709
+
1710
+
1711
+ /**
1712
+ * Returns the cost in bits of encoding the distribution in count using the
1713
+ * table described by norm. The max symbol support by norm is assumed >= max.
1714
+ * norm must be valid for every symbol with non-zero probability in count.
1715
+ */
1716
+ static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
1717
+ unsigned const* count, unsigned const max)
1718
+ {
1719
+ unsigned const shift = 8 - accuracyLog;
1720
+ size_t cost = 0;
1721
+ unsigned s;
1722
+ assert(accuracyLog <= 8);
1723
+ for (s = 0; s <= max; ++s) {
1724
+ unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
1725
+ unsigned const norm256 = normAcc << shift;
1726
+ assert(norm256 > 0);
1727
+ assert(norm256 < 256);
1728
+ cost += count[s] * kInverseProbabiltyLog256[norm256];
1729
+ }
1730
+ return cost >> 8;
1731
+ }
1732
+
1733
+
1734
+ static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
1735
+ void const* ptr = ctable;
1736
+ U16 const* u16ptr = (U16 const*)ptr;
1737
+ U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
1738
+ return maxSymbolValue;
1739
+ }
1740
+
1741
+
1742
+ /**
1743
+ * Returns the cost in bits of encoding the distribution in count using ctable.
1744
+ * Returns an error if ctable cannot represent all the symbols in count.
1745
+ */
1746
+ static size_t ZSTD_fseBitCost(
1747
+ FSE_CTable const* ctable,
1748
+ unsigned const* count,
1749
+ unsigned const max)
1750
+ {
1751
+ unsigned const kAccuracyLog = 8;
1752
+ size_t cost = 0;
1753
+ unsigned s;
1754
+ FSE_CState_t cstate;
1755
+ FSE_initCState(&cstate, ctable);
1756
+ if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {
1757
+ DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u",
1758
+ ZSTD_getFSEMaxSymbolValue(ctable), max);
1759
+ return ERROR(GENERIC);
1760
+ }
1761
+ for (s = 0; s <= max; ++s) {
1762
+ unsigned const tableLog = cstate.stateLog;
1763
+ unsigned const badCost = (tableLog + 1) << kAccuracyLog;
1764
+ unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
1765
+ if (count[s] == 0)
1766
+ continue;
1767
+ if (bitCost >= badCost) {
1768
+ DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s);
1769
+ return ERROR(GENERIC);
1770
+ }
1771
+ cost += count[s] * bitCost;
1772
+ }
1773
+ return cost >> kAccuracyLog;
1774
+ }
1775
+
1776
+ /**
1777
+ * Returns the cost in bytes of encoding the normalized count header.
1778
+ * Returns an error if any of the helper functions return an error.
1779
+ */
1780
+ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
1781
+ size_t const nbSeq, unsigned const FSELog)
1782
+ {
1783
+ BYTE wksp[FSE_NCOUNTBOUND];
1784
+ S16 norm[MaxSeq + 1];
1785
+ const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
1786
+ CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
1787
+ return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
1788
+ }
1789
+
1790
+
1467
1791
  typedef enum {
1468
1792
  ZSTD_defaultDisallowed = 0,
1469
1793
  ZSTD_defaultAllowed = 1
1470
1794
  } ZSTD_defaultPolicy_e;
1471
1795
 
1472
- MEM_STATIC
1473
- symbolEncodingType_e ZSTD_selectEncodingType(
1474
- FSE_repeat* repeatMode, size_t const mostFrequent, size_t nbSeq,
1475
- U32 defaultNormLog, ZSTD_defaultPolicy_e const isDefaultAllowed)
1796
+ MEM_STATIC symbolEncodingType_e
1797
+ ZSTD_selectEncodingType(
1798
+ FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
1799
+ size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
1800
+ FSE_CTable const* prevCTable,
1801
+ short const* defaultNorm, U32 defaultNormLog,
1802
+ ZSTD_defaultPolicy_e const isDefaultAllowed,
1803
+ ZSTD_strategy const strategy)
1476
1804
  {
1477
- #define MIN_SEQ_FOR_DYNAMIC_FSE 64
1478
- #define MAX_SEQ_FOR_STATIC_FSE 1000
1479
1805
  ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
1480
- if ((mostFrequent == nbSeq) && (!isDefaultAllowed || nbSeq > 2)) {
1806
+ if (mostFrequent == nbSeq) {
1807
+ *repeatMode = FSE_repeat_none;
1808
+ if (isDefaultAllowed && nbSeq <= 2) {
1809
+ /* Prefer set_basic over set_rle when there are 2 or less symbols,
1810
+ * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
1811
+ * If basic encoding isn't possible, always choose RLE.
1812
+ */
1813
+ DEBUGLOG(5, "Selected set_basic");
1814
+ return set_basic;
1815
+ }
1481
1816
  DEBUGLOG(5, "Selected set_rle");
1482
- /* Prefer set_basic over set_rle when there are 2 or less symbols,
1483
- * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
1484
- * If basic encoding isn't possible, always choose RLE.
1485
- */
1486
- *repeatMode = FSE_repeat_check;
1487
1817
  return set_rle;
1488
1818
  }
1489
- if ( isDefaultAllowed
1490
- && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
1491
- DEBUGLOG(5, "Selected set_repeat");
1492
- return set_repeat;
1493
- }
1494
- if ( isDefaultAllowed
1495
- && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1)))) ) {
1496
- DEBUGLOG(5, "Selected set_basic");
1497
- /* The format allows default tables to be repeated, but it isn't useful.
1498
- * When using simple heuristics to select encoding type, we don't want
1499
- * to confuse these tables with dictionaries. When running more careful
1500
- * analysis, we don't need to waste time checking both repeating tables
1501
- * and default tables.
1502
- */
1503
- *repeatMode = FSE_repeat_none;
1504
- return set_basic;
1819
+ if (strategy < ZSTD_lazy) {
1820
+ if (isDefaultAllowed) {
1821
+ size_t const staticFse_nbSeq_max = 1000;
1822
+ size_t const mult = 10 - strategy;
1823
+ size_t const baseLog = 3;
1824
+ size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
1825
+ assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
1826
+ assert(mult <= 9 && mult >= 7);
1827
+ if ( (*repeatMode == FSE_repeat_valid)
1828
+ && (nbSeq < staticFse_nbSeq_max) ) {
1829
+ DEBUGLOG(5, "Selected set_repeat");
1830
+ return set_repeat;
1831
+ }
1832
+ if ( (nbSeq < dynamicFse_nbSeq_min)
1833
+ || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
1834
+ DEBUGLOG(5, "Selected set_basic");
1835
+ /* The format allows default tables to be repeated, but it isn't useful.
1836
+ * When using simple heuristics to select encoding type, we don't want
1837
+ * to confuse these tables with dictionaries. When running more careful
1838
+ * analysis, we don't need to waste time checking both repeating tables
1839
+ * and default tables.
1840
+ */
1841
+ *repeatMode = FSE_repeat_none;
1842
+ return set_basic;
1843
+ }
1844
+ }
1845
+ } else {
1846
+ size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
1847
+ size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
1848
+ size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
1849
+ size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
1850
+
1851
+ if (isDefaultAllowed) {
1852
+ assert(!ZSTD_isError(basicCost));
1853
+ assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
1854
+ }
1855
+ assert(!ZSTD_isError(NCountCost));
1856
+ assert(compressedCost < ERROR(maxCode));
1857
+ DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
1858
+ (U32)basicCost, (U32)repeatCost, (U32)compressedCost);
1859
+ if (basicCost <= repeatCost && basicCost <= compressedCost) {
1860
+ DEBUGLOG(5, "Selected set_basic");
1861
+ assert(isDefaultAllowed);
1862
+ *repeatMode = FSE_repeat_none;
1863
+ return set_basic;
1864
+ }
1865
+ if (repeatCost <= compressedCost) {
1866
+ DEBUGLOG(5, "Selected set_repeat");
1867
+ assert(!ZSTD_isError(repeatCost));
1868
+ return set_repeat;
1869
+ }
1870
+ assert(compressedCost < basicCost && compressedCost < repeatCost);
1505
1871
  }
1506
1872
  DEBUGLOG(5, "Selected set_compressed");
1507
1873
  *repeatMode = FSE_repeat_check;
1508
1874
  return set_compressed;
1509
1875
  }
1510
1876
 
1511
- MEM_STATIC
1512
- size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1513
- FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
1514
- U32* count, U32 max,
1515
- BYTE const* codeTable, size_t nbSeq,
1516
- S16 const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
1517
- FSE_CTable const* prevCTable, size_t prevCTableSize,
1518
- void* workspace, size_t workspaceSize)
1877
+ MEM_STATIC size_t
1878
+ ZSTD_buildCTable(void* dst, size_t dstCapacity,
1879
+ FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
1880
+ U32* count, U32 max,
1881
+ const BYTE* codeTable, size_t nbSeq,
1882
+ const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
1883
+ const FSE_CTable* prevCTable, size_t prevCTableSize,
1884
+ void* workspace, size_t workspaceSize)
1519
1885
  {
1520
1886
  BYTE* op = (BYTE*)dst;
1521
- BYTE const* const oend = op + dstCapacity;
1887
+ const BYTE* const oend = op + dstCapacity;
1522
1888
 
1523
1889
  switch (type) {
1524
1890
  case set_rle:
@@ -1706,10 +2072,11 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1706
2072
  const int bmi2)
1707
2073
  {
1708
2074
  const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
2075
+ ZSTD_strategy const strategy = cctxParams->cParams.strategy;
1709
2076
  U32 count[MaxSeq+1];
1710
- FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
1711
- FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
1712
- FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
2077
+ FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
2078
+ FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
2079
+ FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
1713
2080
  U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
1714
2081
  const seqDef* const sequences = seqStorePtr->sequencesStart;
1715
2082
  const BYTE* const ofCodeTable = seqStorePtr->ofCode;
@@ -1720,15 +2087,17 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1720
2087
  BYTE* op = ostart;
1721
2088
  size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
1722
2089
  BYTE* seqHead;
2090
+ BYTE* lastNCount = NULL;
1723
2091
 
1724
2092
  ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
1725
2093
 
1726
2094
  /* Compress literals */
1727
2095
  { const BYTE* const literals = seqStorePtr->litStart;
1728
2096
  size_t const litSize = seqStorePtr->lit - literals;
2097
+ int const disableLiteralCompression = (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
1729
2098
  size_t const cSize = ZSTD_compressLiterals(
1730
- prevEntropy, nextEntropy,
1731
- cctxParams->cParams.strategy, cctxParams->disableLiteralCompression,
2099
+ &prevEntropy->huf, &nextEntropy->huf,
2100
+ cctxParams->cParams.strategy, disableLiteralCompression,
1732
2101
  op, dstCapacity,
1733
2102
  literals, litSize,
1734
2103
  workspace, bmi2);
@@ -1747,13 +2116,9 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1747
2116
  else
1748
2117
  op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1749
2118
  if (nbSeq==0) {
1750
- memcpy(nextEntropy->litlengthCTable, prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable));
1751
- nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
1752
- memcpy(nextEntropy->offcodeCTable, prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable));
1753
- nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
1754
- memcpy(nextEntropy->matchlengthCTable, prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable));
1755
- nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
1756
- return op - ostart;
2119
+ /* Copy the old tables over as if we repeated them */
2120
+ memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
2121
+ return op - ostart;
1757
2122
  }
1758
2123
 
1759
2124
  /* seqHead : flags for FSE encoding type */
@@ -1763,43 +2128,53 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1763
2128
  ZSTD_seqToCodes(seqStorePtr);
1764
2129
  /* build CTable for Literal Lengths */
1765
2130
  { U32 max = MaxLL;
1766
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace);
2131
+ size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace); /* can't fail */
1767
2132
  DEBUGLOG(5, "Building LL table");
1768
- nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
1769
- LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
2133
+ nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
2134
+ LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode, count, max, mostFrequent, nbSeq, LLFSELog, prevEntropy->fse.litlengthCTable, LL_defaultNorm, LL_defaultNormLog, ZSTD_defaultAllowed, strategy);
2135
+ assert(set_basic < set_compressed && set_rle < set_compressed);
2136
+ assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
1770
2137
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
1771
- count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
1772
- prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
1773
- workspace, HUF_WORKSPACE_SIZE);
2138
+ count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
2139
+ prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
2140
+ workspace, HUF_WORKSPACE_SIZE);
1774
2141
  if (ZSTD_isError(countSize)) return countSize;
2142
+ if (LLtype == set_compressed)
2143
+ lastNCount = op;
1775
2144
  op += countSize;
1776
2145
  } }
1777
2146
  /* build CTable for Offsets */
1778
2147
  { U32 max = MaxOff;
1779
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace);
2148
+ size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace); /* can't fail */
1780
2149
  /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
1781
2150
  ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
1782
2151
  DEBUGLOG(5, "Building OF table");
1783
- nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
1784
- Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
2152
+ nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode;
2153
+ Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode, count, max, mostFrequent, nbSeq, OffFSELog, prevEntropy->fse.offcodeCTable, OF_defaultNorm, OF_defaultNormLog, defaultPolicy, strategy);
2154
+ assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
1785
2155
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
1786
- count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
1787
- prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
1788
- workspace, HUF_WORKSPACE_SIZE);
2156
+ count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
2157
+ prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
2158
+ workspace, HUF_WORKSPACE_SIZE);
1789
2159
  if (ZSTD_isError(countSize)) return countSize;
2160
+ if (Offtype == set_compressed)
2161
+ lastNCount = op;
1790
2162
  op += countSize;
1791
2163
  } }
1792
2164
  /* build CTable for MatchLengths */
1793
2165
  { U32 max = MaxML;
1794
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace);
2166
+ size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace); /* can't fail */
1795
2167
  DEBUGLOG(5, "Building ML table");
1796
- nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
1797
- MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
2168
+ nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
2169
+ MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode, count, max, mostFrequent, nbSeq, MLFSELog, prevEntropy->fse.matchlengthCTable, ML_defaultNorm, ML_defaultNormLog, ZSTD_defaultAllowed, strategy);
2170
+ assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
1798
2171
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
1799
- count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
1800
- prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
1801
- workspace, HUF_WORKSPACE_SIZE);
2172
+ count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
2173
+ prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
2174
+ workspace, HUF_WORKSPACE_SIZE);
1802
2175
  if (ZSTD_isError(countSize)) return countSize;
2176
+ if (MLtype == set_compressed)
2177
+ lastNCount = op;
1803
2178
  op += countSize;
1804
2179
  } }
1805
2180
 
@@ -1814,21 +2189,37 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1814
2189
  longOffsets, bmi2);
1815
2190
  if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
1816
2191
  op += bitstreamSize;
2192
+ /* zstd versions <= 1.3.4 mistakenly report corruption when
2193
+ * FSE_readNCount() recieves a buffer < 4 bytes.
2194
+ * Fixed by https://github.com/facebook/zstd/pull/1146.
2195
+ * This can happen when the last set_compressed table present is 2
2196
+ * bytes and the bitstream is only one byte.
2197
+ * In this exceedingly rare case, we will simply emit an uncompressed
2198
+ * block, since it isn't worth optimizing.
2199
+ */
2200
+ if (lastNCount && (op - lastNCount) < 4) {
2201
+ /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
2202
+ assert(op - lastNCount == 3);
2203
+ DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
2204
+ "emitting an uncompressed block.");
2205
+ return 0;
2206
+ }
1817
2207
  }
1818
2208
 
1819
2209
  return op - ostart;
1820
2210
  }
1821
2211
 
1822
2212
  MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1823
- ZSTD_entropyCTables_t const* prevEntropy,
2213
+ const ZSTD_entropyCTables_t* prevEntropy,
1824
2214
  ZSTD_entropyCTables_t* nextEntropy,
1825
- ZSTD_CCtx_params const* cctxParams,
2215
+ const ZSTD_CCtx_params* cctxParams,
1826
2216
  void* dst, size_t dstCapacity,
1827
2217
  size_t srcSize, U32* workspace, int bmi2)
1828
2218
  {
1829
2219
  size_t const cSize = ZSTD_compressSequences_internal(
1830
2220
  seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity,
1831
2221
  workspace, bmi2);
2222
+ if (cSize == 0) return 0;
1832
2223
  /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
1833
2224
  * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
1834
2225
  */
@@ -1837,7 +2228,7 @@ MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1837
2228
  if (ZSTD_isError(cSize)) return cSize;
1838
2229
 
1839
2230
  /* Check compressibility */
1840
- { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize); /* note : fixed formula, maybe should depend on compression level, or strategy */
2231
+ { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
1841
2232
  if (cSize >= maxCSize) return 0; /* block not compressed */
1842
2233
  }
1843
2234
 
@@ -1845,8 +2236,8 @@ MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1845
2236
  * block. After the first block, the offcode table might not have large
1846
2237
  * enough codes to represent the offsets in the data.
1847
2238
  */
1848
- if (nextEntropy->offcode_repeatMode == FSE_repeat_valid)
1849
- nextEntropy->offcode_repeatMode = FSE_repeat_check;
2239
+ if (nextEntropy->fse.offcode_repeatMode == FSE_repeat_valid)
2240
+ nextEntropy->fse.offcode_repeatMode = FSE_repeat_check;
1850
2241
 
1851
2242
  return cSize;
1852
2243
  }
@@ -1854,23 +2245,45 @@ MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1854
2245
  /* ZSTD_selectBlockCompressor() :
1855
2246
  * Not static, but internal use only (used by long distance matcher)
1856
2247
  * assumption : strat is a valid strategy */
1857
- ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
2248
+ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode)
1858
2249
  {
1859
- static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
2250
+ static const ZSTD_blockCompressor blockCompressor[3][(unsigned)ZSTD_btultra+1] = {
1860
2251
  { ZSTD_compressBlock_fast /* default for 0 */,
1861
- ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
1862
- ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2,
1863
- ZSTD_compressBlock_btopt, ZSTD_compressBlock_btultra },
2252
+ ZSTD_compressBlock_fast,
2253
+ ZSTD_compressBlock_doubleFast,
2254
+ ZSTD_compressBlock_greedy,
2255
+ ZSTD_compressBlock_lazy,
2256
+ ZSTD_compressBlock_lazy2,
2257
+ ZSTD_compressBlock_btlazy2,
2258
+ ZSTD_compressBlock_btopt,
2259
+ ZSTD_compressBlock_btultra },
1864
2260
  { ZSTD_compressBlock_fast_extDict /* default for 0 */,
1865
- ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict,
1866
- ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict,
1867
- ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btultra_extDict }
2261
+ ZSTD_compressBlock_fast_extDict,
2262
+ ZSTD_compressBlock_doubleFast_extDict,
2263
+ ZSTD_compressBlock_greedy_extDict,
2264
+ ZSTD_compressBlock_lazy_extDict,
2265
+ ZSTD_compressBlock_lazy2_extDict,
2266
+ ZSTD_compressBlock_btlazy2_extDict,
2267
+ ZSTD_compressBlock_btopt_extDict,
2268
+ ZSTD_compressBlock_btultra_extDict },
2269
+ { ZSTD_compressBlock_fast_dictMatchState /* default for 0 */,
2270
+ ZSTD_compressBlock_fast_dictMatchState,
2271
+ ZSTD_compressBlock_doubleFast_dictMatchState,
2272
+ ZSTD_compressBlock_greedy_dictMatchState,
2273
+ ZSTD_compressBlock_lazy_dictMatchState,
2274
+ ZSTD_compressBlock_lazy2_dictMatchState,
2275
+ ZSTD_compressBlock_btlazy2_dictMatchState,
2276
+ ZSTD_compressBlock_btopt_dictMatchState,
2277
+ ZSTD_compressBlock_btultra_dictMatchState }
1868
2278
  };
2279
+ ZSTD_blockCompressor selectedCompressor;
1869
2280
  ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
1870
2281
 
1871
2282
  assert((U32)strat >= (U32)ZSTD_fast);
1872
2283
  assert((U32)strat <= (U32)ZSTD_btultra);
1873
- return blockCompressor[extDict!=0][(U32)strat];
2284
+ selectedCompressor = blockCompressor[(int)dictMode][(U32)strat];
2285
+ assert(selectedCompressor != NULL);
2286
+ return selectedCompressor;
1874
2287
  }
1875
2288
 
1876
2289
  static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
@@ -1880,7 +2293,7 @@ static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
1880
2293
  seqStorePtr->lit += lastLLSize;
1881
2294
  }
1882
2295
 
1883
- static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
2296
+ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
1884
2297
  {
1885
2298
  ssPtr->lit = ssPtr->litStart;
1886
2299
  ssPtr->sequences = ssPtr->sequencesStart;
@@ -1892,24 +2305,32 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
1892
2305
  const void* src, size_t srcSize)
1893
2306
  {
1894
2307
  ZSTD_matchState_t* const ms = &zc->blockState.matchState;
1895
- DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
1896
- (U32)dstCapacity, ms->window.dictLimit, ms->nextToUpdate);
2308
+ DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%zu, dictLimit=%u, nextToUpdate=%u)",
2309
+ dstCapacity, ms->window.dictLimit, ms->nextToUpdate);
2310
+
1897
2311
  if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
1898
2312
  ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.searchLength);
1899
2313
  return 0; /* don't even attempt compression below a certain srcSize */
1900
2314
  }
1901
2315
  ZSTD_resetSeqStore(&(zc->seqStore));
2316
+ ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* required for optimal parser to read stats from dictionary */
2317
+
2318
+ /* a gap between an attached dict and the current window is not safe,
2319
+ * they must remain adjacent, and when that stops being the case, the dict
2320
+ * must be unset */
2321
+ assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);
1902
2322
 
1903
2323
  /* limited update after a very long match */
1904
2324
  { const BYTE* const base = ms->window.base;
1905
2325
  const BYTE* const istart = (const BYTE*)src;
1906
2326
  const U32 current = (U32)(istart-base);
2327
+ if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */
1907
2328
  if (current > ms->nextToUpdate + 384)
1908
2329
  ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384));
1909
2330
  }
1910
2331
 
1911
2332
  /* select and store sequences */
1912
- { U32 const extDict = ZSTD_window_hasExtDict(ms->window);
2333
+ { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
1913
2334
  size_t lastLLSize;
1914
2335
  { int i;
1915
2336
  for (i = 0; i < ZSTD_REP_NUM; ++i)
@@ -1923,7 +2344,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
1923
2344
  ms, &zc->seqStore,
1924
2345
  zc->blockState.nextCBlock->rep,
1925
2346
  &zc->appliedParams.cParams,
1926
- src, srcSize, extDict);
2347
+ src, srcSize);
1927
2348
  assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
1928
2349
  } else if (zc->appliedParams.ldmParams.enableLdm) {
1929
2350
  rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
@@ -1940,10 +2361,10 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
1940
2361
  ms, &zc->seqStore,
1941
2362
  zc->blockState.nextCBlock->rep,
1942
2363
  &zc->appliedParams.cParams,
1943
- src, srcSize, extDict);
2364
+ src, srcSize);
1944
2365
  assert(ldmSeqStore.pos == ldmSeqStore.size);
1945
2366
  } else { /* not long range mode */
1946
- ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
2367
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
1947
2368
  lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, &zc->appliedParams.cParams, src, srcSize);
1948
2369
  }
1949
2370
  { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
@@ -2010,8 +2431,9 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2010
2431
  if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2011
2432
  else ms->nextToUpdate -= correction;
2012
2433
  ms->loadedDictEnd = 0;
2434
+ ms->dictMatchState = NULL;
2013
2435
  }
2014
- ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd);
2436
+ ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2015
2437
  if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
2016
2438
 
2017
2439
  { size_t cSize = ZSTD_compressBlock_internal(cctx,
@@ -2060,6 +2482,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2060
2482
  BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2061
2483
  size_t pos=0;
2062
2484
 
2485
+ assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
2063
2486
  if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
2064
2487
  DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2065
2488
  !params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
@@ -2153,7 +2576,9 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2153
2576
  if (ZSTD_isError(cSize)) return cSize;
2154
2577
  cctx->consumedSrcSize += srcSize;
2155
2578
  cctx->producedCSize += (cSize + fhSize);
2156
- if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
2579
+ assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
2580
+ if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
2581
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
2157
2582
  if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) {
2158
2583
  DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u",
2159
2584
  (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
@@ -2190,7 +2615,10 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
2190
2615
  /*! ZSTD_loadDictionaryContent() :
2191
2616
  * @return : 0, or an error code
2192
2617
  */
2193
- static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* src, size_t srcSize)
2618
+ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
2619
+ ZSTD_CCtx_params const* params,
2620
+ const void* src, size_t srcSize,
2621
+ ZSTD_dictTableLoadMethod_e dtlm)
2194
2622
  {
2195
2623
  const BYTE* const ip = (const BYTE*) src;
2196
2624
  const BYTE* const iend = ip + srcSize;
@@ -2204,10 +2632,10 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_CCtx_params
2204
2632
  switch(params->cParams.strategy)
2205
2633
  {
2206
2634
  case ZSTD_fast:
2207
- ZSTD_fillHashTable(ms, cParams, iend);
2635
+ ZSTD_fillHashTable(ms, cParams, iend, dtlm);
2208
2636
  break;
2209
2637
  case ZSTD_dfast:
2210
- ZSTD_fillDoubleHashTable(ms, cParams, iend);
2638
+ ZSTD_fillDoubleHashTable(ms, cParams, iend, dtlm);
2211
2639
  break;
2212
2640
 
2213
2641
  case ZSTD_greedy:
@@ -2256,7 +2684,12 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym
2256
2684
  * assumptions : magic number supposed already checked
2257
2685
  * dictSize supposed > 8
2258
2686
  */
2259
- static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* dict, size_t dictSize, void* workspace)
2687
+ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
2688
+ ZSTD_matchState_t* ms,
2689
+ ZSTD_CCtx_params const* params,
2690
+ const void* dict, size_t dictSize,
2691
+ ZSTD_dictTableLoadMethod_e dtlm,
2692
+ void* workspace)
2260
2693
  {
2261
2694
  const BYTE* dictPtr = (const BYTE*)dict;
2262
2695
  const BYTE* const dictEnd = dictPtr + dictSize;
@@ -2265,13 +2698,15 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matc
2265
2698
  size_t dictID;
2266
2699
 
2267
2700
  ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
2701
+ assert(dictSize > 8);
2702
+ assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
2268
2703
 
2269
2704
  dictPtr += 4; /* skip magic number */
2270
2705
  dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
2271
2706
  dictPtr += 4;
2272
2707
 
2273
2708
  { unsigned maxSymbolValue = 255;
2274
- size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
2709
+ size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
2275
2710
  if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
2276
2711
  if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
2277
2712
  dictPtr += hufHeaderSize;
@@ -2282,7 +2717,8 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matc
2282
2717
  if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
2283
2718
  if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
2284
2719
  /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
2285
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, workspace, HUF_WORKSPACE_SIZE),
2720
+ /* fill all offset symbols to avoid garbage at end of table */
2721
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.offcodeCTable, offcodeNCount, MaxOff, offcodeLog, workspace, HUF_WORKSPACE_SIZE),
2286
2722
  dictionary_corrupted);
2287
2723
  dictPtr += offcodeHeaderSize;
2288
2724
  }
@@ -2294,7 +2730,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matc
2294
2730
  if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
2295
2731
  /* Every match length code must have non-zero probability */
2296
2732
  CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
2297
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE),
2733
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE),
2298
2734
  dictionary_corrupted);
2299
2735
  dictPtr += matchlengthHeaderSize;
2300
2736
  }
@@ -2306,7 +2742,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matc
2306
2742
  if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
2307
2743
  /* Every literal length code must have non-zero probability */
2308
2744
  CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
2309
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE),
2745
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE),
2310
2746
  dictionary_corrupted);
2311
2747
  dictPtr += litlengthHeaderSize;
2312
2748
  }
@@ -2332,22 +2768,25 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matc
2332
2768
  if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
2333
2769
  } }
2334
2770
 
2335
- bs->entropy.hufCTable_repeatMode = HUF_repeat_valid;
2336
- bs->entropy.offcode_repeatMode = FSE_repeat_valid;
2337
- bs->entropy.matchlength_repeatMode = FSE_repeat_valid;
2338
- bs->entropy.litlength_repeatMode = FSE_repeat_valid;
2339
- CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize));
2771
+ bs->entropy.huf.repeatMode = HUF_repeat_valid;
2772
+ bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
2773
+ bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
2774
+ bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
2775
+ CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
2340
2776
  return dictID;
2341
2777
  }
2342
2778
  }
2343
2779
 
2344
2780
  /** ZSTD_compress_insertDictionary() :
2345
2781
  * @return : dictID, or an error code */
2346
- static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms,
2347
- ZSTD_CCtx_params const* params,
2348
- const void* dict, size_t dictSize,
2349
- ZSTD_dictContentType_e dictContentType,
2350
- void* workspace)
2782
+ static size_t
2783
+ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
2784
+ ZSTD_matchState_t* ms,
2785
+ const ZSTD_CCtx_params* params,
2786
+ const void* dict, size_t dictSize,
2787
+ ZSTD_dictContentType_e dictContentType,
2788
+ ZSTD_dictTableLoadMethod_e dtlm,
2789
+ void* workspace)
2351
2790
  {
2352
2791
  DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
2353
2792
  if ((dict==NULL) || (dictSize<=8)) return 0;
@@ -2356,12 +2795,12 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZS
2356
2795
 
2357
2796
  /* dict restricted modes */
2358
2797
  if (dictContentType == ZSTD_dct_rawContent)
2359
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
2798
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
2360
2799
 
2361
2800
  if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
2362
2801
  if (dictContentType == ZSTD_dct_auto) {
2363
2802
  DEBUGLOG(4, "raw content dictionary detected");
2364
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
2803
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
2365
2804
  }
2366
2805
  if (dictContentType == ZSTD_dct_fullDict)
2367
2806
  return ERROR(dictionary_wrong);
@@ -2369,7 +2808,7 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZS
2369
2808
  }
2370
2809
 
2371
2810
  /* dict as full zstd dictionary */
2372
- return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, workspace);
2811
+ return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, dtlm, workspace);
2373
2812
  }
2374
2813
 
2375
2814
  /*! ZSTD_compressBegin_internal() :
@@ -2377,6 +2816,7 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZS
2377
2816
  size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2378
2817
  const void* dict, size_t dictSize,
2379
2818
  ZSTD_dictContentType_e dictContentType,
2819
+ ZSTD_dictTableLoadMethod_e dtlm,
2380
2820
  const ZSTD_CDict* cdict,
2381
2821
  ZSTD_CCtx_params params, U64 pledgedSrcSize,
2382
2822
  ZSTD_buffered_policy_e zbuff)
@@ -2387,9 +2827,7 @@ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2387
2827
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2388
2828
 
2389
2829
  if (cdict && cdict->dictContentSize>0) {
2390
- cctx->requestedParams = params;
2391
- return ZSTD_resetCCtx_usingCDict(cctx, cdict, params.cParams.windowLog,
2392
- params.fParams, pledgedSrcSize, zbuff);
2830
+ return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
2393
2831
  }
2394
2832
 
2395
2833
  CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
@@ -2397,7 +2835,7 @@ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2397
2835
  {
2398
2836
  size_t const dictID = ZSTD_compress_insertDictionary(
2399
2837
  cctx->blockState.prevCBlock, &cctx->blockState.matchState,
2400
- &params, dict, dictSize, dictContentType, cctx->entropyWorkspace);
2838
+ &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
2401
2839
  if (ZSTD_isError(dictID)) return dictID;
2402
2840
  assert(dictID <= (size_t)(U32)-1);
2403
2841
  cctx->dictID = (U32)dictID;
@@ -2408,6 +2846,7 @@ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2408
2846
  size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
2409
2847
  const void* dict, size_t dictSize,
2410
2848
  ZSTD_dictContentType_e dictContentType,
2849
+ ZSTD_dictTableLoadMethod_e dtlm,
2411
2850
  const ZSTD_CDict* cdict,
2412
2851
  ZSTD_CCtx_params params,
2413
2852
  unsigned long long pledgedSrcSize)
@@ -2416,7 +2855,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
2416
2855
  /* compression parameters verification and optimization */
2417
2856
  CHECK_F( ZSTD_checkCParams(params.cParams) );
2418
2857
  return ZSTD_compressBegin_internal(cctx,
2419
- dict, dictSize, dictContentType,
2858
+ dict, dictSize, dictContentType, dtlm,
2420
2859
  cdict,
2421
2860
  params, pledgedSrcSize,
2422
2861
  ZSTDb_not_buffered);
@@ -2431,7 +2870,7 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
2431
2870
  ZSTD_CCtx_params const cctxParams =
2432
2871
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2433
2872
  return ZSTD_compressBegin_advanced_internal(cctx,
2434
- dict, dictSize, ZSTD_dct_auto,
2873
+ dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
2435
2874
  NULL /*cdict*/,
2436
2875
  cctxParams, pledgedSrcSize);
2437
2876
  }
@@ -2442,7 +2881,7 @@ size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t di
2442
2881
  ZSTD_CCtx_params const cctxParams =
2443
2882
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2444
2883
  DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (U32)dictSize);
2445
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL,
2884
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
2446
2885
  cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
2447
2886
  }
2448
2887
 
@@ -2505,7 +2944,9 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
2505
2944
  if (ZSTD_isError(cSize)) return cSize;
2506
2945
  endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
2507
2946
  if (ZSTD_isError(endResult)) return endResult;
2508
- if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
2947
+ assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
2948
+ if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
2949
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
2509
2950
  DEBUGLOG(4, "end of frame : controlling src size");
2510
2951
  if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
2511
2952
  DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
@@ -2517,22 +2958,22 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
2517
2958
 
2518
2959
 
2519
2960
  static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
2520
- void* dst, size_t dstCapacity,
2521
- const void* src, size_t srcSize,
2522
- const void* dict,size_t dictSize,
2523
- ZSTD_parameters params)
2961
+ void* dst, size_t dstCapacity,
2962
+ const void* src, size_t srcSize,
2963
+ const void* dict,size_t dictSize,
2964
+ ZSTD_parameters params)
2524
2965
  {
2525
2966
  ZSTD_CCtx_params const cctxParams =
2526
2967
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2527
2968
  DEBUGLOG(4, "ZSTD_compress_internal");
2528
2969
  return ZSTD_compress_advanced_internal(cctx,
2529
- dst, dstCapacity,
2530
- src, srcSize,
2531
- dict, dictSize,
2532
- cctxParams);
2970
+ dst, dstCapacity,
2971
+ src, srcSize,
2972
+ dict, dictSize,
2973
+ cctxParams);
2533
2974
  }
2534
2975
 
2535
- size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
2976
+ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
2536
2977
  void* dst, size_t dstCapacity,
2537
2978
  const void* src, size_t srcSize,
2538
2979
  const void* dict,size_t dictSize,
@@ -2540,7 +2981,11 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
2540
2981
  {
2541
2982
  DEBUGLOG(4, "ZSTD_compress_advanced");
2542
2983
  CHECK_F(ZSTD_checkCParams(params.cParams));
2543
- return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2984
+ return ZSTD_compress_internal(cctx,
2985
+ dst, dstCapacity,
2986
+ src, srcSize,
2987
+ dict, dictSize,
2988
+ params);
2544
2989
  }
2545
2990
 
2546
2991
  /* Internal */
@@ -2551,37 +2996,44 @@ size_t ZSTD_compress_advanced_internal(
2551
2996
  const void* dict,size_t dictSize,
2552
2997
  ZSTD_CCtx_params params)
2553
2998
  {
2554
- DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)",
2555
- (U32)srcSize);
2556
- CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL,
2557
- params, srcSize, ZSTDb_not_buffered) );
2999
+ DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (U32)srcSize);
3000
+ CHECK_F( ZSTD_compressBegin_internal(cctx,
3001
+ dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3002
+ params, srcSize, ZSTDb_not_buffered) );
2558
3003
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
2559
3004
  }
2560
3005
 
2561
- size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
2562
- const void* dict, size_t dictSize, int compressionLevel)
3006
+ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
3007
+ void* dst, size_t dstCapacity,
3008
+ const void* src, size_t srcSize,
3009
+ const void* dict, size_t dictSize,
3010
+ int compressionLevel)
2563
3011
  {
2564
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0);
3012
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize + (!srcSize), dict ? dictSize : 0);
2565
3013
  ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2566
3014
  assert(params.fParams.contentSizeFlag == 1);
2567
- ZSTD_CCtxParam_setParameter(&cctxParams, ZSTD_p_compressLiterals, compressionLevel>=0);
2568
3015
  return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams);
2569
3016
  }
2570
3017
 
2571
- size_t ZSTD_compressCCtx (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
3018
+ size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
3019
+ void* dst, size_t dstCapacity,
3020
+ const void* src, size_t srcSize,
3021
+ int compressionLevel)
2572
3022
  {
2573
3023
  DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (U32)srcSize);
3024
+ assert(cctx != NULL);
2574
3025
  return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
2575
3026
  }
2576
3027
 
2577
- size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
3028
+ size_t ZSTD_compress(void* dst, size_t dstCapacity,
3029
+ const void* src, size_t srcSize,
3030
+ int compressionLevel)
2578
3031
  {
2579
3032
  size_t result;
2580
3033
  ZSTD_CCtx ctxBody;
2581
- memset(&ctxBody, 0, sizeof(ctxBody));
2582
- ctxBody.customMem = ZSTD_defaultCMem;
3034
+ ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem);
2583
3035
  result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
2584
- ZSTD_free(ctxBody.workSpace, ZSTD_defaultCMem); /* can't free ctxBody itself, as it's on stack; free only heap content */
3036
+ ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */
2585
3037
  return result;
2586
3038
  }
2587
3039
 
@@ -2619,7 +3071,7 @@ static size_t ZSTD_initCDict_internal(
2619
3071
  ZSTD_dictContentType_e dictContentType,
2620
3072
  ZSTD_compressionParameters cParams)
2621
3073
  {
2622
- DEBUGLOG(3, "ZSTD_initCDict_internal, dictContentType %u", (U32)dictContentType);
3074
+ DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (U32)dictContentType);
2623
3075
  assert(!ZSTD_checkCParams(cParams));
2624
3076
  cdict->cParams = cParams;
2625
3077
  if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
@@ -2654,7 +3106,7 @@ static size_t ZSTD_initCDict_internal(
2654
3106
  { size_t const dictID = ZSTD_compress_insertDictionary(
2655
3107
  &cdict->cBlockState, &cdict->matchState, &params,
2656
3108
  cdict->dictContent, cdict->dictContentSize,
2657
- dictContentType, cdict->workspace);
3109
+ dictContentType, ZSTD_dtlm_full, cdict->workspace);
2658
3110
  if (ZSTD_isError(dictID)) return dictID;
2659
3111
  assert(dictID <= (size_t)(U32)-1);
2660
3112
  cdict->dictID = (U32)dictID;
@@ -2799,7 +3251,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
2799
3251
  }
2800
3252
  params.fParams = fParams;
2801
3253
  return ZSTD_compressBegin_internal(cctx,
2802
- NULL, 0, ZSTD_dct_auto,
3254
+ NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
2803
3255
  cdict,
2804
3256
  params, pledgedSrcSize,
2805
3257
  ZSTDb_not_buffered);
@@ -2813,7 +3265,7 @@ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
2813
3265
  {
2814
3266
  ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
2815
3267
  DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
2816
- return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0);
3268
+ return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);
2817
3269
  }
2818
3270
 
2819
3271
  size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
@@ -2882,14 +3334,13 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
2882
3334
  const ZSTD_CDict* const cdict,
2883
3335
  ZSTD_CCtx_params const params, unsigned long long const pledgedSrcSize)
2884
3336
  {
2885
- DEBUGLOG(4, "ZSTD_resetCStream_internal (disableLiteralCompression=%i)",
2886
- params.disableLiteralCompression);
3337
+ DEBUGLOG(4, "ZSTD_resetCStream_internal");
2887
3338
  /* params are supposed to be fully validated at this point */
2888
3339
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
2889
3340
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2890
3341
 
2891
3342
  CHECK_F( ZSTD_compressBegin_internal(cctx,
2892
- dict, dictSize, dictContentType,
3343
+ dict, dictSize, dictContentType, ZSTD_dtlm_fast,
2893
3344
  cdict,
2894
3345
  params, pledgedSrcSize,
2895
3346
  ZSTDb_buffered) );
@@ -3073,7 +3524,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3073
3524
  ip = iend;
3074
3525
  op += cSize;
3075
3526
  zcs->frameEnded = 1;
3076
- ZSTD_startNewCompression(zcs);
3527
+ ZSTD_CCtx_reset(zcs);
3077
3528
  someMoreWork = 0; break;
3078
3529
  }
3079
3530
  /* complete loading into inBuffer */
@@ -3126,7 +3577,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3126
3577
  if (zcs->frameEnded) {
3127
3578
  DEBUGLOG(5, "Frame completed directly in outBuffer");
3128
3579
  someMoreWork = 0;
3129
- ZSTD_startNewCompression(zcs);
3580
+ ZSTD_CCtx_reset(zcs);
3130
3581
  }
3131
3582
  break;
3132
3583
  }
@@ -3154,7 +3605,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3154
3605
  if (zcs->frameEnded) {
3155
3606
  DEBUGLOG(5, "Frame completed on flush");
3156
3607
  someMoreWork = 0;
3157
- ZSTD_startNewCompression(zcs);
3608
+ ZSTD_CCtx_reset(zcs);
3158
3609
  break;
3159
3610
  }
3160
3611
  zcs->streamStage = zcss_load;
@@ -3207,19 +3658,16 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
3207
3658
  params.cParams = ZSTD_getCParamsFromCCtxParams(
3208
3659
  &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
3209
3660
 
3661
+
3210
3662
  #ifdef ZSTD_MULTITHREAD
3211
3663
  if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
3212
3664
  params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
3213
3665
  }
3214
3666
  if (params.nbWorkers > 0) {
3215
3667
  /* mt context creation */
3216
- if (cctx->mtctx == NULL || (params.nbWorkers != ZSTDMT_getNbWorkers(cctx->mtctx))) {
3668
+ if (cctx->mtctx == NULL) {
3217
3669
  DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbWorkers=%u",
3218
3670
  params.nbWorkers);
3219
- if (cctx->mtctx != NULL)
3220
- DEBUGLOG(4, "ZSTD_compress_generic: previous nbWorkers was %u",
3221
- ZSTDMT_getNbWorkers(cctx->mtctx));
3222
- ZSTDMT_freeCCtx(cctx->mtctx);
3223
3671
  cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
3224
3672
  if (cctx->mtctx == NULL) return ERROR(memory_allocation);
3225
3673
  }
@@ -3251,7 +3699,7 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
3251
3699
  { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
3252
3700
  if ( ZSTD_isError(flushMin)
3253
3701
  || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
3254
- ZSTD_startNewCompression(cctx);
3702
+ ZSTD_CCtx_reset(cctx);
3255
3703
  }
3256
3704
  return flushMin;
3257
3705
  } }
@@ -3313,77 +3761,77 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3313
3761
  { /* "default" - guarantees a monotonically increasing memory budget */
3314
3762
  /* W, C, H, S, L, TL, strat */
3315
3763
  { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
3316
- { 19, 13, 14, 1, 7, 1, ZSTD_fast }, /* level 1 */
3317
- { 19, 15, 16, 1, 6, 1, ZSTD_fast }, /* level 2 */
3318
- { 20, 16, 17, 1, 5, 8, ZSTD_dfast }, /* level 3 */
3319
- { 20, 17, 18, 1, 5, 8, ZSTD_dfast }, /* level 4 */
3320
- { 20, 17, 18, 2, 5, 16, ZSTD_greedy }, /* level 5 */
3321
- { 21, 17, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */
3322
- { 21, 18, 19, 3, 5, 16, ZSTD_lazy }, /* level 7 */
3323
- { 21, 18, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */
3324
- { 21, 19, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 9 */
3325
- { 21, 19, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
3326
- { 22, 20, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
3764
+ { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
3765
+ { 19, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
3766
+ { 20, 16, 17, 1, 5, 1, ZSTD_dfast }, /* level 3 */
3767
+ { 20, 18, 18, 1, 5, 1, ZSTD_dfast }, /* level 4 */
3768
+ { 20, 18, 18, 2, 5, 2, ZSTD_greedy }, /* level 5 */
3769
+ { 21, 18, 19, 2, 5, 4, ZSTD_lazy }, /* level 6 */
3770
+ { 21, 18, 19, 3, 5, 8, ZSTD_lazy2 }, /* level 7 */
3771
+ { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */
3772
+ { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */
3773
+ { 21, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
3774
+ { 21, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
3327
3775
  { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
3328
3776
  { 22, 21, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
3329
3777
  { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
3330
3778
  { 22, 22, 22, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
3331
3779
  { 22, 21, 22, 4, 5, 48, ZSTD_btopt }, /* level 16 */
3332
- { 23, 22, 22, 4, 4, 48, ZSTD_btopt }, /* level 17 */
3333
- { 23, 22, 22, 5, 3, 64, ZSTD_btopt }, /* level 18 */
3334
- { 23, 23, 22, 7, 3,128, ZSTD_btopt }, /* level 19 */
3335
- { 25, 25, 23, 7, 3,128, ZSTD_btultra }, /* level 20 */
3336
- { 26, 26, 24, 7, 3,256, ZSTD_btultra }, /* level 21 */
3337
- { 27, 27, 25, 9, 3,512, ZSTD_btultra }, /* level 22 */
3780
+ { 23, 22, 22, 4, 4, 64, ZSTD_btopt }, /* level 17 */
3781
+ { 23, 23, 22, 6, 3,256, ZSTD_btopt }, /* level 18 */
3782
+ { 23, 24, 22, 7, 3,256, ZSTD_btultra }, /* level 19 */
3783
+ { 25, 25, 23, 7, 3,256, ZSTD_btultra }, /* level 20 */
3784
+ { 26, 26, 24, 7, 3,512, ZSTD_btultra }, /* level 21 */
3785
+ { 27, 27, 25, 9, 3,999, ZSTD_btultra }, /* level 22 */
3338
3786
  },
3339
3787
  { /* for srcSize <= 256 KB */
3340
3788
  /* W, C, H, S, L, T, strat */
3341
3789
  { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
3342
- { 18, 13, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */
3343
- { 18, 14, 13, 1, 5, 8, ZSTD_dfast }, /* level 2 */
3344
- { 18, 16, 15, 1, 5, 8, ZSTD_dfast }, /* level 3 */
3345
- { 18, 15, 17, 1, 5, 8, ZSTD_greedy }, /* level 4.*/
3346
- { 18, 16, 17, 4, 5, 8, ZSTD_greedy }, /* level 5.*/
3347
- { 18, 16, 17, 3, 5, 8, ZSTD_lazy }, /* level 6.*/
3348
- { 18, 17, 17, 4, 4, 8, ZSTD_lazy }, /* level 7 */
3349
- { 18, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
3350
- { 18, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
3351
- { 18, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
3352
- { 18, 18, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 11.*/
3353
- { 18, 18, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 12.*/
3354
- { 18, 19, 17, 7, 4, 8, ZSTD_btlazy2 }, /* level 13 */
3355
- { 18, 18, 18, 4, 4, 16, ZSTD_btopt }, /* level 14.*/
3356
- { 18, 18, 18, 4, 3, 16, ZSTD_btopt }, /* level 15.*/
3357
- { 18, 19, 18, 6, 3, 32, ZSTD_btopt }, /* level 16.*/
3358
- { 18, 19, 18, 8, 3, 64, ZSTD_btopt }, /* level 17.*/
3359
- { 18, 19, 18, 9, 3,128, ZSTD_btopt }, /* level 18.*/
3360
- { 18, 19, 18, 10, 3,256, ZSTD_btopt }, /* level 19.*/
3361
- { 18, 19, 18, 11, 3,512, ZSTD_btultra }, /* level 20.*/
3362
- { 18, 19, 18, 12, 3,512, ZSTD_btultra }, /* level 21.*/
3363
- { 18, 19, 18, 13, 3,512, ZSTD_btultra }, /* level 22.*/
3790
+ { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
3791
+ { 18, 14, 14, 1, 5, 1, ZSTD_dfast }, /* level 2 */
3792
+ { 18, 16, 16, 1, 4, 1, ZSTD_dfast }, /* level 3 */
3793
+ { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
3794
+ { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
3795
+ { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
3796
+ { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */
3797
+ { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
3798
+ { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
3799
+ { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
3800
+ { 18, 18, 19, 5, 4, 16, ZSTD_btlazy2 }, /* level 11.*/
3801
+ { 18, 19, 19, 6, 4, 16, ZSTD_btlazy2 }, /* level 12.*/
3802
+ { 18, 19, 19, 8, 4, 16, ZSTD_btlazy2 }, /* level 13 */
3803
+ { 18, 18, 19, 4, 4, 24, ZSTD_btopt }, /* level 14.*/
3804
+ { 18, 18, 19, 4, 3, 24, ZSTD_btopt }, /* level 15.*/
3805
+ { 18, 19, 19, 6, 3, 64, ZSTD_btopt }, /* level 16.*/
3806
+ { 18, 19, 19, 8, 3,128, ZSTD_btopt }, /* level 17.*/
3807
+ { 18, 19, 19, 10, 3,256, ZSTD_btopt }, /* level 18.*/
3808
+ { 18, 19, 19, 10, 3,256, ZSTD_btultra }, /* level 19.*/
3809
+ { 18, 19, 19, 11, 3,512, ZSTD_btultra }, /* level 20.*/
3810
+ { 18, 19, 19, 12, 3,512, ZSTD_btultra }, /* level 21.*/
3811
+ { 18, 19, 19, 13, 3,999, ZSTD_btultra }, /* level 22.*/
3364
3812
  },
3365
3813
  { /* for srcSize <= 128 KB */
3366
3814
  /* W, C, H, S, L, T, strat */
3367
- { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* level 0 - not used */
3368
- { 17, 12, 13, 1, 6, 1, ZSTD_fast }, /* level 1 */
3369
- { 17, 13, 16, 1, 5, 1, ZSTD_fast }, /* level 2 */
3370
- { 17, 16, 16, 2, 5, 8, ZSTD_dfast }, /* level 3 */
3371
- { 17, 13, 15, 3, 4, 8, ZSTD_greedy }, /* level 4 */
3372
- { 17, 15, 17, 4, 4, 8, ZSTD_greedy }, /* level 5 */
3373
- { 17, 16, 17, 3, 4, 8, ZSTD_lazy }, /* level 6 */
3374
- { 17, 15, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 7 */
3815
+ { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
3816
+ { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
3817
+ { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
3818
+ { 17, 15, 16, 2, 5, 1, ZSTD_dfast }, /* level 3 */
3819
+ { 17, 17, 17, 2, 4, 1, ZSTD_dfast }, /* level 4 */
3820
+ { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
3821
+ { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
3822
+ { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
3375
3823
  { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
3376
3824
  { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
3377
3825
  { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
3378
3826
  { 17, 17, 17, 7, 4, 8, ZSTD_lazy2 }, /* level 11 */
3379
- { 17, 17, 17, 8, 4, 8, ZSTD_lazy2 }, /* level 12 */
3380
- { 17, 18, 17, 6, 4, 8, ZSTD_btlazy2 }, /* level 13.*/
3381
- { 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/
3382
- { 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/
3383
- { 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/
3384
- { 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
3385
- { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
3386
- { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
3827
+ { 17, 18, 17, 6, 4, 16, ZSTD_btlazy2 }, /* level 12 */
3828
+ { 17, 18, 17, 8, 4, 16, ZSTD_btlazy2 }, /* level 13.*/
3829
+ { 17, 18, 17, 4, 4, 32, ZSTD_btopt }, /* level 14.*/
3830
+ { 17, 18, 17, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
3831
+ { 17, 18, 17, 7, 3,128, ZSTD_btopt }, /* level 16.*/
3832
+ { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 17.*/
3833
+ { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 18.*/
3834
+ { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 19.*/
3387
3835
  { 17, 18, 17, 9, 3,256, ZSTD_btultra }, /* level 20.*/
3388
3836
  { 17, 18, 17, 10, 3,256, ZSTD_btultra }, /* level 21.*/
3389
3837
  { 17, 18, 17, 11, 3,512, ZSTD_btultra }, /* level 22.*/
@@ -3391,28 +3839,28 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3391
3839
  { /* for srcSize <= 16 KB */
3392
3840
  /* W, C, H, S, L, T, strat */
3393
3841
  { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
3394
- { 14, 14, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */
3395
- { 14, 14, 14, 1, 4, 1, ZSTD_fast }, /* level 2 */
3396
- { 14, 14, 14, 1, 4, 6, ZSTD_dfast }, /* level 3.*/
3397
- { 14, 14, 14, 4, 4, 6, ZSTD_greedy }, /* level 4.*/
3398
- { 14, 14, 14, 3, 4, 6, ZSTD_lazy }, /* level 5.*/
3399
- { 14, 14, 14, 4, 4, 6, ZSTD_lazy2 }, /* level 6 */
3400
- { 14, 14, 14, 5, 4, 6, ZSTD_lazy2 }, /* level 7 */
3401
- { 14, 14, 14, 6, 4, 6, ZSTD_lazy2 }, /* level 8.*/
3402
- { 14, 15, 14, 6, 4, 6, ZSTD_btlazy2 }, /* level 9.*/
3403
- { 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/
3404
- { 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/
3842
+ { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
3843
+ { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
3844
+ { 14, 14, 14, 2, 4, 1, ZSTD_dfast }, /* level 3.*/
3845
+ { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4.*/
3846
+ { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
3847
+ { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
3848
+ { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */
3849
+ { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/
3850
+ { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/
3851
+ { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/
3852
+ { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/
3405
3853
  { 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
3406
3854
  { 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
3407
3855
  { 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
3408
3856
  { 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
3409
3857
  { 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
3410
3858
  { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
3411
- { 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
3412
- { 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
3859
+ { 14, 15, 15, 8, 3,256, ZSTD_btopt }, /* level 18.*/
3860
+ { 14, 15, 15, 6, 3,256, ZSTD_btultra }, /* level 19.*/
3413
3861
  { 14, 15, 15, 8, 3,256, ZSTD_btultra }, /* level 20.*/
3414
3862
  { 14, 15, 15, 9, 3,256, ZSTD_btultra }, /* level 21.*/
3415
- { 14, 15, 15, 10, 3,256, ZSTD_btultra }, /* level 22.*/
3863
+ { 14, 15, 15, 10, 3,512, ZSTD_btultra }, /* level 22.*/
3416
3864
  },
3417
3865
  };
3418
3866