zstd-ruby 1.3.3.0 → 1.3.4.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 (44) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/BUCK +13 -0
  4. data/ext/zstdruby/libzstd/README.md +32 -25
  5. data/ext/zstdruby/libzstd/common/bitstream.h +1 -1
  6. data/ext/zstdruby/libzstd/common/compiler.h +25 -0
  7. data/ext/zstdruby/libzstd/common/cpu.h +216 -0
  8. data/ext/zstdruby/libzstd/common/error_private.c +1 -0
  9. data/ext/zstdruby/libzstd/common/fse.h +1 -1
  10. data/ext/zstdruby/libzstd/common/fse_decompress.c +2 -2
  11. data/ext/zstdruby/libzstd/common/huf.h +114 -89
  12. data/ext/zstdruby/libzstd/common/pool.c +46 -17
  13. data/ext/zstdruby/libzstd/common/pool.h +18 -9
  14. data/ext/zstdruby/libzstd/common/threading.h +12 -12
  15. data/ext/zstdruby/libzstd/common/zstd_errors.h +16 -7
  16. data/ext/zstdruby/libzstd/common/zstd_internal.h +4 -5
  17. data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -11
  18. data/ext/zstdruby/libzstd/compress/huf_compress.c +160 -62
  19. data/ext/zstdruby/libzstd/compress/zstd_compress.c +973 -644
  20. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +281 -34
  21. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +80 -62
  22. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +11 -4
  23. data/ext/zstdruby/libzstd/compress/zstd_fast.c +87 -71
  24. data/ext/zstdruby/libzstd/compress/zstd_fast.h +10 -6
  25. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +333 -274
  26. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +33 -16
  27. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +305 -359
  28. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +64 -21
  29. data/ext/zstdruby/libzstd/compress/zstd_opt.c +194 -56
  30. data/ext/zstdruby/libzstd/compress/zstd_opt.h +17 -5
  31. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +1131 -449
  32. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +32 -16
  33. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +390 -290
  34. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +777 -439
  35. data/ext/zstdruby/libzstd/dictBuilder/cover.c +11 -8
  36. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +83 -50
  37. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +44 -43
  38. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +2 -0
  39. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +42 -118
  40. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +2 -2
  41. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +2 -2
  42. data/ext/zstdruby/libzstd/zstd.h +254 -254
  43. data/lib/zstd-ruby/version.rb +1 -1
  44. metadata +4 -3
@@ -21,6 +21,7 @@
21
21
  * Dependencies
22
22
  ***************************************/
23
23
  #include <string.h> /* memset */
24
+ #include "cpu.h"
24
25
  #include "mem.h"
25
26
  #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
26
27
  #include "fse.h"
@@ -49,7 +50,13 @@ struct ZSTD_CDict_s {
49
50
  void* dictBuffer;
50
51
  const void* dictContent;
51
52
  size_t dictContentSize;
52
- ZSTD_CCtx* refContext;
53
+ void* workspace;
54
+ size_t workspaceSize;
55
+ ZSTD_matchState_t matchState;
56
+ ZSTD_compressedBlockState_t cBlockState;
57
+ ZSTD_compressionParameters cParams;
58
+ ZSTD_customMem customMem;
59
+ U32 dictID;
53
60
  }; /* typedef'd to ZSTD_CDict within "zstd.h" */
54
61
 
55
62
  ZSTD_CCtx* ZSTD_createCCtx(void)
@@ -59,18 +66,17 @@ ZSTD_CCtx* ZSTD_createCCtx(void)
59
66
 
60
67
  ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
61
68
  {
62
- ZSTD_CCtx* cctx;
63
-
64
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
65
-
66
- cctx = (ZSTD_CCtx*) ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
67
- if (!cctx) return NULL;
68
- cctx->customMem = customMem;
69
- cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
70
- cctx->requestedParams.fParams.contentSizeFlag = 1;
71
69
  ZSTD_STATIC_ASSERT(zcss_init==0);
72
70
  ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
73
- return cctx;
71
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
72
+ { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
73
+ 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
+ return cctx;
79
+ }
74
80
  }
75
81
 
76
82
  ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
@@ -83,11 +89,16 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
83
89
  cctx->workSpace = (void*)(cctx+1);
84
90
  cctx->workSpaceSize = workspaceSize - sizeof(ZSTD_CCtx);
85
91
 
86
- /* entropy space (never moves) */
87
- if (cctx->workSpaceSize < sizeof(ZSTD_entropyCTables_t)) return NULL;
92
+ /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
93
+ if (cctx->workSpaceSize < HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t)) return NULL;
88
94
  assert(((size_t)cctx->workSpace & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
89
- cctx->entropy = (ZSTD_entropyCTables_t*)cctx->workSpace;
90
-
95
+ cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)cctx->workSpace;
96
+ cctx->blockState.nextCBlock = cctx->blockState.prevCBlock + 1;
97
+ {
98
+ void* const ptr = cctx->blockState.nextCBlock + 1;
99
+ cctx->entropyWorkspace = (U32*)ptr;
100
+ }
101
+ cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
91
102
  return cctx;
92
103
  }
93
104
 
@@ -95,13 +106,10 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
95
106
  {
96
107
  if (cctx==NULL) return 0; /* support free on NULL */
97
108
  if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
98
- ZSTD_free(cctx->workSpace, cctx->customMem);
99
- cctx->workSpace = NULL;
100
- ZSTD_freeCDict(cctx->cdictLocal);
101
- cctx->cdictLocal = NULL;
109
+ ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
110
+ ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
102
111
  #ifdef ZSTD_MULTITHREAD
103
- ZSTDMT_freeCCtx(cctx->mtctx);
104
- cctx->mtctx = NULL;
112
+ ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
105
113
  #endif
106
114
  ZSTD_free(cctx, cctx->customMem);
107
115
  return 0; /* reserved as a potential error code in the future */
@@ -122,10 +130,6 @@ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
122
130
  size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
123
131
  {
124
132
  if (cctx==NULL) return 0; /* support sizeof on NULL */
125
- DEBUGLOG(3, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
126
- DEBUGLOG(3, "workSpaceSize (including streaming buffers): %u", (U32)cctx->workSpaceSize);
127
- DEBUGLOG(3, "inner cdict : %u", (U32)ZSTD_sizeof_CDict(cctx->cdictLocal));
128
- DEBUGLOG(3, "inner MTCTX : %u", (U32)ZSTD_sizeof_mtctx(cctx));
129
133
  return sizeof(*cctx) + cctx->workSpaceSize
130
134
  + ZSTD_sizeof_CDict(cctx->cdictLocal)
131
135
  + ZSTD_sizeof_mtctx(cctx);
@@ -139,37 +143,19 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
139
143
  /* private API call, for dictBuilder only */
140
144
  const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
141
145
 
142
- #define ZSTD_CLEVEL_CUSTOM 999
143
-
144
- static ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
145
- ZSTD_CCtx_params CCtxParams, U64 srcSizeHint, size_t dictSize)
146
- {
147
- DEBUGLOG(4, "ZSTD_getCParamsFromCCtxParams: srcSize = %u, dictSize = %u",
148
- (U32)srcSizeHint, (U32)dictSize);
149
- return (CCtxParams.compressionLevel == ZSTD_CLEVEL_CUSTOM) ?
150
- CCtxParams.cParams :
151
- ZSTD_getCParams(CCtxParams.compressionLevel, srcSizeHint, dictSize);
152
- }
153
-
154
- static void ZSTD_cLevelToCCtxParams_srcSize(ZSTD_CCtx_params* CCtxParams, U64 srcSize)
155
- {
156
- DEBUGLOG(4, "ZSTD_cLevelToCCtxParams_srcSize: srcSize = %u",
157
- (U32)srcSize);
158
- CCtxParams->cParams = ZSTD_getCParamsFromCCtxParams(*CCtxParams, srcSize, 0);
159
- CCtxParams->compressionLevel = ZSTD_CLEVEL_CUSTOM;
160
- }
161
-
162
- static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
163
- {
164
- DEBUGLOG(4, "ZSTD_cLevelToCParams: level=%i", cctx->requestedParams.compressionLevel);
165
- ZSTD_cLevelToCCtxParams_srcSize(
166
- &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1);
167
- }
168
-
169
- static void ZSTD_cLevelToCCtxParams(ZSTD_CCtx_params* CCtxParams)
170
- {
171
- DEBUGLOG(4, "ZSTD_cLevelToCCtxParams");
172
- ZSTD_cLevelToCCtxParams_srcSize(CCtxParams, ZSTD_CONTENTSIZE_UNKNOWN);
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;
173
159
  }
174
160
 
175
161
  static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
@@ -178,7 +164,9 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
178
164
  ZSTD_CCtx_params cctxParams;
179
165
  memset(&cctxParams, 0, sizeof(cctxParams));
180
166
  cctxParams.cParams = cParams;
181
- cctxParams.compressionLevel = ZSTD_CLEVEL_CUSTOM;
167
+ cctxParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
168
+ assert(!ZSTD_checkCParams(cParams));
169
+ cctxParams.fParams.contentSizeFlag = 1;
182
170
  return cctxParams;
183
171
  }
184
172
 
@@ -192,6 +180,7 @@ static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
192
180
  if (!params) { return NULL; }
193
181
  params->customMem = customMem;
194
182
  params->compressionLevel = ZSTD_CLEVEL_DEFAULT;
183
+ params->fParams.contentSizeFlag = 1;
195
184
  return params;
196
185
  }
197
186
 
@@ -207,36 +196,41 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
207
196
  return 0;
208
197
  }
209
198
 
210
- size_t ZSTD_resetCCtxParams(ZSTD_CCtx_params* params)
199
+ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
211
200
  {
212
- return ZSTD_initCCtxParams(params, ZSTD_CLEVEL_DEFAULT);
201
+ return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
213
202
  }
214
203
 
215
- size_t ZSTD_initCCtxParams(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
204
+ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
216
205
  if (!cctxParams) { return ERROR(GENERIC); }
217
206
  memset(cctxParams, 0, sizeof(*cctxParams));
218
207
  cctxParams->compressionLevel = compressionLevel;
208
+ cctxParams->fParams.contentSizeFlag = 1;
219
209
  return 0;
220
210
  }
221
211
 
222
- size_t ZSTD_initCCtxParams_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
212
+ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
223
213
  {
224
214
  if (!cctxParams) { return ERROR(GENERIC); }
225
215
  CHECK_F( ZSTD_checkCParams(params.cParams) );
226
216
  memset(cctxParams, 0, sizeof(*cctxParams));
227
217
  cctxParams->cParams = params.cParams;
228
218
  cctxParams->fParams = params.fParams;
229
- cctxParams->compressionLevel = ZSTD_CLEVEL_CUSTOM;
219
+ cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
220
+ assert(!ZSTD_checkCParams(params.cParams));
230
221
  return 0;
231
222
  }
232
223
 
224
+ /* ZSTD_assignParamsToCCtxParams() :
225
+ * params is presumed valid at this stage */
233
226
  static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
234
227
  ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
235
228
  {
236
229
  ZSTD_CCtx_params ret = cctxParams;
237
230
  ret.cParams = params.cParams;
238
231
  ret.fParams = params.fParams;
239
- ret.compressionLevel = ZSTD_CLEVEL_CUSTOM;
232
+ ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
233
+ assert(!ZSTD_checkCParams(params.cParams));
240
234
  return ret;
241
235
  }
242
236
 
@@ -245,10 +239,49 @@ static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
245
239
  return ERROR(parameter_outOfBound); \
246
240
  } }
247
241
 
242
+
243
+ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
244
+ {
245
+ switch(param)
246
+ {
247
+ case ZSTD_p_compressionLevel:
248
+ case ZSTD_p_hashLog:
249
+ case ZSTD_p_chainLog:
250
+ case ZSTD_p_searchLog:
251
+ case ZSTD_p_minMatch:
252
+ case ZSTD_p_targetLength:
253
+ case ZSTD_p_compressionStrategy:
254
+ case ZSTD_p_compressLiterals:
255
+ return 1;
256
+
257
+ case ZSTD_p_format:
258
+ case ZSTD_p_windowLog:
259
+ case ZSTD_p_contentSizeFlag:
260
+ case ZSTD_p_checksumFlag:
261
+ case ZSTD_p_dictIDFlag:
262
+ case ZSTD_p_forceMaxWindow :
263
+ case ZSTD_p_nbWorkers:
264
+ case ZSTD_p_jobSize:
265
+ case ZSTD_p_overlapSizeLog:
266
+ case ZSTD_p_enableLongDistanceMatching:
267
+ case ZSTD_p_ldmHashLog:
268
+ case ZSTD_p_ldmMinMatch:
269
+ case ZSTD_p_ldmBucketSizeLog:
270
+ case ZSTD_p_ldmHashEveryLog:
271
+ default:
272
+ return 0;
273
+ }
274
+ }
275
+
248
276
  size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value)
