zstd-ruby 1.3.3.0 → 1.3.4.0

Sign up to get free protection for your applications and to get access to all the features.
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;