zstd-ruby 1.3.4.0 → 1.3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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