249
277
  {
250
278
  DEBUGLOG(4, "ZSTD_CCtx_setParameter (%u, %u)", (U32)param, value);
251
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
279
+ if (cctx->streamStage != zcss_init) {
280
+ if (ZSTD_isUpdateAuthorized(param)) {
281
+ cctx->cParamsChanged = 1;
282
+ } else {
283
+ return ERROR(stage_wrong);
284
+ } }
252
285
 
253
286
  switch(param)
254
287
  {
@@ -267,9 +300,9 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
267
300
  case ZSTD_p_targetLength:
268
301
  case ZSTD_p_compressionStrategy:
269
302
  if (cctx->cdict) return ERROR(stage_wrong);
270
- if (value>0) ZSTD_cLevelToCParams(cctx); /* Can optimize if srcSize is known */
271
303
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
272
304
 
305
+ case ZSTD_p_compressLiterals:
273
306
  case ZSTD_p_contentSizeFlag:
274
307
  case ZSTD_p_checksumFlag:
275
308
  case ZSTD_p_dictIDFlag:
@@ -280,23 +313,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
280
313
  * default : 0 when using a CDict, 1 when using a Prefix */
281
314
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
282
315
 
283
- case ZSTD_p_nbThreads:
284
- if ((value > 1) && cctx->staticSize) {
316
+ case ZSTD_p_nbWorkers:
317
+ if ((value>0) && cctx->staticSize) {
285
318
  return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
286
319
  }
287
320
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
288
321
 
289
322
  case ZSTD_p_jobSize:
290
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
291
-
292
323
  case ZSTD_p_overlapSizeLog:
293
324
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
294
325
 
295
326
  case ZSTD_p_enableLongDistanceMatching:
296
- if (cctx->cdict) return ERROR(stage_wrong);
297
- if (value>0) ZSTD_cLevelToCParams(cctx);
298
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
299
-
300
327
  case ZSTD_p_ldmHashLog:
301
328
  case ZSTD_p_ldmMinMatch:
302
329
  case ZSTD_p_ldmBucketSizeLog:
@@ -320,69 +347,62 @@ size_t ZSTD_CCtxParam_setParameter(
320
347
  CCtxParams->format = (ZSTD_format_e)value;
321
348
  return (size_t)CCtxParams->format;
322
349
 
323
- case ZSTD_p_compressionLevel :
324
- if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel();
325
- if (value) /* 0 : does not change current level */
326
- CCtxParams->compressionLevel = value;
327
- return CCtxParams->compressionLevel;
350
+ case ZSTD_p_compressionLevel : {
351
+ int cLevel = (int)value; /* cast expected to restore negative sign */
352
+ if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
353
+ if (cLevel) { /* 0 : does not change current level */
354
+ CCtxParams->disableLiteralCompression = (cLevel<0); /* negative levels disable huffman */
355
+ CCtxParams->compressionLevel = cLevel;
356
+ }
357
+ if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
358
+ return 0; /* return type (size_t) cannot represent negative values */
359
+ }
328
360
 
329
361
  case ZSTD_p_windowLog :
330
- DEBUGLOG(4, "ZSTD_CCtxParam_setParameter: set windowLog=%u", value);
331
- if (value) { /* 0 : does not change current windowLog */
362
+ if (value>0) /* 0 => use default */
332
363
  CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
333
- ZSTD_cLevelToCCtxParams(CCtxParams);
334
- CCtxParams->cParams.windowLog = value;
335
- }
364
+ CCtxParams->cParams.windowLog = value;
336
365
  return CCtxParams->cParams.windowLog;
337
366
 
338
367
  case ZSTD_p_hashLog :
339
- if (value) { /* 0 : does not change current hashLog */
368
+ if (value>0) /* 0 => use default */
340
369
  CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
341
- ZSTD_cLevelToCCtxParams(CCtxParams);
342
- CCtxParams->cParams.hashLog = value;
343
- }
370
+ CCtxParams->cParams.hashLog = value;
344
371
  return CCtxParams->cParams.hashLog;
345
372
 
346
373
  case ZSTD_p_chainLog :
347
- if (value) { /* 0 : does not change current chainLog */
374
+ if (value>0) /* 0 => use default */
348
375
  CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
349
- ZSTD_cLevelToCCtxParams(CCtxParams);
350
- CCtxParams->cParams.chainLog = value;
351
- }
376
+ CCtxParams->cParams.chainLog = value;
352
377
  return CCtxParams->cParams.chainLog;
353
378
 
354
379
  case ZSTD_p_searchLog :
355
- if (value) { /* 0 : does not change current searchLog */
380
+ if (value>0) /* 0 => use default */
356
381
  CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
357
- ZSTD_cLevelToCCtxParams(CCtxParams);
358
- CCtxParams->cParams.searchLog = value;
359
- }
382
+ CCtxParams->cParams.searchLog = value;
360
383
  return value;
361
384
 
362
385
  case ZSTD_p_minMatch :
363
- if (value) { /* 0 : does not change current minMatch length */
386
+ if (value>0) /* 0 => use default */
364
387
  CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
365
- ZSTD_cLevelToCCtxParams(CCtxParams);
366
- CCtxParams->cParams.searchLength = value;
367
- }
388
+ CCtxParams->cParams.searchLength = value;
368
389
  return CCtxParams->cParams.searchLength;
369
390
 
370
391
  case ZSTD_p_targetLength :
371
- if (value) { /* 0 : does not change current sufficient_len */
372
- CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
373
- ZSTD_cLevelToCCtxParams(CCtxParams);
374
- CCtxParams->cParams.targetLength = value;
375
- }
392
+ /* all values are valid. 0 => use default */
393
+ CCtxParams->cParams.targetLength = value;
376
394
  return CCtxParams->cParams.targetLength;
377
395
 
378
396
  case ZSTD_p_compressionStrategy :
379
- if (value) { /* 0 : does not change currentstrategy */
397
+ if (value>0) /* 0 => use default */
380
398
  CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
381
- ZSTD_cLevelToCCtxParams(CCtxParams);
382
- CCtxParams->cParams.strategy = (ZSTD_strategy)value;
383
- }
399
+ CCtxParams->cParams.strategy = (ZSTD_strategy)value;
384
400
  return (size_t)CCtxParams->cParams.strategy;
385
401
 
402
+ case ZSTD_p_compressLiterals:
403
+ CCtxParams->disableLiteralCompression = !value;
404
+ return !CCtxParams->disableLiteralCompression;
405
+
386
406
  case ZSTD_p_contentSizeFlag :
387
407
  /* Content size written in frame header _when known_ (default:1) */
388
408
  DEBUGLOG(4, "set content size flag = %u", (value>0));
@@ -396,27 +416,25 @@ size_t ZSTD_CCtxParam_setParameter(
396
416
 
397
417
  case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
398
418
  DEBUGLOG(4, "set dictIDFlag = %u", (value>0));
399
- CCtxParams->fParams.noDictIDFlag = (value == 0);
419
+ CCtxParams->fParams.noDictIDFlag = !value;
400
420
  return !CCtxParams->fParams.noDictIDFlag;
401
421
 
402
422
  case ZSTD_p_forceMaxWindow :
403
423
  CCtxParams->forceWindow = (value > 0);
404
424
  return CCtxParams->forceWindow;
405
425
 
406
- case ZSTD_p_nbThreads :
407
- if (value == 0) return CCtxParams->nbThreads;
426
+ case ZSTD_p_nbWorkers :
408
427
  #ifndef ZSTD_MULTITHREAD
409
- if (value > 1) return ERROR(parameter_unsupported);
410
- return 1;
428
+ if (value>0) return ERROR(parameter_unsupported);
429
+ return 0;
411
430
  #else
412
- return ZSTDMT_CCtxParam_setNbThreads(CCtxParams, value);
431
+ return ZSTDMT_CCtxParam_setNbWorkers(CCtxParams, value);
413
432
  #endif
414
433
 
415
434
  case ZSTD_p_jobSize :
416
435
  #ifndef ZSTD_MULTITHREAD
417
436
  return ERROR(parameter_unsupported);
418
437
  #else
419
- if (CCtxParams->nbThreads <= 1) return ERROR(parameter_unsupported);
420
438
  return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value);
421
439
  #endif
422
440
 
@@ -424,44 +442,36 @@ size_t ZSTD_CCtxParam_setParameter(
424
442
  #ifndef ZSTD_MULTITHREAD
425
443
  return ERROR(parameter_unsupported);
426
444
  #else
427
- if (CCtxParams->nbThreads <= 1) return ERROR(parameter_unsupported);
428
445
  return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapSectionLog, value);
429
446
  #endif
430
447
 
431
448
  case ZSTD_p_enableLongDistanceMatching :
432
- if (value) {
433
- ZSTD_cLevelToCCtxParams(CCtxParams);
434
- CCtxParams->cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
435
- }
436
- return ZSTD_ldm_initializeParameters(&CCtxParams->ldmParams, value);
449
+ CCtxParams->ldmParams.enableLdm = (value>0);
450
+ return CCtxParams->ldmParams.enableLdm;
437
451
 
438
452
  case ZSTD_p_ldmHashLog :
439
- if (value) { /* 0 : does not change current ldmHashLog */
453
+ if (value>0) /* 0 ==> auto */
440
454
  CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
441
- CCtxParams->ldmParams.hashLog = value;
442
- }
455
+ CCtxParams->ldmParams.hashLog = value;
443
456
  return CCtxParams->ldmParams.hashLog;
444
457
 
445
458
  case ZSTD_p_ldmMinMatch :
446
- if (value) { /* 0 : does not change current ldmMinMatch */
459
+ if (value>0) /* 0 ==> default */
447
460
  CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
448
- CCtxParams->ldmParams.minMatchLength = value;
449
- }
461
+ CCtxParams->ldmParams.minMatchLength = value;
450
462
  return CCtxParams->ldmParams.minMatchLength;
451
463
 
452
464
  case ZSTD_p_ldmBucketSizeLog :
453
- if (value > ZSTD_LDM_BUCKETSIZELOG_MAX) {
465
+ if (value > ZSTD_LDM_BUCKETSIZELOG_MAX)
454
466
  return ERROR(parameter_outOfBound);
455
- }
456
467
  CCtxParams->ldmParams.bucketSizeLog = value;
457
- return value;
468
+ return CCtxParams->ldmParams.bucketSizeLog;
458
469
 
459
470
  case ZSTD_p_ldmHashEveryLog :
460
- if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) {
471
+ if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
461
472
  return ERROR(parameter_outOfBound);
462
- }
463
473
  CCtxParams->ldmParams.hashEveryLog = value;
464
- return value;
474
+ return CCtxParams->ldmParams.hashEveryLog;
465
475
 
466
476
  default: return ERROR(parameter_unsupported);
467
477
  }
@@ -470,6 +480,9 @@ size_t ZSTD_CCtxParam_setParameter(
470
480
  /** ZSTD_CCtx_setParametersUsingCCtxParams() :
471
481
  * just applies `params` into `cctx`
472
482
  * no action is performed, parameters are merely stored.
483
+ * If ZSTDMT is enabled, parameters are pushed to cctx->mtctx.
484
+ * This is possible even if a compression is ongoing.
485
+ * In which case, new parameters will be applied on the fly, starting with next compression job.
473
486
  */
474
487
  size_t ZSTD_CCtx_setParametersUsingCCtxParams(
475
488
  ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
@@ -478,7 +491,6 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
478
491
  if (cctx->cdict) return ERROR(stage_wrong);
479
492
 
480
493
  cctx->requestedParams = *params;
481
-
482
494
  return 0;
483
495
  }
484
496
 
@@ -492,7 +504,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo
492
504
 
493
505
  size_t ZSTD_CCtx_loadDictionary_advanced(
494
506
  ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
495
- ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode)
507
+ ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
496
508
  {
497
509
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
498
510
  if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
@@ -503,10 +515,10 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
503
515
  cctx->cdict = NULL;
504
516
  } else {
505
517
  ZSTD_compressionParameters const cParams =
506
- ZSTD_getCParamsFromCCtxParams(cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
518
+ ZSTD_getCParamsFromCCtxParams(&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
507
519
  cctx->cdictLocal = ZSTD_createCDict_advanced(
508
520
  dict, dictSize,
509
- dictLoadMethod, dictMode,
521
+ dictLoadMethod, dictContentType,
510
522
  cParams, cctx->customMem);
511
523
  cctx->cdict = cctx->cdictLocal;
512
524
  if (cctx->cdictLocal == NULL)
@@ -519,13 +531,13 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
519
531
  ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
520
532
  {
521
533
  return ZSTD_CCtx_loadDictionary_advanced(
522
- cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dm_auto);
534
+ cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
523
535
  }
524
536
 
525
537
  ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
526
538
  {
527
539
  return ZSTD_CCtx_loadDictionary_advanced(
528
- cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dm_auto);
540
+ cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
529
541
  }
530
542
 
531
543
 
@@ -539,17 +551,17 @@ size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
539
551
 
540
552
  size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
541
553
  {
542
- return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dm_rawContent);
554
+ return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);
543
555
  }
544
556
 
545
557
  size_t ZSTD_CCtx_refPrefix_advanced(
546
- ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode)
558
+ ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
547
559
  {
548
560
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
549
561
  cctx->cdict = NULL; /* prefix discards any prior cdict */
550
562
  cctx->prefixDict.dict = prefix;
551
563
  cctx->prefixDict.dictSize = prefixSize;
552
- cctx->prefixDict.dictMode = dictMode;
564
+ cctx->prefixDict.dictContentType = dictContentType;
553
565
  return 0;
554
566
  }
555
567
 
@@ -577,7 +589,8 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
577
589
  CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
578
590
  CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
579
591
  CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
580
- CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
592
+ if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN)
593
+ return ERROR(parameter_unsupported);
581
594
  if ((U32)(cParams.strategy) > (U32)ZSTD_btultra)
582
595
  return ERROR(parameter_unsupported);
583
596
  return 0;
@@ -597,7 +610,7 @@ static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters c
597
610
  CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
598
611
  CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
599
612
  CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
600
- CLAMP(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
613
+ if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN) cParams.targetLength = ZSTD_TARGETLENGTH_MIN;
601
614
  if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) cParams.strategy = ZSTD_btultra;
602
615
  return cParams;
603
616
  }
@@ -653,36 +666,43 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
653
666
  return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
654
667
  }
655
668
 
669
+ static size_t ZSTD_sizeof_matchState(ZSTD_compressionParameters const* cParams, const U32 forCCtx)
670
+ {
671
+ size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
672
+ size_t const hSize = ((size_t)1) << cParams->hashLog;
673
+ U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
674
+ size_t const h3Size = ((size_t)1) << hashLog3;
675
+ size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
676
+ size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
677
+ + (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
678
+ size_t const optSpace = (forCCtx && ((cParams->strategy == ZSTD_btopt) ||
679
+ (cParams->strategy == ZSTD_btultra)))
680
+ ? optPotentialSpace
681
+ : 0;
682
+ DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u",
683
+ (U32)chainSize, (U32)hSize, (U32)h3Size);
684
+ return tableSpace + optSpace;
685
+ }
686
+
656
687
  size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
657
688
  {
658
689
  /* Estimate CCtx size is supported for single-threaded compression only. */
659
- if (params->nbThreads > 1) { return ERROR(GENERIC); }
690
+ if (params->nbWorkers > 0) { return ERROR(GENERIC); }
660
691
  { ZSTD_compressionParameters const cParams =
661
- ZSTD_getCParamsFromCCtxParams(*params, 0, 0);
692
+ ZSTD_getCParamsFromCCtxParams(params, 0, 0);
662
693
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
663
694
  U32 const divider = (cParams.searchLength==3) ? 3 : 4;
664
695
  size_t const maxNbSeq = blockSize / divider;
665
696
  size_t const tokenSpace = blockSize + 11*maxNbSeq;
666
- size_t const chainSize =
667
- (cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams.chainLog);
668
- size_t const hSize = ((size_t)1) << cParams.hashLog;
669
- U32 const hashLog3 = (cParams.searchLength>3) ?
670
- 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
671
- size_t const h3Size = ((size_t)1) << hashLog3;
672
- size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
673
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
697
+ size_t const entropySpace = HUF_WORKSPACE_SIZE;
698
+ size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
699
+ size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
674
700
 
675
- size_t const optBudget =
676
- ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
677
- + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
678
- size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
701
+ size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
702
+ size_t const ldmSeqSpace = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq);
679
703
 
680
- size_t const ldmSpace = params->ldmParams.enableLdm ?
681
- ZSTD_ldm_getTableSize(params->ldmParams.hashLog,
682
- params->ldmParams.bucketSizeLog) : 0;
683
-
684
- size_t const neededSpace = entropySpace + tableSpace + tokenSpace +
685
- optSpace + ldmSpace;
704
+ size_t const neededSpace = entropySpace + blockStateSpace + tokenSpace +
705
+ matchStateSize + ldmSpace + ldmSeqSpace;
686
706
 
687
707
  DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
688
708
  DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
@@ -696,15 +716,26 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
696
716
  return ZSTD_estimateCCtxSize_usingCCtxParams(&params);
697
717
  }
698
718
 
699
- size_t ZSTD_estimateCCtxSize(int compressionLevel)
719
+ static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
700
720
  {
701
721
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
702
722
  return ZSTD_estimateCCtxSize_usingCParams(cParams);
703
723
  }
704
724
 
725
+ size_t ZSTD_estimateCCtxSize(int compressionLevel)
726
+ {
727
+ int level;
728
+ size_t memBudget = 0;
729
+ for (level=1; level<=compressionLevel; level++) {
730
+ size_t const newMB = ZSTD_estimateCCtxSize_internal(level);
731
+ if (newMB > memBudget) memBudget = newMB;
732
+ }
733
+ return memBudget;
734
+ }
735
+
705
736
  size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
706
737
  {
707
- if (params->nbThreads > 1) { return ERROR(GENERIC); }
738
+ if (params->nbWorkers > 0) { return ERROR(GENERIC); }
708
739
  { size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
709
740
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
710
741
  size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
@@ -721,11 +752,44 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
721
752
  return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
722
753
  }
723
754
 
724
- size_t ZSTD_estimateCStreamSize(int compressionLevel) {
755
+ static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) {
725
756
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
726
757
  return ZSTD_estimateCStreamSize_usingCParams(cParams);
727
758
  }
728
759
 
760
+ size_t ZSTD_estimateCStreamSize(int compressionLevel) {
761
+ int level;
762
+ size_t memBudget = 0;
763
+ for (level=1; level<=compressionLevel; level++) {
764
+ size_t const newMB = ZSTD_estimateCStreamSize_internal(level);
765
+ if (newMB > memBudget) memBudget = newMB;
766
+ }
767
+ return memBudget;
768
+ }
769
+
770
+ /* ZSTD_getFrameProgression():
771
+ * tells how much data has been consumed (input) and produced (output) for current frame.
772
+ * able to count progression inside worker threads (non-blocking mode).
773
+ */
774
+ ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)
775
+ {
776
+ #ifdef ZSTD_MULTITHREAD
777
+ if (cctx->appliedParams.nbWorkers > 0) {
778
+ return ZSTDMT_getFrameProgression(cctx->mtctx);
779
+ }
780
+ #endif
781
+ { ZSTD_frameProgression fp;
782
+ size_t const buffered = (cctx->inBuff == NULL) ? 0 :
783
+ cctx->inBuffPos - cctx->inToCompress;
784
+ if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress);
785
+ assert(buffered <= ZSTD_BLOCKSIZE_MAX);
786
+ fp.ingested = cctx->consumedSrcSize + buffered;
787
+ fp.consumed = cctx->consumedSrcSize;
788
+ fp.produced = cctx->producedCSize;
789
+ return fp;
790
+ } }
791
+
792
+
729
793
  static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
730
794
  ZSTD_compressionParameters cParams2)
731
795
  {
@@ -761,9 +825,9 @@ static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t blockSize1,
761
825
  size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
762
826
  size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
763
827
  size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
764
- DEBUGLOG(4, "ZSTD_sufficientBuff: windowSize2=%u from wlog=%u",
828
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is windowSize2=%u <= wlog1=%u",
765
829
  (U32)windowSize2, cParams2.windowLog);
766
- DEBUGLOG(4, "ZSTD_sufficientBuff: blockSize2 %u <=? blockSize1 %u",
830
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is blockSize2=%u <= blockSize1=%u",
767
831
  (U32)blockSize2, (U32)blockSize1);
768
832
  return (blockSize2 <= blockSize1) /* seqStore space depends on blockSize */
769
833
  & (neededBufferSize2 <= bufferSize1);
@@ -782,37 +846,101 @@ static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
782
846
  ZSTD_sufficientBuff(buffSize1, blockSize1, buffPol2, params2.cParams, pledgedSrcSize);
783
847
  }
784
848
 
849
+ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
850
+ {
851
+ int i;
852
+ for (i = 0; i < ZSTD_REP_NUM; ++i)
853
+ 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;
858
+ }
859
+
860
+ /*! ZSTD_invalidateMatchState()
861
+ * Invalidate all the matches in the match finder tables.
862
+ * Requires nextSrc and base to be set (can be NULL).
863
+ */
864
+ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
865
+ {
866
+ ZSTD_window_clear(&ms->window);
867
+
868
+ ms->nextToUpdate = ms->window.dictLimit + 1;
869
+ ms->loadedDictEnd = 0;
870
+ ms->opt.litLengthSum = 0; /* force reset of btopt stats */
871
+ }
872
+
785
873
  /*! ZSTD_continueCCtx() :
786
874
  * reuse CCtx without reset (note : requires no dictionary) */
787
875
  static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
788
876
  {
789
- U32 const end = (U32)(cctx->nextSrc - cctx->base);
790
877
  size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
791
878
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
792
- DEBUGLOG(4, "ZSTD_continueCCtx");
879
+ DEBUGLOG(4, "ZSTD_continueCCtx: re-use context in place");
793
880
 
794
881
  cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
795
882
  cctx->appliedParams = params;
796
883
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
797
884
  cctx->consumedSrcSize = 0;
885
+ cctx->producedCSize = 0;
798
886
  if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
799
887
  cctx->appliedParams.fParams.contentSizeFlag = 0;
800
888
  DEBUGLOG(4, "pledged content size : %u ; flag : %u",
801
889
  (U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
802
- cctx->lowLimit = end;
803
- cctx->dictLimit = end;
804
- cctx->nextToUpdate = end+1;
805
890
  cctx->stage = ZSTDcs_init;
806
891
  cctx->dictID = 0;
807
- cctx->loadedDictEnd = 0;
808
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) cctx->seqStore.rep[i] = repStartValue[i]; }
809
- cctx->optState.litLengthSum = 0; /* force reset of btopt stats */
892
+ if (params.ldmParams.enableLdm)
893
+ ZSTD_window_clear(&cctx->ldmState.window);
894
+ ZSTD_referenceExternalSequences(cctx, NULL, 0);
895
+ ZSTD_invalidateMatchState(&cctx->blockState.matchState);
896
+ ZSTD_reset_compressedBlockState(cctx->blockState.prevCBlock);
810
897
  XXH64_reset(&cctx->xxhState, 0);
811
898
  return 0;
812
899
  }
813
900
 
814
901
  typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
815
902
 
903
+ static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compressionParameters const* cParams, ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
904
+ {
905
+ size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
906
+ size_t const hSize = ((size_t)1) << cParams->hashLog;
907
+ U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
908
+ size_t const h3Size = ((size_t)1) << hashLog3;
909
+ size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
910
+
911
+ assert(((size_t)ptr & 3) == 0);
912
+
913
+ ms->hashLog3 = hashLog3;
914
+ memset(&ms->window, 0, sizeof(ms->window));
915
+ ZSTD_invalidateMatchState(ms);
916
+
917
+ /* opt parser space */
918
+ if (forCCtx && ((cParams->strategy == ZSTD_btopt) | (cParams->strategy == ZSTD_btultra))) {
919
+ DEBUGLOG(4, "reserving optimal parser space");
920
+ ms->opt.litFreq = (U32*)ptr;
921
+ ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits);
922
+ ms->opt.matchLengthFreq = ms->opt.litLengthFreq + (MaxLL+1);
923
+ ms->opt.offCodeFreq = ms->opt.matchLengthFreq + (MaxML+1);
924
+ ptr = ms->opt.offCodeFreq + (MaxOff+1);
925
+ ms->opt.matchTable = (ZSTD_match_t*)ptr;
926
+ ptr = ms->opt.matchTable + ZSTD_OPT_NUM+1;
927
+ ms->opt.priceTable = (ZSTD_optimal_t*)ptr;
928
+ ptr = ms->opt.priceTable + ZSTD_OPT_NUM+1;
929
+ }
930
+
931
+ /* table Space */
932
+ DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
933
+ assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
934
+ if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
935
+ ms->hashTable = (U32*)(ptr);
936
+ ms->chainTable = ms->hashTable + hSize;
937
+ ms->hashTable3 = ms->chainTable + chainSize;
938
+ ptr = ms->hashTable3 + h3Size;
939
+
940
+ assert(((size_t)ptr & 3) == 0);
941
+ return ptr;
942
+ }
943
+
816
944
  /*! ZSTD_resetCCtx_internal() :
817
945
  note : `params` are assumed fully validated at this stage */
818
946
  static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
@@ -830,19 +958,14 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
830
958
  zbuff, pledgedSrcSize)) {
831
959
  DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%u)",
832
960
  zc->appliedParams.cParams.windowLog, (U32)zc->blockSize);
833
- assert(!(params.ldmParams.enableLdm &&
834
- params.ldmParams.hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET));
835
- zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
836
- zc->entropy->offcode_repeatMode = FSE_repeat_none;
837
- zc->entropy->matchlength_repeatMode = FSE_repeat_none;
838
- zc->entropy->litlength_repeatMode = FSE_repeat_none;
839
961
  return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
840
962
  } }
841
963
  DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
842
964
 
843
965
  if (params.ldmParams.enableLdm) {
844
966
  /* Adjust long distance matching parameters */
845
- ZSTD_ldm_adjustParameters(&params.ldmParams, params.cParams.windowLog);
967
+ params.ldmParams.windowLog = params.cParams.windowLog;
968
+ ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
846
969
  assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
847
970
  assert(params.ldmParams.hashEveryLog < 32);
848
971
  zc->ldmState.hashPower =
@@ -854,34 +977,25 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
854
977
  U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
855
978
  size_t const maxNbSeq = blockSize / divider;
856
979
  size_t const tokenSpace = blockSize + 11*maxNbSeq;
857
- size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ?
858
- 0 : ((size_t)1 << params.cParams.chainLog);
859
- size_t const hSize = ((size_t)1) << params.cParams.hashLog;
860
- U32 const hashLog3 = (params.cParams.searchLength>3) ?
861
- 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
862
- size_t const h3Size = ((size_t)1) << hashLog3;
863
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
864
980
  size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
865
981
  size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
982
+ size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
983
+ size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
866
984
  void* ptr;
867
985
 
868
986
  /* Check if workSpace is large enough, alloc a new one if needed */
869
- { size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
870
- size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
871
- + (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
872
- size_t const optSpace = ( (params.cParams.strategy == ZSTD_btopt)
873
- || (params.cParams.strategy == ZSTD_btultra)) ?
874
- optPotentialSpace : 0;
987
+ { size_t const entropySpace = HUF_WORKSPACE_SIZE;
988
+ size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
875
989
  size_t const bufferSpace = buffInSize + buffOutSize;
876
- size_t const ldmSpace = params.ldmParams.enableLdm
877
- ? ZSTD_ldm_getTableSize(params.ldmParams.hashLog, params.ldmParams.bucketSizeLog)
878
- : 0;
879
- size_t const neededSpace = entropySpace + optSpace + ldmSpace +
880
- tableSpace + tokenSpace + bufferSpace;
881
- DEBUGLOG(4, "Need %uKB workspace, including %uKB for tables, and %uKB for buffers",
882
- (U32)(neededSpace>>10), (U32)(tableSpace>>10), (U32)(bufferSpace>>10));
883
- DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u - windowSize: %u - blockSize: %u",
884
- (U32)chainSize, (U32)hSize, (U32)h3Size, (U32)windowSize, (U32)blockSize);
990
+ size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
991
+ size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq);
992
+
993
+ size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
994
+ ldmSeqSpace + matchStateSize + tokenSpace +
995
+ 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);
885
999
 
886
1000
  if (zc->workSpaceSize < neededSpace) { /* too small : resize */
887
1001
  DEBUGLOG(4, "Need to update workSpaceSize from %uK to %uK",
@@ -897,16 +1011,20 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
897
1011
  zc->workSpaceSize = neededSpace;
898
1012
  ptr = zc->workSpace;
899
1013
 
900
- /* entropy space */
1014
+ /* Statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
901
1015
  assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */
902
- assert(zc->workSpaceSize >= sizeof(ZSTD_entropyCTables_t));
903
- zc->entropy = (ZSTD_entropyCTables_t*)zc->workSpace;
1016
+ assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t));
1017
+ zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace;
1018
+ zc->blockState.nextCBlock = zc->blockState.prevCBlock + 1;
1019
+ ptr = zc->blockState.nextCBlock + 1;
1020
+ zc->entropyWorkspace = (U32*)ptr;
904
1021
  } }
905
1022
 
906
1023
  /* init params */
907
1024
  zc->appliedParams = params;
908
1025
  zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
909
1026
  zc->consumedSrcSize = 0;
1027
+ zc->producedCSize = 0;
910
1028
  if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
911
1029
  zc->appliedParams.fParams.contentSizeFlag = 0;
912
1030
  DEBUGLOG(4, "pledged content size : %u ; flag : %u",
@@ -916,37 +1034,10 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
916
1034
  XXH64_reset(&zc->xxhState, 0);
917
1035
  zc->stage = ZSTDcs_init;
918
1036
  zc->dictID = 0;
919
- zc->loadedDictEnd = 0;
920
- zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
921
- zc->entropy->offcode_repeatMode = FSE_repeat_none;
922
- zc->entropy->matchlength_repeatMode = FSE_repeat_none;
923
- zc->entropy->litlength_repeatMode = FSE_repeat_none;
924
- zc->nextToUpdate = 1;
925
- zc->nextSrc = NULL;
926
- zc->base = NULL;
927
- zc->dictBase = NULL;
928
- zc->dictLimit = 0;
929
- zc->lowLimit = 0;
930
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->seqStore.rep[i] = repStartValue[i]; }
931
- zc->hashLog3 = hashLog3;
932
- zc->optState.litLengthSum = 0;
933
-
934
- ptr = zc->entropy + 1;
935
-
936
- /* opt parser space */
937
- if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) {
938
- DEBUGLOG(4, "reserving optimal parser space");
939
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
940
- zc->optState.litFreq = (U32*)ptr;
941
- zc->optState.litLengthFreq = zc->optState.litFreq + (1<<Litbits);
942
- zc->optState.matchLengthFreq = zc->optState.litLengthFreq + (MaxLL+1);
943
- zc->optState.offCodeFreq = zc->optState.matchLengthFreq + (MaxML+1);
944
- ptr = zc->optState.offCodeFreq + (MaxOff+1);
945
- zc->optState.matchTable = (ZSTD_match_t*)ptr;
946
- ptr = zc->optState.matchTable + ZSTD_OPT_NUM+1;
947
- zc->optState.priceTable = (ZSTD_optimal_t*)ptr;
948
- ptr = zc->optState.priceTable + ZSTD_OPT_NUM+1;
949
- }
1037
+
1038
+ ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
1039
+
1040
+ ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32;
950
1041
 
951
1042
  /* ldm hash table */
952
1043
  /* initialize bucketOffsets table later for pointer alignment */
@@ -956,16 +1047,15 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
956
1047
  assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
957
1048
  zc->ldmState.hashTable = (ldmEntry_t*)ptr;
958
1049
  ptr = zc->ldmState.hashTable + ldmHSize;
1050
+ zc->ldmSequences = (rawSeq*)ptr;
1051
+ ptr = zc->ldmSequences + maxNbLdmSeq;
1052
+ zc->maxNbLdmSequences = maxNbLdmSeq;
1053
+
1054
+ memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window));
959
1055
  }
1056
+ assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
960
1057
 
961
- /* table Space */
962
- DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
963
- if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
964
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
965
- zc->hashTable = (U32*)(ptr);
966
- zc->chainTable = zc->hashTable + hSize;
967
- zc->hashTable3 = zc->chainTable + chainSize;
968
- ptr = zc->hashTable3 + h3Size;
1058
+ ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
969
1059
 
970
1060
  /* sequences storage */
971
1061
  zc->seqStore.sequencesStart = (seqDef*)ptr;
@@ -984,7 +1074,9 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
984
1074
  memset(ptr, 0, ldmBucketSize);
985
1075
  zc->ldmState.bucketOffsets = (BYTE*)ptr;
986
1076
  ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
1077
+ ZSTD_window_clear(&zc->ldmState.window);
987
1078
  }
1079
+ ZSTD_referenceExternalSequences(zc, NULL, 0);
988
1080
 
989
1081
  /* buffers */
990
1082
  zc->inBuffSize = buffInSize;
@@ -1002,9 +1094,61 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1002
1094
  * do not use with extDict variant ! */
1003
1095
  void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
1004
1096
  int i;
1005
- for (i=0; i<ZSTD_REP_NUM; i++) cctx->seqStore.rep[i] = 0;
1097
+ for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;
1098
+ assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
1006
1099
  }
1007
1100
 
1101
+ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1102
+ const ZSTD_CDict* cdict,
1103
+ unsigned windowLog,
1104
+ ZSTD_frameParameters fParams,
1105
+ U64 pledgedSrcSize,
1106
+ ZSTD_buffered_policy_e zbuff)
1107
+ {
1108
+ { ZSTD_CCtx_params params = cctx->requestedParams;
1109
+ /* Copy only compression parameters related to tables. */
1110
+ params.cParams = cdict->cParams;
1111
+ if (windowLog) params.cParams.windowLog = windowLog;
1112
+ params.fParams = fParams;
1113
+ ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1114
+ ZSTDcrp_noMemset, zbuff);
1115
+ assert(cctx->appliedParams.cParams.strategy == cdict->cParams.strategy);
1116
+ assert(cctx->appliedParams.cParams.hashLog == cdict->cParams.hashLog);
1117
+ assert(cctx->appliedParams.cParams.chainLog == cdict->cParams.chainLog);
1118
+ }
1119
+
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
+ }
1135
+
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;
1144
+ }
1145
+ cctx->dictID = cdict->dictID;
1146
+
1147
+ /* copy block state */
1148
+ memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
1149
+
1150
+ return 0;
1151
+ }
1008
1152
 
1009
1153
  /*! ZSTD_copyCCtx_internal() :
1010
1154
  * Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
@@ -1015,7 +1159,6 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
1015
1159
  * @return : 0, or an error code */
1016
1160
  static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1017
1161
  const ZSTD_CCtx* srcCCtx,
1018
- unsigned windowLog,
1019
1162
  ZSTD_frameParameters fParams,
1020
1163
  U64 pledgedSrcSize,
1021
1164
  ZSTD_buffered_policy_e zbuff)
@@ -1027,41 +1170,39 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1027
1170
  { ZSTD_CCtx_params params = dstCCtx->requestedParams;
1028
1171
  /* Copy only compression parameters related to tables. */
1029
1172
  params.cParams = srcCCtx->appliedParams.cParams;
1030
- if (windowLog) params.cParams.windowLog = windowLog;
1031
1173
  params.fParams = fParams;
1032
1174
  ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
1033
1175
  ZSTDcrp_noMemset, zbuff);
1176
+ assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
1177
+ assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
1178
+ assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
1179
+ assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog);
1180
+ assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
1034
1181
  }
1035
1182
 
1036
1183
  /* copy tables */
1037
1184
  { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
1038
1185
  size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
1039
- size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
1186
+ size_t const h3Size = (size_t)1 << srcCCtx->blockState.matchState.hashLog3;
1040
1187
  size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
1041
- assert((U32*)dstCCtx->chainTable == (U32*)dstCCtx->hashTable + hSize); /* chainTable must follow hashTable */
1042
- assert((U32*)dstCCtx->hashTable3 == (U32*)dstCCtx->chainTable + chainSize);
1043
- memcpy(dstCCtx->hashTable, srcCCtx->hashTable, tableSpace); /* presumes all tables follow each other */
1188
+ assert((U32*)dstCCtx->blockState.matchState.chainTable == (U32*)dstCCtx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1189
+ assert((U32*)dstCCtx->blockState.matchState.hashTable3 == (U32*)dstCCtx->blockState.matchState.chainTable + chainSize);
1190
+ memcpy(dstCCtx->blockState.matchState.hashTable, srcCCtx->blockState.matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1044
1191
  }
1045
1192
 
1046
1193
  /* copy dictionary offsets */
1047
- dstCCtx->nextToUpdate = srcCCtx->nextToUpdate;
1048
- dstCCtx->nextToUpdate3= srcCCtx->nextToUpdate3;
1049
- dstCCtx->nextSrc = srcCCtx->nextSrc;
1050
- dstCCtx->base = srcCCtx->base;
1051
- dstCCtx->dictBase = srcCCtx->dictBase;
1052
- dstCCtx->dictLimit = srcCCtx->dictLimit;
1053
- dstCCtx->lowLimit = srcCCtx->lowLimit;
1054
- dstCCtx->loadedDictEnd= srcCCtx->loadedDictEnd;
1055
- dstCCtx->dictID = srcCCtx->dictID;
1056
-
1057
- /* copy entropy tables */
1058
- memcpy(dstCCtx->entropy, srcCCtx->entropy, sizeof(ZSTD_entropyCTables_t));
1059
- /* copy repcodes */
1060
1194
  {
1061
- int i;
1062
- for (i = 0; i < ZSTD_REP_NUM; ++i)
1063
- dstCCtx->seqStore.rep[i] = srcCCtx->seqStore.rep[i];
1195
+ ZSTD_matchState_t const* srcMatchState = &srcCCtx->blockState.matchState;
1196
+ ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
1197
+ dstMatchState->window = srcMatchState->window;
1198
+ dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1199
+ dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1200
+ dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1064
1201
  }
1202
+ dstCCtx->dictID = srcCCtx->dictID;
1203
+
1204
+ /* copy block state */
1205
+ memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));
1065
1206
 
1066
1207
  return 0;
1067
1208
  }
@@ -1080,51 +1221,69 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long
1080
1221
  fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);
1081
1222
 
1082
1223
  return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx,
1083
- 0 /*windowLog from srcCCtx*/, fParams, pledgedSrcSize,
1224
+ fParams, pledgedSrcSize,
1084
1225
  zbuff);
1085
1226
  }
1086
1227
 
1087
1228
 
1229
+ #define ZSTD_ROWSIZE 16
1088
1230
  /*! ZSTD_reduceTable() :
1089
- * reduce table indexes by `reducerValue` */
1090
- static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
1231
+ * reduce table indexes by `reducerValue`, or squash to zero.
1232
+ * PreserveMark preserves "unsorted mark" for btlazy2 strategy.
1233
+ * It must be set to a clear 0/1 value, to remove branch during inlining.
1234
+ * Presume table size is a multiple of ZSTD_ROWSIZE
1235
+ * to help auto-vectorization */
1236
+ FORCE_INLINE_TEMPLATE void
1237
+ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark)
1238
+ {
1239
+ int const nbRows = (int)size / ZSTD_ROWSIZE;
1240
+ int cellNb = 0;
1241
+ int rowNb;
1242
+ assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
1243
+ assert(size < (1U<<31)); /* can be casted to int */
1244
+ for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
1245
+ int column;
1246
+ for (column=0; column<ZSTD_ROWSIZE; column++) {
1247
+ if (preserveMark) {
1248
+ U32 const adder = (table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) ? reducerValue : 0;
1249
+ table[cellNb] += adder;
1250
+ }
1251
+ if (table[cellNb] < reducerValue) table[cellNb] = 0;
1252
+ else table[cellNb] -= reducerValue;
1253
+ cellNb++;
1254
+ } }
1255
+ }
1256
+
1257
+ static void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)
1091
1258
  {
1092
- U32 u;
1093
- for (u=0 ; u < size ; u++) {
1094
- if (table[u] < reducerValue) table[u] = 0;
1095
- else table[u] -= reducerValue;
1096
- }
1259
+ ZSTD_reduceTable_internal(table, size, reducerValue, 0);
1097
1260
  }
1098
1261
 
1099
- /*! ZSTD_ldm_reduceTable() :
1100
- * reduce table indexes by `reducerValue` */
1101
- static void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,
1102
- U32 const reducerValue)
1262
+ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)
1103
1263
  {
1104
- U32 u;
1105
- for (u = 0; u < size; u++) {
1106
- if (table[u].offset < reducerValue) table[u].offset = 0;
1107
- else table[u].offset -= reducerValue;
1108
- }
1264
+ ZSTD_reduceTable_internal(table, size, reducerValue, 1);
1109
1265
  }
1110
1266
 
1111
1267
  /*! ZSTD_reduceIndex() :
1112
1268
  * rescale all indexes to avoid future overflow (indexes are U32) */
1113
1269
  static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
1114
1270
  {
1115
- { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
1116
- ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
1117
-
1118
- { U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((U32)1 << zc->appliedParams.cParams.chainLog);
1119
- ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
1271
+ ZSTD_matchState_t* const ms = &zc->blockState.matchState;
1272
+ { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
1273
+ ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
1274
+ }
1120
1275
 
1121
- { U32 const h3Size = (zc->hashLog3) ? (U32)1 << zc->hashLog3 : 0;
1122
- ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
1276
+ if (zc->appliedParams.cParams.strategy != ZSTD_fast) {
1277
+ U32 const chainSize = (U32)1 << zc->appliedParams.cParams.chainLog;
1278
+ if (zc->appliedParams.cParams.strategy == ZSTD_btlazy2)
1279
+ ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
1280
+ else
1281
+ ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
1282
+ }
1123
1283
 
1124
- { if (zc->appliedParams.ldmParams.enableLdm) {
1125
- U32 const ldmHSize = (U32)1 << zc->appliedParams.ldmParams.hashLog;
1126
- ZSTD_ldm_reduceTable(zc->ldmState.hashTable, ldmHSize, reducerValue);
1127
- }
1284
+ if (ms->hashLog3) {
1285
+ U32 const h3Size = (U32)1 << ms->hashLog3;
1286
+ ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue);
1128
1287
  }
1129
1288
  }
1130
1289
 
@@ -1199,10 +1358,12 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
1199
1358
 
1200
1359
  static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
1201
1360
 
1202
- static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
1203
- ZSTD_strategy strategy,
1361
+ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
1362
+ ZSTD_entropyCTables_t* nextEntropy,
1363
+ ZSTD_strategy strategy, int disableLiteralCompression,
1204
1364
  void* dst, size_t dstCapacity,
1205
- const void* src, size_t srcSize)
1365
+ const void* src, size_t srcSize,
1366
+ U32* workspace, const int bmi2)
1206
1367
  {
1207
1368
  size_t const minGain = ZSTD_minGain(srcSize);
1208
1369
  size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
@@ -1211,34 +1372,51 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
1211
1372
  symbolEncodingType_e hType = set_compressed;
1212
1373
  size_t cLitSize;
1213
1374
 
1375
+ DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
1376
+ disableLiteralCompression);
1377
+
1378
+ /* Prepare nextEntropy assuming reusing the existing table */
1379
+ nextEntropy->hufCTable_repeatMode = prevEntropy->hufCTable_repeatMode;
1380
+ memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable,
1381
+ sizeof(prevEntropy->hufCTable));
1382
+
1383
+ if (disableLiteralCompression)
1384
+ return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1214
1385
 
1215
1386
  /* small ? don't even attempt compression (speed opt) */
1216
- # define LITERAL_NOENTROPY 63
1217
- { size_t const minLitSize = entropy->hufCTable_repeatMode == HUF_repeat_valid ? 6 : LITERAL_NOENTROPY;
1387
+ # define COMPRESS_LITERALS_SIZE_MIN 63
1388
+ { size_t const minLitSize = (prevEntropy->hufCTable_repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
1218
1389
  if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1219
1390
  }
1220
1391
 
1221
1392
  if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
1222
- { HUF_repeat repeat = entropy->hufCTable_repeatMode;
1393
+ { HUF_repeat repeat = prevEntropy->hufCTable_repeatMode;
1223
1394
  int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
1224
1395
  if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
1225
1396
  cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1226
- entropy->workspace, sizeof(entropy->workspace), (HUF_CElt*)entropy->hufCTable, &repeat, preferRepeat)
1397
+ workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2)
1227
1398
  : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1228
- entropy->workspace, sizeof(entropy->workspace), (HUF_CElt*)entropy->hufCTable, &repeat, preferRepeat);
1229
- if (repeat != HUF_repeat_none) { hType = set_repeat; } /* reused the existing table */
1230
- else { entropy->hufCTable_repeatMode = HUF_repeat_check; } /* now have a table to reuse */
1399
+ workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2);
1400
+ if (repeat != HUF_repeat_none) {
1401
+ /* reused the existing table */
1402
+ hType = set_repeat;
1403
+ }
1231
1404
  }
1232
1405
 
1233
1406
  if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
1234
- entropy->hufCTable_repeatMode = HUF_repeat_none;
1407
+ memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
1235
1408
  return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1236
1409
  }
1237
1410
  if (cLitSize==1) {
1238
- entropy->hufCTable_repeatMode = HUF_repeat_none;
1411
+ memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
1239
1412
  return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
1240
1413
  }
1241
1414
 
1415
+ if (hType == set_compressed) {
1416
+ /* using a newly constructed table */
1417
+ nextEntropy->hufCTable_repeatMode = HUF_repeat_check;
1418
+ }
1419
+
1242
1420
  /* Build header */
1243
1421
  switch(lhSize)
1244
1422
  {
@@ -1332,10 +1510,11 @@ symbolEncodingType_e ZSTD_selectEncodingType(
1332
1510
 
1333
1511
  MEM_STATIC
1334
1512
  size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1335
- FSE_CTable* CTable, U32 FSELog, symbolEncodingType_e type,
1513
+ FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
1336
1514
  U32* count, U32 max,
1337
1515
  BYTE const* codeTable, size_t nbSeq,
1338
1516
  S16 const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
1517
+ FSE_CTable const* prevCTable, size_t prevCTableSize,
1339
1518
  void* workspace, size_t workspaceSize)
1340
1519
  {
1341
1520
  BYTE* op = (BYTE*)dst;
@@ -1344,12 +1523,13 @@ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1344
1523
  switch (type) {
1345
1524
  case set_rle:
1346
1525
  *op = codeTable[0];
1347
- CHECK_F(FSE_buildCTable_rle(CTable, (BYTE)max));
1526
+ CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
1348
1527
  return 1;
1349
1528
  case set_repeat:
1529
+ memcpy(nextCTable, prevCTable, prevCTableSize);
1350
1530
  return 0;
1351
1531
  case set_basic:
1352
- CHECK_F(FSE_buildCTable_wksp(CTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
1532
+ CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
1353
1533
  return 0;
1354
1534
  case set_compressed: {
1355
1535
  S16 norm[MaxSeq + 1];
@@ -1363,7 +1543,7 @@ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1363
1543
  CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
1364
1544
  { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
1365
1545
  if (FSE_isError(NCountSize)) return NCountSize;
1366
- CHECK_F(FSE_buildCTable_wksp(CTable, norm, max, tableLog, workspace, workspaceSize));
1546
+ CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
1367
1547
  return NCountSize;
1368
1548
  }
1369
1549
  }
@@ -1371,8 +1551,8 @@ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1371
1551
  }
1372
1552
  }
1373
1553
 
1374
- MEM_STATIC
1375
- size_t ZSTD_encodeSequences(
1554
+ FORCE_INLINE_TEMPLATE size_t
1555
+ ZSTD_encodeSequences_body(
1376
1556
  void* dst, size_t dstCapacity,
1377
1557
  FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1378
1558
  FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
@@ -1419,7 +1599,8 @@ size_t ZSTD_encodeSequences(
1419
1599
  DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
1420
1600
  sequences[n].litLength,
1421
1601
  sequences[n].matchLength + MINMATCH,
1422
- sequences[n].offset); /* 32b*/ /* 64b*/
1602
+ sequences[n].offset);
1603
+ /* 32b*/ /* 64b*/
1423
1604
  /* (7)*/ /* (7)*/
1424
1605
  FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
1425
1606
  FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
@@ -1445,8 +1626,11 @@ size_t ZSTD_encodeSequences(
1445
1626
  BIT_flushBits(&blockStream); /* (7)*/
1446
1627
  } }
1447
1628
 
1629
+ DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
1448
1630
  FSE_flushCState(&blockStream, &stateMatchLength);
1631
+ DEBUGLOG(6, "ZSTD_encodeSequences: flushing Off state with %u bits", stateOffsetBits.stateLog);
1449
1632
  FSE_flushCState(&blockStream, &stateOffsetBits);
1633
+ DEBUGLOG(6, "ZSTD_encodeSequences: flushing LL state with %u bits", stateLitLength.stateLog);
1450
1634
  FSE_flushCState(&blockStream, &stateLitLength);
1451
1635
 
1452
1636
  { size_t const streamSize = BIT_closeCStream(&blockStream);
@@ -1455,16 +1639,77 @@ size_t ZSTD_encodeSequences(
1455
1639
  }
1456
1640
  }
1457
1641
 
1642
+ static size_t
1643
+ ZSTD_encodeSequences_default(
1644
+ void* dst, size_t dstCapacity,
1645
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1646
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1647
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1648
+ seqDef const* sequences, size_t nbSeq, int longOffsets)
1649
+ {
1650
+ return ZSTD_encodeSequences_body(dst, dstCapacity,
1651
+ CTable_MatchLength, mlCodeTable,
1652
+ CTable_OffsetBits, ofCodeTable,
1653
+ CTable_LitLength, llCodeTable,
1654
+ sequences, nbSeq, longOffsets);
1655
+ }
1656
+
1657
+
1658
+ #if DYNAMIC_BMI2
1659
+
1660
+ static TARGET_ATTRIBUTE("bmi2") size_t
1661
+ ZSTD_encodeSequences_bmi2(
1662
+ void* dst, size_t dstCapacity,
1663
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1664
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1665
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1666
+ seqDef const* sequences, size_t nbSeq, int longOffsets)
1667
+ {
1668
+ return ZSTD_encodeSequences_body(dst, dstCapacity,
1669
+ CTable_MatchLength, mlCodeTable,
1670
+ CTable_OffsetBits, ofCodeTable,
1671
+ CTable_LitLength, llCodeTable,
1672
+ sequences, nbSeq, longOffsets);
1673
+ }
1674
+
1675
+ #endif
1676
+
1677
+ size_t ZSTD_encodeSequences(
1678
+ void* dst, size_t dstCapacity,
1679
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1680
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1681
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1682
+ seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
1683
+ {
1684
+ #if DYNAMIC_BMI2
1685
+ if (bmi2) {
1686
+ return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
1687
+ CTable_MatchLength, mlCodeTable,
1688
+ CTable_OffsetBits, ofCodeTable,
1689
+ CTable_LitLength, llCodeTable,
1690
+ sequences, nbSeq, longOffsets);
1691
+ }
1692
+ #endif
1693
+ (void)bmi2;
1694
+ return ZSTD_encodeSequences_default(dst, dstCapacity,
1695
+ CTable_MatchLength, mlCodeTable,
1696
+ CTable_OffsetBits, ofCodeTable,
1697
+ CTable_LitLength, llCodeTable,
1698
+ sequences, nbSeq, longOffsets);
1699
+ }
1700
+
1458
1701
  MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1459
- ZSTD_entropyCTables_t* entropy,
1460
- ZSTD_compressionParameters const* cParams,
1461
- void* dst, size_t dstCapacity)
1702
+ ZSTD_entropyCTables_t const* prevEntropy,
1703
+ ZSTD_entropyCTables_t* nextEntropy,
1704
+ ZSTD_CCtx_params const* cctxParams,
1705
+ void* dst, size_t dstCapacity, U32* workspace,
1706
+ const int bmi2)
1462
1707
  {
1463
- const int longOffsets = cParams->windowLog > STREAM_ACCUMULATOR_MIN;
1708
+ const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
1464
1709
  U32 count[MaxSeq+1];
1465
- FSE_CTable* CTable_LitLength = entropy->litlengthCTable;
1466
- FSE_CTable* CTable_OffsetBits = entropy->offcodeCTable;
1467
- FSE_CTable* CTable_MatchLength = entropy->matchlengthCTable;
1710
+ FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
1711
+ FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
1712
+ FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
1468
1713
  U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
1469
1714
  const seqDef* const sequences = seqStorePtr->sequencesStart;
1470
1715
  const BYTE* const ofCodeTable = seqStorePtr->ofCode;
@@ -1476,13 +1721,17 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1476
1721
  size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
1477
1722
  BYTE* seqHead;
1478
1723
 
1479
- ZSTD_STATIC_ASSERT(sizeof(entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
1724
+ ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
1480
1725
 
1481
1726
  /* Compress literals */
1482
1727
  { const BYTE* const literals = seqStorePtr->litStart;
1483
1728
  size_t const litSize = seqStorePtr->lit - literals;
1484
1729
  size_t const cSize = ZSTD_compressLiterals(
1485
- entropy, cParams->strategy, op, dstCapacity, literals, litSize);
1730
+ prevEntropy, nextEntropy,
1731
+ cctxParams->cParams.strategy, cctxParams->disableLiteralCompression,
1732
+ op, dstCapacity,
1733
+ literals, litSize,
1734
+ workspace, bmi2);
1486
1735
  if (ZSTD_isError(cSize))
1487
1736
  return cSize;
1488
1737
  assert(cSize <= dstCapacity);
@@ -1497,7 +1746,15 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1497
1746
  op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
1498
1747
  else
1499
1748
  op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1500
- if (nbSeq==0) return op - ostart;
1749
+ 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;
1757
+ }
1501
1758
 
1502
1759
  /* seqHead : flags for FSE encoding type */
1503
1760
  seqHead = op++;
@@ -1506,36 +1763,42 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1506
1763
  ZSTD_seqToCodes(seqStorePtr);
1507
1764
  /* build CTable for Literal Lengths */
1508
1765
  { U32 max = MaxLL;
1509
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
1766
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace);
1510
1767
  DEBUGLOG(5, "Building LL table");
1511
- LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
1768
+ nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
1769
+ LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
1512
1770
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
1513
1771
  count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
1514
- entropy->workspace, sizeof(entropy->workspace));
1772
+ prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
1773
+ workspace, HUF_WORKSPACE_SIZE);
1515
1774
  if (ZSTD_isError(countSize)) return countSize;
1516
1775
  op += countSize;
1517
1776
  } }
1518
1777
  /* build CTable for Offsets */
1519
1778
  { U32 max = MaxOff;
1520
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
1779
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace);
1521
1780
  /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
1522
1781
  ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
1523
1782
  DEBUGLOG(5, "Building OF table");
1524
- Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
1783
+ nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
1784
+ Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
1525
1785
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
1526
1786
  count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
1527
- entropy->workspace, sizeof(entropy->workspace));
1787
+ prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
1788
+ workspace, HUF_WORKSPACE_SIZE);
1528
1789
  if (ZSTD_isError(countSize)) return countSize;
1529
1790
  op += countSize;
1530
1791
  } }
1531
1792
  /* build CTable for MatchLengths */
1532
1793
  { U32 max = MaxML;
1533
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
1794
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace);
1534
1795
  DEBUGLOG(5, "Building ML table");
1535
- MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
1796
+ nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
1797
+ MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
1536
1798
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
1537
1799
  count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
1538
- entropy->workspace, sizeof(entropy->workspace));
1800
+ prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
1801
+ workspace, HUF_WORKSPACE_SIZE);
1539
1802
  if (ZSTD_isError(countSize)) return countSize;
1540
1803
  op += countSize;
1541
1804
  } }
@@ -1548,7 +1811,7 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1548
1811
  CTable_OffsetBits, ofCodeTable,
1549
1812
  CTable_LitLength, llCodeTable,
1550
1813
  sequences, nbSeq,
1551
- longOffsets);
1814
+ longOffsets, bmi2);
1552
1815
  if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
1553
1816
  op += bitstreamSize;
1554
1817
  }
@@ -1557,48 +1820,40 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1557
1820
  }
1558
1821
 
1559
1822
  MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1560
- ZSTD_entropyCTables_t* entropy,
1561
- ZSTD_compressionParameters const* cParams,
1823
+ ZSTD_entropyCTables_t const* prevEntropy,
1824
+ ZSTD_entropyCTables_t* nextEntropy,
1825
+ ZSTD_CCtx_params const* cctxParams,
1562
1826
  void* dst, size_t dstCapacity,
1563
- size_t srcSize)
1827
+ size_t srcSize, U32* workspace, int bmi2)
1564
1828
  {
1565
- size_t const cSize = ZSTD_compressSequences_internal(seqStorePtr, entropy, cParams,
1566
- dst, dstCapacity);
1567
- /* If the srcSize <= dstCapacity, then there is enough space to write a
1568
- * raw uncompressed block. Since we ran out of space, the block must not
1569
- * be compressible, so fall back to a raw uncompressed block.
1829
+ size_t const cSize = ZSTD_compressSequences_internal(
1830
+ seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity,
1831
+ workspace, bmi2);
1832
+ /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
1833
+ * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
1570
1834
  */
1571
- int const uncompressibleError = (cSize == ERROR(dstSize_tooSmall)) && (srcSize <= dstCapacity);
1572
- if (ZSTD_isError(cSize) && !uncompressibleError)
1573
- return cSize;
1835
+ if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
1836
+ return 0; /* block not compressed */
1837
+ if (ZSTD_isError(cSize)) return cSize;
1838
+
1839
+ /* Check compressibility */
1840
+ { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize); /* note : fixed formula, maybe should depend on compression level, or strategy */
1841
+ if (cSize >= maxCSize) return 0; /* block not compressed */
1842
+ }
1843
+
1574
1844
  /* We check that dictionaries have offset codes available for the first
1575
1845
  * block. After the first block, the offcode table might not have large
1576
1846
  * enough codes to represent the offsets in the data.
1577
1847
  */
1578
- if (entropy->offcode_repeatMode == FSE_repeat_valid)
1579
- entropy->offcode_repeatMode = FSE_repeat_check;
1580
-
1581
- /* Check compressibility */
1582
- { size_t const minGain = ZSTD_minGain(srcSize); /* note : fixed formula, maybe should depend on compression level, or strategy */
1583
- size_t const maxCSize = srcSize - minGain;
1584
- if (cSize >= maxCSize || uncompressibleError) {
1585
- entropy->hufCTable_repeatMode = HUF_repeat_none;
1586
- entropy->offcode_repeatMode = FSE_repeat_none;
1587
- entropy->matchlength_repeatMode = FSE_repeat_none;
1588
- entropy->litlength_repeatMode = FSE_repeat_none;
1589
- return 0; /* block not compressed */
1590
- } }
1591
- assert(!ZSTD_isError(cSize));
1848
+ if (nextEntropy->offcode_repeatMode == FSE_repeat_valid)
1849
+ nextEntropy->offcode_repeatMode = FSE_repeat_check;
1592
1850
 
1593
- /* block is compressed => confirm repcodes in history */
1594
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->rep[i] = seqStorePtr->repToConfirm[i]; }
1595
1851
  return cSize;
1596
1852
  }
1597
1853
 
1598
1854
  /* ZSTD_selectBlockCompressor() :
1599
1855
  * Not static, but internal use only (used by long distance matcher)
1600
1856
  * assumption : strat is a valid strategy */
1601
- typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
1602
1857
  ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
1603
1858
  {
1604
1859
  static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
@@ -1632,32 +1887,83 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
1632
1887
  ssPtr->longLengthID = 0;
1633
1888
  }
1634
1889
 
1635
- static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1890
+ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
1891
+ void* dst, size_t dstCapacity,
1892
+ const void* src, size_t srcSize)
1636
1893
  {
1637
- DEBUGLOG(5, "ZSTD_compressBlock_internal : dstCapacity = %u", (U32)dstCapacity);
1638
- if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1)
1894
+ 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);
1897
+ if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
1898
+ ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.searchLength);
1639
1899
  return 0; /* don't even attempt compression below a certain srcSize */
1900
+ }
1640
1901
  ZSTD_resetSeqStore(&(zc->seqStore));
1641
1902
 
1642
1903
  /* limited update after a very long match */
1643
- { const BYTE* const base = zc->base;
1904
+ { const BYTE* const base = ms->window.base;
1644
1905
  const BYTE* const istart = (const BYTE*)src;
1645
1906
  const U32 current = (U32)(istart-base);
1646
- if (current > zc->nextToUpdate + 384)
1647
- zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384));
1907
+ if (current > ms->nextToUpdate + 384)
1908
+ ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384));
1648
1909
  }
1649
- /* find and store sequences */
1650
- { U32 const extDict = zc->lowLimit < zc->dictLimit;
1651
- const ZSTD_blockCompressor blockCompressor =
1652
- zc->appliedParams.ldmParams.enableLdm
1653
- ? (extDict ? ZSTD_compressBlock_ldm_extDict : ZSTD_compressBlock_ldm)
1654
- : ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
1655
- size_t const lastLLSize = blockCompressor(zc, src, srcSize);
1656
- const BYTE* const anchor = (const BYTE*)src + srcSize - lastLLSize;
1657
- ZSTD_storeLastLiterals(&zc->seqStore, anchor, lastLLSize);
1910
+
1911
+ /* select and store sequences */
1912
+ { U32 const extDict = ZSTD_window_hasExtDict(ms->window);
1913
+ size_t lastLLSize;
1914
+ { int i;
1915
+ for (i = 0; i < ZSTD_REP_NUM; ++i)
1916
+ zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];
1917
+ }
1918
+ if (zc->externSeqStore.pos < zc->externSeqStore.size) {
1919
+ assert(!zc->appliedParams.ldmParams.enableLdm);
1920
+ /* Updates ldmSeqStore.pos */
1921
+ lastLLSize =
1922
+ ZSTD_ldm_blockCompress(&zc->externSeqStore,
1923
+ ms, &zc->seqStore,
1924
+ zc->blockState.nextCBlock->rep,
1925
+ &zc->appliedParams.cParams,
1926
+ src, srcSize, extDict);
1927
+ assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
1928
+ } else if (zc->appliedParams.ldmParams.enableLdm) {
1929
+ rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
1930
+
1931
+ ldmSeqStore.seq = zc->ldmSequences;
1932
+ ldmSeqStore.capacity = zc->maxNbLdmSequences;
1933
+ /* Updates ldmSeqStore.size */
1934
+ CHECK_F(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
1935
+ &zc->appliedParams.ldmParams,
1936
+ src, srcSize));
1937
+ /* Updates ldmSeqStore.pos */
1938
+ lastLLSize =
1939
+ ZSTD_ldm_blockCompress(&ldmSeqStore,
1940
+ ms, &zc->seqStore,
1941
+ zc->blockState.nextCBlock->rep,
1942
+ &zc->appliedParams.cParams,
1943
+ src, srcSize, extDict);
1944
+ assert(ldmSeqStore.pos == ldmSeqStore.size);
1945
+ } else { /* not long range mode */
1946
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
1947
+ lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, &zc->appliedParams.cParams, src, srcSize);
1948
+ }
1949
+ { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
1950
+ ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
1951
+ } }
1952
+
1953
+ /* encode sequences and literals */
1954
+ { size_t const cSize = ZSTD_compressSequences(&zc->seqStore,
1955
+ &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
1956
+ &zc->appliedParams,
1957
+ dst, dstCapacity,
1958
+ srcSize, zc->entropyWorkspace, zc->bmi2);
1959
+ if (ZSTD_isError(cSize) || cSize == 0) return cSize;
1960
+ /* confirm repcodes and entropy tables */
1961
+ { ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
1962
+ zc->blockState.prevCBlock = zc->blockState.nextCBlock;
1963
+ zc->blockState.nextCBlock = tmp;
1964
+ }
1965
+ return cSize;
1658
1966
  }
1659
- /* encode */
1660
- return ZSTD_compressSequences(&zc->seqStore, zc->entropy, &zc->appliedParams.cParams, dst, dstCapacity, srcSize);
1661
1967
  }
1662
1968
 
1663
1969
 
@@ -1686,54 +1992,27 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
1686
1992
  XXH64_update(&cctx->xxhState, src, srcSize);
1687
1993
 
1688
1994
  while (remaining) {
1995
+ ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
1689
1996
  U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
1690
1997
 
1691
1998
  if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE)
1692
1999
  return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
1693
2000
  if (remaining < blockSize) blockSize = remaining;
1694
2001
 
1695
- /* preemptive overflow correction:
1696
- * 1. correction is large enough:
1697
- * lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog - blockSize
1698
- * 1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
1699
- *
1700
- * current - newCurrent
1701
- * > (3<<29 + 1<<windowLog - blockSize) - (1<<windowLog + 1<<chainLog)
1702
- * > (3<<29 - blockSize) - (1<<chainLog)
1703
- * > (3<<29 - blockSize) - (1<<30) (NOTE: chainLog <= 30)
1704
- * > 1<<29 - 1<<17
1705
- *
1706
- * 2. (ip+blockSize - cctx->base) doesn't overflow:
1707
- * In 32 bit mode we limit windowLog to 30 so we don't get
1708
- * differences larger than 1<<31-1.
1709
- * 3. cctx->lowLimit < 1<<32:
1710
- * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
1711
- */
1712
- if (cctx->lowLimit > (3U<<29)) {
1713
- U32 const cycleMask = ((U32)1 << ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy)) - 1;
1714
- U32 const current = (U32)(ip - cctx->base);
1715
- U32 const newCurrent = (current & cycleMask) + ((U32)1 << cctx->appliedParams.cParams.windowLog);
1716
- U32 const correction = current - newCurrent;
2002
+ if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) {
2003
+ U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2004
+ U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
1717
2005
  ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
1718
2006
  ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
1719
2007
  ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
1720
- assert(current > newCurrent);
1721
- assert(correction > 1<<28); /* Loose bound, should be about 1<<29 */
2008
+
1722
2009
  ZSTD_reduceIndex(cctx, correction);
1723
- cctx->base += correction;
1724
- cctx->dictBase += correction;
1725
- cctx->lowLimit -= correction;
1726
- cctx->dictLimit -= correction;
1727
- if (cctx->nextToUpdate < correction) cctx->nextToUpdate = 0;
1728
- else cctx->nextToUpdate -= correction;
1729
- DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x\n", correction, cctx->lowLimit);
1730
- }
1731
- /* enforce maxDist */
1732
- if ((U32)(ip+blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) {
1733
- U32 const newLowLimit = (U32)(ip+blockSize - cctx->base) - maxDist;
1734
- if (cctx->lowLimit < newLowLimit) cctx->lowLimit = newLowLimit;
1735
- if (cctx->dictLimit < cctx->lowLimit) cctx->dictLimit = cctx->lowLimit;
2010
+ if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2011
+ else ms->nextToUpdate -= correction;
2012
+ ms->loadedDictEnd = 0;
1736
2013
  }
2014
+ ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd);
2015
+ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
1737
2016
 
1738
2017
  { size_t cSize = ZSTD_compressBlock_internal(cctx,
1739
2018
  op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
@@ -1810,16 +2089,44 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
1810
2089
  return pos;
1811
2090
  }
1812
2091
 
2092
+ /* ZSTD_writeLastEmptyBlock() :
2093
+ * output an empty Block with end-of-frame mark to complete a frame
2094
+ * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
2095
+ * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
2096
+ */
2097
+ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
2098
+ {
2099
+ if (dstCapacity < ZSTD_blockHeaderSize) return ERROR(dstSize_tooSmall);
2100
+ { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
2101
+ MEM_writeLE24(dst, cBlockHeader24);
2102
+ return ZSTD_blockHeaderSize;
2103
+ }
2104
+ }
2105
+
2106
+ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
2107
+ {
2108
+ if (cctx->stage != ZSTDcs_init)
2109
+ return ERROR(stage_wrong);
2110
+ if (cctx->appliedParams.ldmParams.enableLdm)
2111
+ return ERROR(parameter_unsupported);
2112
+ cctx->externSeqStore.seq = seq;
2113
+ cctx->externSeqStore.size = nbSeq;
2114
+ cctx->externSeqStore.capacity = nbSeq;
2115
+ cctx->externSeqStore.pos = 0;
2116
+ return 0;
2117
+ }
2118
+
1813
2119
 
1814
2120
  static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
1815
2121
  void* dst, size_t dstCapacity,
1816
2122
  const void* src, size_t srcSize,
1817
2123
  U32 frame, U32 lastFrameChunk)
1818
2124
  {
1819
- const BYTE* const ip = (const BYTE*) src;
2125
+ ZSTD_matchState_t* ms = &cctx->blockState.matchState;
1820
2126
  size_t fhSize = 0;
1821
2127
 
1822
- DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u", cctx->stage);
2128
+ DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
2129
+ cctx->stage, (U32)srcSize);
1823
2130
  if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
1824
2131
 
1825
2132
  if (frame && (cctx->stage==ZSTDcs_init)) {
@@ -1833,26 +2140,11 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
1833
2140
 
1834
2141
  if (!srcSize) return fhSize; /* do not generate an empty block if no input */
1835
2142
 
1836
- /* Check if blocks follow each other */
1837
- if (src != cctx->nextSrc) {
1838
- /* not contiguous */
1839
- size_t const distanceFromBase = (size_t)(cctx->nextSrc - cctx->base);
1840
- cctx->lowLimit = cctx->dictLimit;
1841
- assert(distanceFromBase == (size_t)(U32)distanceFromBase); /* should never overflow */
1842
- cctx->dictLimit = (U32)distanceFromBase;
1843
- cctx->dictBase = cctx->base;
1844
- cctx->base = ip - distanceFromBase;
1845
- cctx->nextToUpdate = cctx->dictLimit;
1846
- if (cctx->dictLimit - cctx->lowLimit < HASH_READ_SIZE) cctx->lowLimit = cctx->dictLimit; /* too small extDict */
1847
- }
1848
- cctx->nextSrc = ip + srcSize;
1849
-
1850
- /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
1851
- if ((ip+srcSize > cctx->dictBase + cctx->lowLimit) & (ip < cctx->dictBase + cctx->dictLimit)) {
1852
- ptrdiff_t const highInputIdx = (ip + srcSize) - cctx->dictBase;
1853
- U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)cctx->dictLimit) ? cctx->dictLimit : (U32)highInputIdx;
1854
- cctx->lowLimit = lowLimitMax;
2143
+ if (!ZSTD_window_update(&ms->window, src, srcSize)) {
2144
+ ms->nextToUpdate = ms->window.dictLimit;
1855
2145
  }
2146
+ if (cctx->appliedParams.ldmParams.enableLdm)
2147
+ ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
1856
2148
 
1857
2149
  DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (U32)cctx->blockSize);
1858
2150
  { size_t const cSize = frame ?
@@ -1860,6 +2152,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
1860
2152
  ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
1861
2153
  if (ZSTD_isError(cSize)) return cSize;
1862
2154
  cctx->consumedSrcSize += srcSize;
2155
+ cctx->producedCSize += (cSize + fhSize);
2156
+ if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
2157
+ if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) {
2158
+ DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u",
2159
+ (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
2160
+ return ERROR(srcSize_wrong);
2161
+ }
2162
+ }
1863
2163
  return cSize + fhSize;
1864
2164
  }
1865
2165
  }
@@ -1868,14 +2168,15 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
1868
2168
  void* dst, size_t dstCapacity,
1869
2169
  const void* src, size_t srcSize)
1870
2170
  {
2171
+ DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (U32)srcSize);
1871
2172
  return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);
1872
2173
  }
1873
2174
 
1874
2175
 
1875
2176
  size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
1876
2177
  {
1877
- ZSTD_compressionParameters const cParams =
1878
- ZSTD_getCParamsFromCCtxParams(cctx->appliedParams, 0, 0);
2178
+ ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams;
2179
+ assert(!ZSTD_checkCParams(cParams));
1879
2180
  return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
1880
2181
  }
1881
2182
 
@@ -1889,50 +2190,45 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
1889
2190
  /*! ZSTD_loadDictionaryContent() :
1890
2191
  * @return : 0, or an error code
1891
2192
  */
1892
- static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
2193
+ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* src, size_t srcSize)
1893
2194
  {
1894
2195
  const BYTE* const ip = (const BYTE*) src;
1895
2196
  const BYTE* const iend = ip + srcSize;
2197
+ ZSTD_compressionParameters const* cParams = &params->cParams;
1896
2198
 
1897
- /* input becomes current prefix */
1898
- zc->lowLimit = zc->dictLimit;
1899
- zc->dictLimit = (U32)(zc->nextSrc - zc->base);
1900
- zc->dictBase = zc->base;
1901
- zc->base = ip - zc->dictLimit;
1902
- zc->nextToUpdate = zc->dictLimit;
1903
- zc->loadedDictEnd = zc->appliedParams.forceWindow ? 0 : (U32)(iend - zc->base);
2199
+ ZSTD_window_update(&ms->window, src, srcSize);
2200
+ ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
1904
2201
 
1905
- zc->nextSrc = iend;
1906
2202
  if (srcSize <= HASH_READ_SIZE) return 0;
1907
2203
 
1908
- switch(zc->appliedParams.cParams.strategy)
2204
+ switch(params->cParams.strategy)
1909
2205
  {
1910
2206
  case ZSTD_fast:
1911
- ZSTD_fillHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
2207
+ ZSTD_fillHashTable(ms, cParams, iend);
1912
2208
  break;
1913
2209
  case ZSTD_dfast:
1914
- ZSTD_fillDoubleHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
2210
+ ZSTD_fillDoubleHashTable(ms, cParams, iend);
1915
2211
  break;
1916
2212
 
1917
2213
  case ZSTD_greedy:
1918
2214
  case ZSTD_lazy:
1919
2215
  case ZSTD_lazy2:
1920
2216
  if (srcSize >= HASH_READ_SIZE)
1921
- ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->appliedParams.cParams.searchLength);
2217
+ ZSTD_insertAndFindFirstIndex(ms, cParams, iend-HASH_READ_SIZE);
1922
2218
  break;
1923
2219
 
1924
- case ZSTD_btlazy2:
2220
+ case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
1925
2221
  case ZSTD_btopt:
1926
2222
  case ZSTD_btultra:
1927
2223
  if (srcSize >= HASH_READ_SIZE)
1928
- ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, (U32)1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
2224
+ ZSTD_updateTree(ms, cParams, iend-HASH_READ_SIZE, iend);
1929
2225
  break;
1930
2226
 
1931
2227
  default:
1932
2228
  assert(0); /* not possible : not a valid strategy id */
1933
2229
  }
1934
2230
 
1935
- zc->nextToUpdate = (U32)(iend - zc->base);
2231
+ ms->nextToUpdate = (U32)(iend - ms->window.base);
1936
2232
  return 0;
1937
2233
  }
1938
2234
 
@@ -1956,25 +2252,26 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym
1956
2252
  * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
1957
2253
  */
1958
2254
  /*! ZSTD_loadZstdDictionary() :
1959
- * @return : 0, or an error code
2255
+ * @return : dictID, or an error code
1960
2256
  * assumptions : magic number supposed already checked
1961
2257
  * dictSize supposed > 8
1962
2258
  */
1963
- static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
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)
1964
2260
  {
1965
2261
  const BYTE* dictPtr = (const BYTE*)dict;
1966
2262
  const BYTE* const dictEnd = dictPtr + dictSize;
1967
2263
  short offcodeNCount[MaxOff+1];
1968
2264
  unsigned offcodeMaxValue = MaxOff;
2265
+ size_t dictID;
1969
2266
 
1970
- ZSTD_STATIC_ASSERT(sizeof(cctx->entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
2267
+ ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
1971
2268
 
1972
2269
  dictPtr += 4; /* skip magic number */
1973
- cctx->dictID = cctx->appliedParams.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
2270
+ dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
1974
2271
  dictPtr += 4;
1975
2272
 
1976
2273
  { unsigned maxSymbolValue = 255;
1977
- size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)cctx->entropy->hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
2274
+ size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
1978
2275
  if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
1979
2276
  if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
1980
2277
  dictPtr += hufHeaderSize;
@@ -1985,7 +2282,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
1985
2282
  if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
1986
2283
  if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
1987
2284
  /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
1988
- CHECK_E( FSE_buildCTable_wksp(cctx->entropy->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, cctx->entropy->workspace, sizeof(cctx->entropy->workspace)),
2285
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, workspace, HUF_WORKSPACE_SIZE),
1989
2286
  dictionary_corrupted);
1990
2287
  dictPtr += offcodeHeaderSize;
1991
2288
  }
@@ -1997,7 +2294,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
1997
2294
  if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
1998
2295
  /* Every match length code must have non-zero probability */
1999
2296
  CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
2000
- CHECK_E( FSE_buildCTable_wksp(cctx->entropy->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, cctx->entropy->workspace, sizeof(cctx->entropy->workspace)),
2297
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE),
2001
2298
  dictionary_corrupted);
2002
2299
  dictPtr += matchlengthHeaderSize;
2003
2300
  }
@@ -2009,15 +2306,15 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
2009
2306
  if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
2010
2307
  /* Every literal length code must have non-zero probability */
2011
2308
  CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
2012
- CHECK_E( FSE_buildCTable_wksp(cctx->entropy->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, cctx->entropy->workspace, sizeof(cctx->entropy->workspace)),
2309
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE),
2013
2310
  dictionary_corrupted);
2014
2311
  dictPtr += litlengthHeaderSize;
2015
2312
  }
2016
2313
 
2017
2314
  if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
2018
- cctx->seqStore.rep[0] = MEM_readLE32(dictPtr+0);
2019
- cctx->seqStore.rep[1] = MEM_readLE32(dictPtr+4);
2020
- cctx->seqStore.rep[2] = MEM_readLE32(dictPtr+8);
2315
+ bs->rep[0] = MEM_readLE32(dictPtr+0);
2316
+ bs->rep[1] = MEM_readLE32(dictPtr+4);
2317
+ bs->rep[2] = MEM_readLE32(dictPtr+8);
2021
2318
  dictPtr += 12;
2022
2319
 
2023
2320
  { size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
@@ -2031,50 +2328,55 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
2031
2328
  /* All repCodes must be <= dictContentSize and != 0*/
2032
2329
  { U32 u;
2033
2330
  for (u=0; u<3; u++) {
2034
- if (cctx->seqStore.rep[u] == 0) return ERROR(dictionary_corrupted);
2035
- if (cctx->seqStore.rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
2331
+ if (bs->rep[u] == 0) return ERROR(dictionary_corrupted);
2332
+ if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
2036
2333
  } }
2037
2334
 
2038
- cctx->entropy->hufCTable_repeatMode = HUF_repeat_valid;
2039
- cctx->entropy->offcode_repeatMode = FSE_repeat_valid;
2040
- cctx->entropy->matchlength_repeatMode = FSE_repeat_valid;
2041
- cctx->entropy->litlength_repeatMode = FSE_repeat_valid;
2042
- return ZSTD_loadDictionaryContent(cctx, dictPtr, dictContentSize);
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));
2340
+ return dictID;
2043
2341
  }
2044
2342
  }
2045
2343
 
2046
2344
  /** ZSTD_compress_insertDictionary() :
2047
- * @return : 0, or an error code */
2048
- static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx,
2345
+ * @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,
2049
2348
  const void* dict, size_t dictSize,
2050
- ZSTD_dictMode_e dictMode)
2349
+ ZSTD_dictContentType_e dictContentType,
2350
+ void* workspace)
2051
2351
  {
2052
2352
  DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
2053
2353
  if ((dict==NULL) || (dictSize<=8)) return 0;
2054
2354
 
2355
+ ZSTD_reset_compressedBlockState(bs);
2356
+
2055
2357
  /* dict restricted modes */
2056
- if (dictMode==ZSTD_dm_rawContent)
2057
- return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
2358
+ if (dictContentType == ZSTD_dct_rawContent)
2359
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
2058
2360
 
2059
2361
  if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
2060
- if (dictMode == ZSTD_dm_auto) {
2362
+ if (dictContentType == ZSTD_dct_auto) {
2061
2363
  DEBUGLOG(4, "raw content dictionary detected");
2062
- return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
2364
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
2063
2365
  }
2064
- if (dictMode == ZSTD_dm_fullDict)
2366
+ if (dictContentType == ZSTD_dct_fullDict)
2065
2367
  return ERROR(dictionary_wrong);
2066
2368
  assert(0); /* impossible */
2067
2369
  }
2068
2370
 
2069
2371
  /* dict as full zstd dictionary */
2070
- return ZSTD_loadZstdDictionary(cctx, dict, dictSize);
2372
+ return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, workspace);
2071
2373
  }
2072
2374
 
2073
2375
  /*! ZSTD_compressBegin_internal() :
2074
2376
  * @return : 0, or an error code */
2075
2377
  size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2076
2378
  const void* dict, size_t dictSize,
2077
- ZSTD_dictMode_e dictMode,
2379
+ ZSTD_dictContentType_e dictContentType,
2078
2380
  const ZSTD_CDict* cdict,
2079
2381
  ZSTD_CCtx_params params, U64 pledgedSrcSize,
2080
2382
  ZSTD_buffered_policy_e zbuff)
@@ -2086,19 +2388,26 @@ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2086
2388
 
2087
2389
  if (cdict && cdict->dictContentSize>0) {
2088
2390
  cctx->requestedParams = params;
2089
- return ZSTD_copyCCtx_internal(cctx, cdict->refContext,
2090
- params.cParams.windowLog, params.fParams, pledgedSrcSize,
2091
- zbuff);
2391
+ return ZSTD_resetCCtx_usingCDict(cctx, cdict, params.cParams.windowLog,
2392
+ params.fParams, pledgedSrcSize, zbuff);
2092
2393
  }
2093
2394
 
2094
2395
  CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
2095
2396
  ZSTDcrp_continue, zbuff) );
2096
- return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
2397
+ {
2398
+ size_t const dictID = ZSTD_compress_insertDictionary(
2399
+ cctx->blockState.prevCBlock, &cctx->blockState.matchState,
2400
+ &params, dict, dictSize, dictContentType, cctx->entropyWorkspace);
2401
+ if (ZSTD_isError(dictID)) return dictID;
2402
+ assert(dictID <= (size_t)(U32)-1);
2403
+ cctx->dictID = (U32)dictID;
2404
+ }
2405
+ return 0;
2097
2406
  }
2098
2407
 
2099
2408
  size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
2100
2409
  const void* dict, size_t dictSize,
2101
- ZSTD_dictMode_e dictMode,
2410
+ ZSTD_dictContentType_e dictContentType,
2102
2411
  const ZSTD_CDict* cdict,
2103
2412
  ZSTD_CCtx_params params,
2104
2413
  unsigned long long pledgedSrcSize)
@@ -2107,7 +2416,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
2107
2416
  /* compression parameters verification and optimization */
2108
2417
  CHECK_F( ZSTD_checkCParams(params.cParams) );
2109
2418
  return ZSTD_compressBegin_internal(cctx,
2110
- dict, dictSize, dictMode,
2419
+ dict, dictSize, dictContentType,
2111
2420
  cdict,
2112
2421
  params, pledgedSrcSize,
2113
2422
  ZSTDb_not_buffered);
@@ -2122,18 +2431,18 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
2122
2431
  ZSTD_CCtx_params const cctxParams =
2123
2432
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2124
2433
  return ZSTD_compressBegin_advanced_internal(cctx,
2125
- dict, dictSize, ZSTD_dm_auto,
2434
+ dict, dictSize, ZSTD_dct_auto,
2126
2435
  NULL /*cdict*/,
2127
2436
  cctxParams, pledgedSrcSize);
2128
2437
  }
2129
2438
 
2130
2439
  size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
2131
2440
  {
2132
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
2441
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
2133
2442
  ZSTD_CCtx_params const cctxParams =
2134
2443
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2135
- DEBUGLOG(4, "ZSTD_compressBegin_usingDict");
2136
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
2444
+ DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (U32)dictSize);
2445
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL,
2137
2446
  cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
2138
2447
  }
2139
2448
 
@@ -2152,7 +2461,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
2152
2461
  BYTE* op = ostart;
2153
2462
  size_t fhSize = 0;
2154
2463
 
2155
- DEBUGLOG(5, "ZSTD_writeEpilogue");
2464
+ DEBUGLOG(4, "ZSTD_writeEpilogue");
2156
2465
  if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
2157
2466
 
2158
2467
  /* special case : empty frame */
@@ -2176,6 +2485,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
2176
2485
  if (cctx->appliedParams.fParams.checksumFlag) {
2177
2486
  U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
2178
2487
  if (dstCapacity<4) return ERROR(dstSize_tooSmall);
2488
+ DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", checksum);
2179
2489
  MEM_writeLE32(op, checksum);
2180
2490
  op += 4;
2181
2491
  }
@@ -2184,7 +2494,6 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
2184
2494
  return op-ostart;
2185
2495
  }
2186
2496
 
2187
-
2188
2497
  size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
2189
2498
  void* dst, size_t dstCapacity,
2190
2499
  const void* src, size_t srcSize)
@@ -2242,25 +2551,27 @@ size_t ZSTD_compress_advanced_internal(
2242
2551
  const void* dict,size_t dictSize,
2243
2552
  ZSTD_CCtx_params params)
2244
2553
  {
2245
- DEBUGLOG(4, "ZSTD_compress_advanced_internal");
2246
- CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
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,
2247
2557
  params, srcSize, ZSTDb_not_buffered) );
2248
2558
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
2249
2559
  }
2250
2560
 
2251
- size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
2561
+ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
2252
2562
  const void* dict, size_t dictSize, int compressionLevel)
2253
2563
  {
2254
- ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0);
2255
- params.fParams.contentSizeFlag = 1;
2256
- DEBUGLOG(4, "ZSTD_compress_usingDict (level=%i, srcSize=%u, dictSize=%u)",
2257
- compressionLevel, (U32)srcSize, (U32)dictSize);
2258
- return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2564
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0);
2565
+ ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2566
+ assert(params.fParams.contentSizeFlag == 1);
2567
+ ZSTD_CCtxParam_setParameter(&cctxParams, ZSTD_p_compressLiterals, compressionLevel>=0);
2568
+ return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams);
2259
2569
  }
2260
2570
 
2261
- size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
2571
+ size_t ZSTD_compressCCtx (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
2262
2572
  {
2263
- return ZSTD_compress_usingDict(ctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
2573
+ DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (U32)srcSize);
2574
+ return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
2264
2575
  }
2265
2576
 
2266
2577
  size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
@@ -2284,9 +2595,7 @@ size_t ZSTD_estimateCDictSize_advanced(
2284
2595
  ZSTD_dictLoadMethod_e dictLoadMethod)
2285
2596
  {
2286
2597
  DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
2287
- DEBUGLOG(5, "CCtx estimate : %u",
2288
- (U32)ZSTD_estimateCCtxSize_usingCParams(cParams));
2289
- return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_usingCParams(cParams)
2598
+ return sizeof(ZSTD_CDict) + HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
2290
2599
  + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
2291
2600
  }
2292
2601
 
@@ -2300,23 +2609,24 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
2300
2609
  {
2301
2610
  if (cdict==NULL) return 0; /* support sizeof on NULL */
2302
2611
  DEBUGLOG(5, "sizeof(*cdict) : %u", (U32)sizeof(*cdict));
2303
- DEBUGLOG(5, "ZSTD_sizeof_CCtx : %u", (U32)ZSTD_sizeof_CCtx(cdict->refContext));
2304
- return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
2612
+ return cdict->workspaceSize + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
2305
2613
  }
2306
2614
 
2307
2615
  static size_t ZSTD_initCDict_internal(
2308
2616
  ZSTD_CDict* cdict,
2309
2617
  const void* dictBuffer, size_t dictSize,
2310
2618
  ZSTD_dictLoadMethod_e dictLoadMethod,
2311
- ZSTD_dictMode_e dictMode,
2619
+ ZSTD_dictContentType_e dictContentType,
2312
2620
  ZSTD_compressionParameters cParams)
2313
2621
  {
2314
- DEBUGLOG(3, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
2622
+ DEBUGLOG(3, "ZSTD_initCDict_internal, dictContentType %u", (U32)dictContentType);
2623
+ assert(!ZSTD_checkCParams(cParams));
2624
+ cdict->cParams = cParams;
2315
2625
  if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
2316
2626
  cdict->dictBuffer = NULL;
2317
2627
  cdict->dictContent = dictBuffer;
2318
2628
  } else {
2319
- void* const internalBuffer = ZSTD_malloc(dictSize, cdict->refContext->customMem);
2629
+ void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
2320
2630
  cdict->dictBuffer = internalBuffer;
2321
2631
  cdict->dictContent = internalBuffer;
2322
2632
  if (!internalBuffer) return ERROR(memory_allocation);
@@ -2324,13 +2634,31 @@ static size_t ZSTD_initCDict_internal(
2324
2634
  }
2325
2635
  cdict->dictContentSize = dictSize;
2326
2636
 
2327
- { ZSTD_CCtx_params cctxParams = cdict->refContext->requestedParams;
2328
- cctxParams.cParams = cParams;
2329
- CHECK_F( ZSTD_compressBegin_internal(cdict->refContext,
2330
- cdict->dictContent, dictSize, dictMode,
2331
- NULL,
2332
- cctxParams, ZSTD_CONTENTSIZE_UNKNOWN,
2333
- ZSTDb_not_buffered) );
2637
+ /* Reset the state to no dictionary */
2638
+ ZSTD_reset_compressedBlockState(&cdict->cBlockState);
2639
+ { void* const end = ZSTD_reset_matchState(
2640
+ &cdict->matchState,
2641
+ (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32,
2642
+ &cParams, ZSTDcrp_continue, /* forCCtx */ 0);
2643
+ assert(end == (char*)cdict->workspace + cdict->workspaceSize);
2644
+ (void)end;
2645
+ }
2646
+ /* (Maybe) load the dictionary
2647
+ * Skips loading the dictionary if it is <= 8 bytes.
2648
+ */
2649
+ { ZSTD_CCtx_params params;
2650
+ memset(&params, 0, sizeof(params));
2651
+ params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
2652
+ params.fParams.contentSizeFlag = 1;
2653
+ params.cParams = cParams;
2654
+ { size_t const dictID = ZSTD_compress_insertDictionary(
2655
+ &cdict->cBlockState, &cdict->matchState, &params,
2656
+ cdict->dictContent, cdict->dictContentSize,
2657
+ dictContentType, cdict->workspace);
2658
+ if (ZSTD_isError(dictID)) return dictID;
2659
+ assert(dictID <= (size_t)(U32)-1);
2660
+ cdict->dictID = (U32)dictID;
2661
+ }
2334
2662
  }
2335
2663
 
2336
2664
  return 0;
@@ -2338,24 +2666,27 @@ static size_t ZSTD_initCDict_internal(
2338
2666
 
2339
2667
  ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
2340
2668
  ZSTD_dictLoadMethod_e dictLoadMethod,
2341
- ZSTD_dictMode_e dictMode,
2669
+ ZSTD_dictContentType_e dictContentType,
2342
2670
  ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
2343
2671
  {
2344
- DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
2672
+ DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (U32)dictContentType);
2345
2673
  if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
2346
2674
 
2347
2675
  { ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
2348
- ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
2676
+ size_t const workspaceSize = HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
2677
+ void* const workspace = ZSTD_malloc(workspaceSize, customMem);
2349
2678
 
2350
- if (!cdict || !cctx) {
2679
+ if (!cdict || !workspace) {
2351
2680
  ZSTD_free(cdict, customMem);
2352
- ZSTD_freeCCtx(cctx);
2681
+ ZSTD_free(workspace, customMem);
2353
2682
  return NULL;
2354
2683
  }
2355
- cdict->refContext = cctx;
2684
+ cdict->customMem = customMem;
2685
+ cdict->workspace = workspace;
2686
+ cdict->workspaceSize = workspaceSize;
2356
2687
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
2357
2688
  dictBuffer, dictSize,
2358
- dictLoadMethod, dictMode,
2689
+ dictLoadMethod, dictContentType,
2359
2690
  cParams) )) {
2360
2691
  ZSTD_freeCDict(cdict);
2361
2692
  return NULL;
@@ -2369,7 +2700,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
2369
2700
  {
2370
2701
  ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
2371
2702
  return ZSTD_createCDict_advanced(dict, dictSize,
2372
- ZSTD_dlm_byCopy, ZSTD_dm_auto,
2703
+ ZSTD_dlm_byCopy, ZSTD_dct_auto,
2373
2704
  cParams, ZSTD_defaultCMem);
2374
2705
  }
2375
2706
 
@@ -2377,15 +2708,15 @@ ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int
2377
2708
  {
2378
2709
  ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
2379
2710
  return ZSTD_createCDict_advanced(dict, dictSize,
2380
- ZSTD_dlm_byRef, ZSTD_dm_auto,
2711
+ ZSTD_dlm_byRef, ZSTD_dct_auto,
2381
2712
  cParams, ZSTD_defaultCMem);
2382
2713
  }
2383
2714
 
2384
2715
  size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
2385
2716
  {
2386
2717
  if (cdict==NULL) return 0; /* support free on NULL */
2387
- { ZSTD_customMem const cMem = cdict->refContext->customMem;
2388
- ZSTD_freeCCtx(cdict->refContext);
2718
+ { ZSTD_customMem const cMem = cdict->customMem;
2719
+ ZSTD_free(cdict->workspace, cMem);
2389
2720
  ZSTD_free(cdict->dictBuffer, cMem);
2390
2721
  ZSTD_free(cdict, cMem);
2391
2722
  return 0;
@@ -2405,18 +2736,18 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
2405
2736
  * Note : there is no corresponding "free" function.
2406
2737
  * Since workspace was allocated externally, it must be freed externally.
2407
2738
  */
2408
- ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
2739
+ const ZSTD_CDict* ZSTD_initStaticCDict(
2740
+ void* workspace, size_t workspaceSize,
2409
2741
  const void* dict, size_t dictSize,
2410
2742
  ZSTD_dictLoadMethod_e dictLoadMethod,
2411
- ZSTD_dictMode_e dictMode,
2743
+ ZSTD_dictContentType_e dictContentType,
2412
2744
  ZSTD_compressionParameters cParams)
2413
2745
  {
2414
- size_t const cctxSize = ZSTD_estimateCCtxSize_usingCParams(cParams);
2746
+ size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
2415
2747
  size_t const neededSize = sizeof(ZSTD_CDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize)
2416
- + cctxSize;
2748
+ + HUF_WORKSPACE_SIZE + matchStateSize;
2417
2749
  ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
2418
2750
  void* ptr;
2419
- DEBUGLOG(4, "(size_t)workspace & 7 : %u", (U32)(size_t)workspace & 7);
2420
2751
  if ((size_t)workspace & 7) return NULL; /* 8-aligned */
2421
2752
  DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
2422
2753
  (U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
@@ -2429,19 +2760,22 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
2429
2760
  } else {
2430
2761
  ptr = cdict+1;
2431
2762
  }
2432
- cdict->refContext = ZSTD_initStaticCCtx(ptr, cctxSize);
2763
+ cdict->workspace = ptr;
2764
+ cdict->workspaceSize = HUF_WORKSPACE_SIZE + matchStateSize;
2433
2765
 
2434
2766
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
2435
2767
  dict, dictSize,
2436
- ZSTD_dlm_byRef, dictMode,
2768
+ ZSTD_dlm_byRef, dictContentType,
2437
2769
  cParams) ))
2438
2770
  return NULL;
2439
2771
 
2440
2772
  return cdict;
2441
2773
  }
2442
2774
 
2443
- ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) {
2444
- return cdict->refContext->appliedParams.cParams;
2775
+ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
2776
+ {
2777
+ assert(cdict != NULL);
2778
+ return cdict->cParams;
2445
2779
  }
2446
2780
 
2447
2781
  /* ZSTD_compressBegin_usingCDict_advanced() :
@@ -2454,9 +2788,18 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
2454
2788
  if (cdict==NULL) return ERROR(dictionary_wrong);
2455
2789
  { ZSTD_CCtx_params params = cctx->requestedParams;
2456
2790
  params.cParams = ZSTD_getCParamsFromCDict(cdict);
2791
+ /* Increase window log to fit the entire dictionary and source if the
2792
+ * source size is known. Limit the increase to 19, which is the
2793
+ * window log for compression level 1 with the largest source size.
2794
+ */
2795
+ if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
2796
+ U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
2797
+ U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
2798
+ params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog);
2799
+ }
2457
2800
  params.fParams = fParams;
2458
2801
  return ZSTD_compressBegin_internal(cctx,
2459
- NULL, 0, ZSTD_dm_auto,
2802
+ NULL, 0, ZSTD_dct_auto,
2460
2803
  cdict,
2461
2804
  params, pledgedSrcSize,
2462
2805
  ZSTDb_not_buffered);
@@ -2534,29 +2877,30 @@ size_t ZSTD_CStreamOutSize(void)
2534
2877
  return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
2535
2878
  }
2536
2879
 
2537
- static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
2538
- const void* const dict, size_t const dictSize, ZSTD_dictMode_e const dictMode,
2880
+ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
2881
+ const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType,
2539
2882
  const ZSTD_CDict* const cdict,
2540
2883
  ZSTD_CCtx_params const params, unsigned long long const pledgedSrcSize)
2541
2884
  {
2542
- DEBUGLOG(4, "ZSTD_resetCStream_internal");
2885
+ DEBUGLOG(4, "ZSTD_resetCStream_internal (disableLiteralCompression=%i)",
2886
+ params.disableLiteralCompression);
2543
2887
  /* params are supposed to be fully validated at this point */
2544
2888
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
2545
2889
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2546
2890
 
2547
- CHECK_F( ZSTD_compressBegin_internal(zcs,
2548
- dict, dictSize, dictMode,
2891
+ CHECK_F( ZSTD_compressBegin_internal(cctx,
2892
+ dict, dictSize, dictContentType,
2549
2893
  cdict,
2550
2894
  params, pledgedSrcSize,
2551
2895
  ZSTDb_buffered) );
2552
2896
 
2553
- zcs->inToCompress = 0;
2554
- zcs->inBuffPos = 0;
2555
- zcs->inBuffTarget = zcs->blockSize
2556
- + (zcs->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */
2557
- zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
2558
- zcs->streamStage = zcss_load;
2559
- zcs->frameEnded = 0;
2897
+ cctx->inToCompress = 0;
2898
+ cctx->inBuffPos = 0;
2899
+ cctx->inBuffTarget = cctx->blockSize
2900
+ + (cctx->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */
2901
+ cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
2902
+ cctx->streamStage = zcss_load;
2903
+ cctx->frameEnded = 0;
2560
2904
  return 0; /* ready to go */
2561
2905
  }
2562
2906
 
@@ -2568,8 +2912,8 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
2568
2912
  DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (U32)pledgedSrcSize);
2569
2913
  if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
2570
2914
  params.fParams.contentSizeFlag = 1;
2571
- params.cParams = ZSTD_getCParamsFromCCtxParams(params, pledgedSrcSize, 0);
2572
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
2915
+ params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, 0);
2916
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
2573
2917
  }
2574
2918
 
2575
2919
  /*! ZSTD_initCStream_internal() :
@@ -2592,7 +2936,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
2592
2936
  }
2593
2937
  ZSTD_freeCDict(zcs->cdictLocal);
2594
2938
  zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
2595
- ZSTD_dlm_byCopy, ZSTD_dm_auto,
2939
+ ZSTD_dlm_byCopy, ZSTD_dct_auto,
2596
2940
  params.cParams, zcs->customMem);
2597
2941
  zcs->cdict = zcs->cdictLocal;
2598
2942
  if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
@@ -2605,10 +2949,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
2605
2949
  zcs->cdict = cdict;
2606
2950
  }
2607
2951
 
2608
- params.compressionLevel = ZSTD_CLEVEL_CUSTOM; /* enforce usage of cParams, instead of a dynamic derivation from cLevel (but does that happen ?) */
2609
- zcs->requestedParams = params;
2610
-
2611
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
2952
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
2612
2953
  }
2613
2954
 
2614
2955
  /* ZSTD_initCStream_usingCDict_advanced() :
@@ -2637,20 +2978,22 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
2637
2978
  return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */
2638
2979
  }
2639
2980
 
2981
+
2640
2982
  /* ZSTD_initCStream_advanced() :
2641
- * pledgedSrcSize must be correct.
2983
+ * pledgedSrcSize must be exact.
2642
2984
  * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
2643
2985
  * dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
2644
2986
  size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
2645
2987
  const void* dict, size_t dictSize,
2646
2988
  ZSTD_parameters params, unsigned long long pledgedSrcSize)
2647
2989
  {
2648
- ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2649
2990
  DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u",
2650
2991
  (U32)pledgedSrcSize, params.fParams.contentSizeFlag);
2651
2992
  CHECK_F( ZSTD_checkCParams(params.cParams) );
2652
2993
  if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
2653
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, cctxParams, pledgedSrcSize);
2994
+ { ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2995
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, cctxParams, pledgedSrcSize);
2996
+ }
2654
2997
  }
2655
2998
 
2656
2999
  size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
@@ -2687,7 +3030,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
2687
3030
 
2688
3031
  /** ZSTD_compressStream_generic():
2689
3032
  * internal function for all *compressStream*() variants and *compress_generic()
2690
- * non-static, because can be called from zstdmt.c
3033
+ * non-static, because can be called from zstdmt_compress.c
2691
3034
  * @return : hint size for next input */
2692
3035
  size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
2693
3036
  ZSTD_outBuffer* output,
@@ -2862,46 +3205,56 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
2862
3205
  DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
2863
3206
  if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
2864
3207
  params.cParams = ZSTD_getCParamsFromCCtxParams(
2865
- cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
3208
+ &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
2866
3209
 
2867
3210
  #ifdef ZSTD_MULTITHREAD
2868
- if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN)
2869
- params.nbThreads = 1; /* do not invoke multi-threading when src size is too small */
2870
- if (params.nbThreads > 1) {
2871
- if (cctx->mtctx == NULL || (params.nbThreads != ZSTDMT_getNbThreads(cctx->mtctx))) {
2872
- DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbThreads=%u (previous: %u)",
2873
- params.nbThreads, ZSTDMT_getNbThreads(cctx->mtctx));
3211
+ if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
3212
+ params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
3213
+ }
3214
+ if (params.nbWorkers > 0) {
3215
+ /* mt context creation */
3216
+ if (cctx->mtctx == NULL || (params.nbWorkers != ZSTDMT_getNbWorkers(cctx->mtctx))) {
3217
+ DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbWorkers=%u",
3218
+ params.nbWorkers);
3219
+ if (cctx->mtctx != NULL)
3220
+ DEBUGLOG(4, "ZSTD_compress_generic: previous nbWorkers was %u",
3221
+ ZSTDMT_getNbWorkers(cctx->mtctx));
2874
3222
  ZSTDMT_freeCCtx(cctx->mtctx);
2875
- cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbThreads, cctx->customMem);
3223
+ cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
2876
3224
  if (cctx->mtctx == NULL) return ERROR(memory_allocation);
2877
3225
  }
2878
- DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", params.nbThreads);
3226
+ /* mt compression */
3227
+ DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
2879
3228
  CHECK_F( ZSTDMT_initCStream_internal(
2880
3229
  cctx->mtctx,
2881
- prefixDict.dict, prefixDict.dictSize, ZSTD_dm_rawContent,
3230
+ prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
2882
3231
  cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
2883
3232
  cctx->streamStage = zcss_load;
2884
- cctx->appliedParams.nbThreads = params.nbThreads;
3233
+ cctx->appliedParams.nbWorkers = params.nbWorkers;
2885
3234
  } else
2886
3235
  #endif
2887
- { CHECK_F( ZSTD_resetCStream_internal(
2888
- cctx, prefixDict.dict, prefixDict.dictSize,
2889
- prefixDict.dictMode, cctx->cdict, params,
2890
- cctx->pledgedSrcSizePlusOne-1) );
3236
+ { CHECK_F( ZSTD_resetCStream_internal(cctx,
3237
+ prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
3238
+ cctx->cdict,
3239
+ params, cctx->pledgedSrcSizePlusOne-1) );
2891
3240
  assert(cctx->streamStage == zcss_load);
2892
- assert(cctx->appliedParams.nbThreads <= 1);
3241
+ assert(cctx->appliedParams.nbWorkers == 0);
2893
3242
  } }
2894
3243
 
2895
3244
  /* compression stage */
2896
3245
  #ifdef ZSTD_MULTITHREAD
2897
- if (cctx->appliedParams.nbThreads > 1) {
2898
- size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
2899
- if ( ZSTD_isError(flushMin)
2900
- || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
2901
- ZSTD_startNewCompression(cctx);
3246
+ if (cctx->appliedParams.nbWorkers > 0) {
3247
+ if (cctx->cParamsChanged) {
3248
+ ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
3249
+ cctx->cParamsChanged = 0;
2902
3250
  }
2903
- return flushMin;
2904
- }
3251
+ { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
3252
+ if ( ZSTD_isError(flushMin)
3253
+ || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
3254
+ ZSTD_startNewCompression(cctx);
3255
+ }
3256
+ return flushMin;
3257
+ } }
2905
3258
  #endif
2906
3259
  CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
2907
3260
  DEBUGLOG(5, "completed ZSTD_compress_generic");
@@ -2927,7 +3280,7 @@ size_t ZSTD_compress_generic_simpleArgs (
2927
3280
  /*====== Finalize ======*/
2928
3281
 
2929
3282
  /*! ZSTD_flushStream() :
2930
- * @return : amount of data remaining to flush */
3283
+ * @return : amount of data remaining to flush */
2931
3284
  size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
2932
3285
  {
2933
3286
  ZSTD_inBuffer input = { NULL, 0, 0 };
@@ -2959,11 +3312,11 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
2959
3312
  static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
2960
3313
  { /* "default" - guarantees a monotonically increasing memory budget */
2961
3314
  /* W, C, H, S, L, TL, strat */
2962
- { 18, 12, 12, 1, 7, 16, ZSTD_fast }, /* level 0 - never used */
2963
- { 19, 13, 14, 1, 7, 16, ZSTD_fast }, /* level 1 */
2964
- { 19, 15, 16, 1, 6, 16, ZSTD_fast }, /* level 2 */
2965
- { 20, 16, 17, 1, 5, 16, ZSTD_dfast }, /* level 3 */
2966
- { 20, 17, 18, 1, 5, 16, ZSTD_dfast }, /* level 4 */
3315
+ { 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 */
2967
3320
  { 20, 17, 18, 2, 5, 16, ZSTD_greedy }, /* level 5 */
2968
3321
  { 21, 17, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */
2969
3322
  { 21, 18, 19, 3, 5, 16, ZSTD_lazy }, /* level 7 */
@@ -2972,9 +3325,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
2972
3325
  { 21, 19, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
2973
3326
  { 22, 20, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
2974
3327
  { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
2975
- { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 13 */
2976
- { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 14 */
2977
- { 22, 21, 22, 4, 5, 16, ZSTD_btlazy2 }, /* level 15 */
3328
+ { 22, 21, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
3329
+ { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
3330
+ { 22, 22, 22, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
2978
3331
  { 22, 21, 22, 4, 5, 48, ZSTD_btopt }, /* level 16 */
2979
3332
  { 23, 22, 22, 4, 4, 48, ZSTD_btopt }, /* level 17 */
2980
3333
  { 23, 22, 22, 5, 3, 64, ZSTD_btopt }, /* level 18 */
@@ -2985,8 +3338,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
2985
3338
  },
2986
3339
  { /* for srcSize <= 256 KB */
2987
3340
  /* W, C, H, S, L, T, strat */
2988
- { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - not used */
2989
- { 18, 13, 14, 1, 6, 8, ZSTD_fast }, /* level 1 */
3341
+ { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
3342
+ { 18, 13, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */
2990
3343
  { 18, 14, 13, 1, 5, 8, ZSTD_dfast }, /* level 2 */
2991
3344
  { 18, 16, 15, 1, 5, 8, ZSTD_dfast }, /* level 3 */
2992
3345
  { 18, 15, 17, 1, 5, 8, ZSTD_greedy }, /* level 4.*/
@@ -2997,8 +3350,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
2997
3350
  { 18, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
2998
3351
  { 18, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
2999
3352
  { 18, 18, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 11.*/
3000
- { 18, 18, 17, 7, 4, 8, ZSTD_lazy2 }, /* level 12.*/
3001
- { 18, 19, 17, 6, 4, 8, ZSTD_btlazy2 }, /* level 13 */
3353
+ { 18, 18, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 12.*/
3354
+ { 18, 19, 17, 7, 4, 8, ZSTD_btlazy2 }, /* level 13 */
3002
3355
  { 18, 18, 18, 4, 4, 16, ZSTD_btopt }, /* level 14.*/
3003
3356
  { 18, 18, 18, 4, 3, 16, ZSTD_btopt }, /* level 15.*/
3004
3357
  { 18, 19, 18, 6, 3, 32, ZSTD_btopt }, /* level 16.*/
@@ -3011,9 +3364,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3011
3364
  },
3012
3365
  { /* for srcSize <= 128 KB */
3013
3366
  /* W, C, H, S, L, T, strat */
3014
- { 17, 12, 12, 1, 7, 8, ZSTD_fast }, /* level 0 - not used */
3015
- { 17, 12, 13, 1, 6, 8, ZSTD_fast }, /* level 1 */
3016
- { 17, 13, 16, 1, 5, 8, ZSTD_fast }, /* level 2 */
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 */
3017
3370
  { 17, 16, 16, 2, 5, 8, ZSTD_dfast }, /* level 3 */
3018
3371
  { 17, 13, 15, 3, 4, 8, ZSTD_greedy }, /* level 4 */
3019
3372
  { 17, 15, 17, 4, 4, 8, ZSTD_greedy }, /* level 5 */
@@ -3037,9 +3390,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3037
3390
  },
3038
3391
  { /* for srcSize <= 16 KB */
3039
3392
  /* W, C, H, S, L, T, strat */
3040
- { 14, 12, 12, 1, 7, 6, ZSTD_fast }, /* level 0 - not used */
3041
- { 14, 14, 14, 1, 6, 6, ZSTD_fast }, /* level 1 */
3042
- { 14, 14, 14, 1, 4, 6, ZSTD_fast }, /* level 2 */
3393
+ { 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 */
3043
3396
  { 14, 14, 14, 1, 4, 6, ZSTD_dfast }, /* level 3.*/
3044
3397
  { 14, 14, 14, 4, 4, 6, ZSTD_greedy }, /* level 4.*/
3045
3398
  { 14, 14, 14, 3, 4, 6, ZSTD_lazy }, /* level 5.*/
@@ -3063,47 +3416,22 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3063
3416
  },
3064
3417
  };
3065
3418
 
3066
- #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
3067
- /* This function just controls
3068
- * the monotonic memory budget increase of ZSTD_defaultCParameters[0].
3069
- * Run once, on first ZSTD_getCParams() usage, if ZSTD_DEBUG is enabled
3070
- */
3071
- MEM_STATIC void ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget(void)
3072
- {
3073
- int level;
3074
- for (level=1; level<ZSTD_maxCLevel(); level++) {
3075
- ZSTD_compressionParameters const c1 = ZSTD_defaultCParameters[0][level];
3076
- ZSTD_compressionParameters const c2 = ZSTD_defaultCParameters[0][level+1];
3077
- assert(c1.windowLog <= c2.windowLog);
3078
- # define ZSTD_TABLECOST(h,c) ((1<<(h)) + (1<<(c)))
3079
- assert(ZSTD_TABLECOST(c1.hashLog, c1.chainLog) <= ZSTD_TABLECOST(c2.hashLog, c2.chainLog));
3080
- }
3081
- }
3082
- #endif
3083
-
3084
3419
  /*! ZSTD_getCParams() :
3085
- * @return ZSTD_compressionParameters structure for a selected compression level, `srcSize` and `dictSize`.
3420
+ * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
3086
3421
  * Size values are optional, provide 0 if not known or unused */
3087
3422
  ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
3088
3423
  {
3089
3424
  size_t const addedSize = srcSizeHint ? 0 : 500;
3090
3425
  U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1;
3091
3426
  U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
3092
-
3093
- #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
3094
- static int g_monotonicTest = 1;
3095
- if (g_monotonicTest) {
3096
- ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget();
3097
- g_monotonicTest=0;
3098
- }
3099
- #endif
3100
-
3101
- DEBUGLOG(4, "ZSTD_getCParams: cLevel=%i, srcSize=%u, dictSize=%u => table %u",
3102
- compressionLevel, (U32)srcSizeHint, (U32)dictSize, tableID);
3103
- if (compressionLevel <= 0) compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default; no negative compressionLevel yet */
3104
- if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
3105
- { ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
3106
- return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
3427
+ int row = compressionLevel;
3428
+ DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
3429
+ if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
3430
+ if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
3431
+ if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
3432
+ { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
3433
+ if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
3434
+ return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
3107
3435
 
3108
3436
  }
3109
3437
 
@@ -3113,6 +3441,7 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
3113
3441
  ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
3114
3442
  ZSTD_parameters params;
3115
3443
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
3444
+ DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
3116
3445
  memset(&params, 0, sizeof(params));
3117
3446
  params.cParams = cParams;
3118
3447
  params.fParams.contentSizeFlag = 1;