zstd-ruby 1.3.2.0 → 1.3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/BUCK +31 -10
  4. data/ext/zstdruby/libzstd/common/bitstream.h +1 -1
  5. data/ext/zstdruby/libzstd/common/mem.h +15 -13
  6. data/ext/zstdruby/libzstd/common/pool.c +1 -2
  7. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -4
  8. data/ext/zstdruby/libzstd/common/zstd_internal.h +52 -170
  9. data/ext/zstdruby/libzstd/compress/zstd_compress.c +434 -337
  10. data/ext/zstdruby/libzstd/compress/{zstd_compress.h → zstd_compress_internal.h} +191 -36
  11. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +1 -0
  12. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
  13. data/ext/zstdruby/libzstd/compress/zstd_fast.c +1 -0
  14. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
  15. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +66 -50
  16. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +3 -2
  17. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +3 -2
  18. data/ext/zstdruby/libzstd/compress/zstd_opt.c +504 -676
  19. data/ext/zstdruby/libzstd/compress/zstd_opt.h +2 -2
  20. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +130 -80
  21. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +15 -7
  22. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +41 -31
  23. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
  24. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +1 -1
  25. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -1
  26. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -74
  27. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -74
  28. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -72
  29. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -73
  30. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -77
  31. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -77
  32. data/ext/zstdruby/libzstd/zstd.h +43 -30
  33. data/lib/zstd-ruby/version.rb +1 -1
  34. metadata +4 -4
@@ -26,7 +26,7 @@
26
26
  #include "fse.h"
27
27
  #define HUF_STATIC_LINKING_ONLY
28
28
  #include "huf.h"
29
- #include "zstd_compress.h"
29
+ #include "zstd_compress_internal.h"
30
30
  #include "zstd_fast.h"
31
31
  #include "zstd_double_fast.h"
32
32
  #include "zstd_lazy.h"
@@ -42,17 +42,6 @@ size_t ZSTD_compressBound(size_t srcSize) {
42
42
  }
43
43
 
44
44
 
45
- /*-*************************************
46
- * Sequence storage
47
- ***************************************/
48
- static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
49
- {
50
- ssPtr->lit = ssPtr->litStart;
51
- ssPtr->sequences = ssPtr->sequencesStart;
52
- ssPtr->longLengthID = 0;
53
- }
54
-
55
-
56
45
  /*-*************************************
57
46
  * Context memory management
58
47
  ***************************************/
@@ -78,6 +67,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
78
67
  if (!cctx) return NULL;
79
68
  cctx->customMem = customMem;
80
69
  cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
70
+ cctx->requestedParams.fParams.contentSizeFlag = 1;
81
71
  ZSTD_STATIC_ASSERT(zcss_init==0);
82
72
  ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
83
73
  return cctx;
@@ -152,28 +142,34 @@ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStor
152
142
  #define ZSTD_CLEVEL_CUSTOM 999
153
143
 
154
144
  static ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
155
- ZSTD_CCtx_params params, U64 srcSizeHint, size_t dictSize)
145
+ ZSTD_CCtx_params CCtxParams, U64 srcSizeHint, size_t dictSize)
156
146
  {
157
- return (params.compressionLevel == ZSTD_CLEVEL_CUSTOM ?
158
- params.cParams :
159
- ZSTD_getCParams(params.compressionLevel, srcSizeHint, dictSize));
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);
160
152
  }
161
153
 
162
- static void ZSTD_cLevelToCCtxParams_srcSize(ZSTD_CCtx_params* params, U64 srcSize)
154
+ static void ZSTD_cLevelToCCtxParams_srcSize(ZSTD_CCtx_params* CCtxParams, U64 srcSize)
163
155
  {
164
- params->cParams = ZSTD_getCParamsFromCCtxParams(*params, srcSize, 0);
165
- params->compressionLevel = ZSTD_CLEVEL_CUSTOM;
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;
166
160
  }
167
161
 
168
162
  static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
169
163
  {
164
+ DEBUGLOG(4, "ZSTD_cLevelToCParams: level=%i", cctx->requestedParams.compressionLevel);
170
165
  ZSTD_cLevelToCCtxParams_srcSize(
171
166
  &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1);
172
167
  }
173
168
 
174
- static void ZSTD_cLevelToCCtxParams(ZSTD_CCtx_params* params)
169
+ static void ZSTD_cLevelToCCtxParams(ZSTD_CCtx_params* CCtxParams)
175
170
  {
176
- ZSTD_cLevelToCCtxParams_srcSize(params, 0);
171
+ DEBUGLOG(4, "ZSTD_cLevelToCCtxParams");
172
+ ZSTD_cLevelToCCtxParams_srcSize(CCtxParams, ZSTD_CONTENTSIZE_UNKNOWN);
177
173
  }
178
174
 
179
175
  static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
@@ -251,6 +247,7 @@ static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
251
247
 
252
248
  size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value)
253
249
  {
250
+ DEBUGLOG(4, "ZSTD_CCtx_setParameter (%u, %u)", (U32)param, value);
254
251
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
255
252
 
256
253
  switch(param)
@@ -259,7 +256,6 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
259
256
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
260
257
 
261
258
  case ZSTD_p_compressionLevel:
262
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
263
259
  if (cctx->cdict) return ERROR(stage_wrong);
264
260
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
265
261
 
@@ -270,9 +266,8 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
270
266
  case ZSTD_p_minMatch:
271
267
  case ZSTD_p_targetLength:
272
268
  case ZSTD_p_compressionStrategy:
273
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
274
269
  if (cctx->cdict) return ERROR(stage_wrong);
275
- ZSTD_cLevelToCParams(cctx); /* Can optimize if srcSize is known */
270
+ if (value>0) ZSTD_cLevelToCParams(cctx); /* Can optimize if srcSize is known */
276
271
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
277
272
 
278
273
  case ZSTD_p_contentSizeFlag:
@@ -281,15 +276,12 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
281
276
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
282
277
 
283
278
  case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
284
- * even when referencing into Dictionary content
279
+ * even when referencing into Dictionary content.
285
280
  * default : 0 when using a CDict, 1 when using a Prefix */
286
- cctx->loadedDictEnd = 0;
287
281
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
288
282
 
289
283
  case ZSTD_p_nbThreads:
290
- if (value==0) return 0;
291
- DEBUGLOG(5, " setting nbThreads : %u", value);
292
- if (value > 1 && cctx->staticSize) {
284
+ if ((value > 1) && cctx->staticSize) {
293
285
  return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
294
286
  }
295
287
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
@@ -298,22 +290,15 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
298
290
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
299
291
 
300
292
  case ZSTD_p_overlapSizeLog:
301
- DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->requestedParams.nbThreads);
302
293
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
303
294
 
304
295
  case ZSTD_p_enableLongDistanceMatching:
305
296
  if (cctx->cdict) return ERROR(stage_wrong);
306
- if (value != 0) {
307
- ZSTD_cLevelToCParams(cctx);
308
- }
297
+ if (value>0) ZSTD_cLevelToCParams(cctx);
309
298
  return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
310
299
 
311
300
  case ZSTD_p_ldmHashLog:
312
301
  case ZSTD_p_ldmMinMatch:
313
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
314
- if (cctx->cdict) return ERROR(stage_wrong);
315
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
316
-
317
302
  case ZSTD_p_ldmBucketSizeLog:
318
303
  case ZSTD_p_ldmHashEveryLog:
319
304
  if (cctx->cdict) return ERROR(stage_wrong);
@@ -324,160 +309,167 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
324
309
  }
325
310
 
326
311
  size_t ZSTD_CCtxParam_setParameter(
327
- ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value)
312
+ ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, unsigned value)
328
313
  {
314
+ DEBUGLOG(4, "ZSTD_CCtxParam_setParameter (%u, %u)", (U32)param, value);
329
315
  switch(param)
330
316
  {
331
317
  case ZSTD_p_format :
332
318
  if (value > (unsigned)ZSTD_f_zstd1_magicless)
333
319
  return ERROR(parameter_unsupported);
334
- params->format = (ZSTD_format_e)value;
335
- return 0;
320
+ CCtxParams->format = (ZSTD_format_e)value;
321
+ return (size_t)CCtxParams->format;
336
322
 
337
323
  case ZSTD_p_compressionLevel :
338
324
  if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel();
339
- if (value == 0) return 0;
340
- params->compressionLevel = value;
341
- return 0;
325
+ if (value) /* 0 : does not change current level */
326
+ CCtxParams->compressionLevel = value;
327
+ return CCtxParams->compressionLevel;
342
328
 
343
329
  case ZSTD_p_windowLog :
344
- if (value == 0) return 0;
345
- CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
346
- ZSTD_cLevelToCCtxParams(params);
347
- params->cParams.windowLog = value;
348
- return 0;
330
+ DEBUGLOG(4, "ZSTD_CCtxParam_setParameter: set windowLog=%u", value);
331
+ if (value) { /* 0 : does not change current windowLog */
332
+ CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
333
+ ZSTD_cLevelToCCtxParams(CCtxParams);
334
+ CCtxParams->cParams.windowLog = value;
335
+ }
336
+ return CCtxParams->cParams.windowLog;
349
337
 
350
338
  case ZSTD_p_hashLog :
351
- if (value == 0) return 0;
352
- CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
353
- ZSTD_cLevelToCCtxParams(params);
354
- params->cParams.hashLog = value;
355
- return 0;
339
+ if (value) { /* 0 : does not change current hashLog */
340
+ CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
341
+ ZSTD_cLevelToCCtxParams(CCtxParams);
342
+ CCtxParams->cParams.hashLog = value;
343
+ }
344
+ return CCtxParams->cParams.hashLog;
356
345
 
357
346
  case ZSTD_p_chainLog :
358
- if (value == 0) return 0;
359
- CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
360
- ZSTD_cLevelToCCtxParams(params);
361
- params->cParams.chainLog = value;
362
- return 0;
347
+ if (value) { /* 0 : does not change current chainLog */
348
+ CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
349
+ ZSTD_cLevelToCCtxParams(CCtxParams);
350
+ CCtxParams->cParams.chainLog = value;
351
+ }
352
+ return CCtxParams->cParams.chainLog;
363
353
 
364
354
  case ZSTD_p_searchLog :
365
- if (value == 0) return 0;
366
- CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
367
- ZSTD_cLevelToCCtxParams(params);
368
- params->cParams.searchLog = value;
369
- return 0;
355
+ if (value) { /* 0 : does not change current searchLog */
356
+ CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
357
+ ZSTD_cLevelToCCtxParams(CCtxParams);
358
+ CCtxParams->cParams.searchLog = value;
359
+ }
360
+ return value;
370
361
 
371
362
  case ZSTD_p_minMatch :
372
- if (value == 0) return 0;
373
- CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
374
- ZSTD_cLevelToCCtxParams(params);
375
- params->cParams.searchLength = value;
376
- return 0;
363
+ if (value) { /* 0 : does not change current minMatch length */
364
+ CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
365
+ ZSTD_cLevelToCCtxParams(CCtxParams);
366
+ CCtxParams->cParams.searchLength = value;
367
+ }
368
+ return CCtxParams->cParams.searchLength;
377
369
 
378
370
  case ZSTD_p_targetLength :
379
- if (value == 0) return 0;
380
- CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
381
- ZSTD_cLevelToCCtxParams(params);
382
- params->cParams.targetLength = value;
383
- return 0;
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
+ }
376
+ return CCtxParams->cParams.targetLength;
384
377
 
385
378
  case ZSTD_p_compressionStrategy :
386
- if (value == 0) return 0;
387
- CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
388
- ZSTD_cLevelToCCtxParams(params);
389
- params->cParams.strategy = (ZSTD_strategy)value;
390
- return 0;
379
+ if (value) { /* 0 : does not change currentstrategy */
380
+ CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
381
+ ZSTD_cLevelToCCtxParams(CCtxParams);
382
+ CCtxParams->cParams.strategy = (ZSTD_strategy)value;
383
+ }
384
+ return (size_t)CCtxParams->cParams.strategy;
391
385
 
392
386
  case ZSTD_p_contentSizeFlag :
393
387
  /* Content size written in frame header _when known_ (default:1) */
394
- DEBUGLOG(5, "set content size flag = %u", (value>0));
395
- params->fParams.contentSizeFlag = value > 0;
396
- return 0;
388
+ DEBUGLOG(4, "set content size flag = %u", (value>0));
389
+ CCtxParams->fParams.contentSizeFlag = value > 0;
390
+ return CCtxParams->fParams.contentSizeFlag;
397
391
 
398
392
  case ZSTD_p_checksumFlag :
399
393
  /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
400
- params->fParams.checksumFlag = value > 0;
401
- return 0;
394
+ CCtxParams->fParams.checksumFlag = value > 0;
395
+ return CCtxParams->fParams.checksumFlag;
402
396
 
403
397
  case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
404
- DEBUGLOG(5, "set dictIDFlag = %u", (value>0));
405
- params->fParams.noDictIDFlag = (value == 0);
406
- return 0;
398
+ DEBUGLOG(4, "set dictIDFlag = %u", (value>0));
399
+ CCtxParams->fParams.noDictIDFlag = (value == 0);
400
+ return !CCtxParams->fParams.noDictIDFlag;
407
401
 
408
402
  case ZSTD_p_forceMaxWindow :
409
- params->forceWindow = value > 0;
410
- return 0;
403
+ CCtxParams->forceWindow = (value > 0);
404
+ return CCtxParams->forceWindow;
411
405
 
412
406
  case ZSTD_p_nbThreads :
413
- if (value == 0) return 0;
407
+ if (value == 0) return CCtxParams->nbThreads;
414
408
  #ifndef ZSTD_MULTITHREAD
415
409
  if (value > 1) return ERROR(parameter_unsupported);
416
- return 0;
410
+ return 1;
417
411
  #else
418
- return ZSTDMT_initializeCCtxParameters(params, value);
412
+ return ZSTDMT_CCtxParam_setNbThreads(CCtxParams, value);
419
413
  #endif
420
414
 
421
415
  case ZSTD_p_jobSize :
422
416
  #ifndef ZSTD_MULTITHREAD
423
417
  return ERROR(parameter_unsupported);
424
418
  #else
425
- if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
426
- return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_sectionSize, value);
419
+ if (CCtxParams->nbThreads <= 1) return ERROR(parameter_unsupported);
420
+ return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value);
427
421
  #endif
428
422
 
429
423
  case ZSTD_p_overlapSizeLog :
430
424
  #ifndef ZSTD_MULTITHREAD
431
425
  return ERROR(parameter_unsupported);
432
426
  #else
433
- if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
434
- return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_overlapSectionLog, value);
427
+ if (CCtxParams->nbThreads <= 1) return ERROR(parameter_unsupported);
428
+ return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapSectionLog, value);
435
429
  #endif
436
430
 
437
431
  case ZSTD_p_enableLongDistanceMatching :
438
- if (value != 0) {
439
- ZSTD_cLevelToCCtxParams(params);
440
- params->cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
432
+ if (value) {
433
+ ZSTD_cLevelToCCtxParams(CCtxParams);
434
+ CCtxParams->cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
441
435
  }
442
- return ZSTD_ldm_initializeParameters(&params->ldmParams, value);
436
+ return ZSTD_ldm_initializeParameters(&CCtxParams->ldmParams, value);
443
437
 
444
438
  case ZSTD_p_ldmHashLog :
445
- if (value == 0) return 0;
446
- CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
447
- params->ldmParams.hashLog = value;
448
- return 0;
439
+ if (value) { /* 0 : does not change current ldmHashLog */
440
+ CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
441
+ CCtxParams->ldmParams.hashLog = value;
442
+ }
443
+ return CCtxParams->ldmParams.hashLog;
449
444
 
450
445
  case ZSTD_p_ldmMinMatch :
451
- if (value == 0) return 0;
452
- CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
453
- params->ldmParams.minMatchLength = value;
454
- return 0;
446
+ if (value) { /* 0 : does not change current ldmMinMatch */
447
+ CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
448
+ CCtxParams->ldmParams.minMatchLength = value;
449
+ }
450
+ return CCtxParams->ldmParams.minMatchLength;
455
451
 
456
452
  case ZSTD_p_ldmBucketSizeLog :
457
453
  if (value > ZSTD_LDM_BUCKETSIZELOG_MAX) {
458
454
  return ERROR(parameter_outOfBound);
459
455
  }
460
- params->ldmParams.bucketSizeLog = value;
461
- return 0;
456
+ CCtxParams->ldmParams.bucketSizeLog = value;
457
+ return value;
462
458
 
463
459
  case ZSTD_p_ldmHashEveryLog :
464
460
  if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) {
465
461
  return ERROR(parameter_outOfBound);
466
462
  }
467
- params->ldmParams.hashEveryLog = value;
468
- return 0;
463
+ CCtxParams->ldmParams.hashEveryLog = value;
464
+ return value;
469
465
 
470
466
  default: return ERROR(parameter_unsupported);
471
467
  }
472
468
  }
473
469
 
474
- /**
475
- * This function should be updated whenever ZSTD_CCtx_params is updated.
476
- * Parameters are copied manually before the dictionary is loaded.
477
- * The multithreading parameters jobSize and overlapSizeLog are set only if
478
- * nbThreads > 1.
479
- *
480
- * Pledged srcSize is treated as unknown.
470
+ /** ZSTD_CCtx_setParametersUsingCCtxParams() :
471
+ * just applies `params` into `cctx`
472
+ * no action is performed, parameters are merely stored.
481
473
  */
482
474
  size_t ZSTD_CCtx_setParametersUsingCCtxParams(
483
475
  ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
@@ -485,33 +477,14 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
485
477
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
486
478
  if (cctx->cdict) return ERROR(stage_wrong);
487
479
 
488
- /* Assume the compression and frame parameters are validated */
489
- cctx->requestedParams.cParams = params->cParams;
490
- cctx->requestedParams.fParams = params->fParams;
491
- cctx->requestedParams.compressionLevel = params->compressionLevel;
492
-
493
- /* Set force window explicitly since it sets cctx->loadedDictEnd */
494
- CHECK_F( ZSTD_CCtx_setParameter(
495
- cctx, ZSTD_p_forceMaxWindow, params->forceWindow) );
496
-
497
- /* Set multithreading parameters explicitly */
498
- CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_nbThreads, params->nbThreads) );
499
- if (params->nbThreads > 1) {
500
- CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_jobSize, params->jobSize) );
501
- CHECK_F( ZSTD_CCtx_setParameter(
502
- cctx, ZSTD_p_overlapSizeLog, params->overlapSizeLog) );
503
- }
480
+ cctx->requestedParams = *params;
504
481
 
505
- /* Copy long distance matching parameters */
506
- cctx->requestedParams.ldmParams = params->ldmParams;
507
-
508
- /* customMem is used only for create/free params and can be ignored */
509
482
  return 0;
510
483
  }
511
484
 
512
485
  ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
513
486
  {
514
- DEBUGLOG(4, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
487
+ DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
515
488
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
516
489
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
517
490
  return 0;
@@ -523,14 +496,14 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
523
496
  {
524
497
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
525
498
  if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
526
- DEBUGLOG(4, "load dictionary of size %u", (U32)dictSize);
499
+ DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
527
500
  ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
528
501
  if (dict==NULL || dictSize==0) { /* no dictionary mode */
529
502
  cctx->cdictLocal = NULL;
530
503
  cctx->cdict = NULL;
531
504
  } else {
532
505
  ZSTD_compressionParameters const cParams =
533
- ZSTD_getCParamsFromCCtxParams(cctx->requestedParams, 0, dictSize);
506
+ ZSTD_getCParamsFromCCtxParams(cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
534
507
  cctx->cdictLocal = ZSTD_createCDict_advanced(
535
508
  dict, dictSize,
536
509
  dictLoadMethod, dictMode,
@@ -756,10 +729,7 @@ size_t ZSTD_estimateCStreamSize(int compressionLevel) {
756
729
  static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
757
730
  ZSTD_compressionParameters cParams2)
758
731
  {
759
- U32 bslog1 = MIN(cParams1.windowLog, ZSTD_BLOCKSIZELOG_MAX);
760
- U32 bslog2 = MIN(cParams2.windowLog, ZSTD_BLOCKSIZELOG_MAX);
761
- return (bslog1 == bslog2) /* same block size */
762
- & (cParams1.hashLog == cParams2.hashLog)
732
+ return (cParams1.hashLog == cParams2.hashLog)
763
733
  & (cParams1.chainLog == cParams2.chainLog)
764
734
  & (cParams1.strategy == cParams2.strategy) /* opt parser space */
765
735
  & ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
@@ -778,12 +748,38 @@ static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
778
748
  ldmParams1.hashEveryLog == ldmParams2.hashEveryLog);
779
749
  }
780
750
 
751
+ typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
752
+
753
+ /* ZSTD_sufficientBuff() :
754
+ * check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
755
+ * Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
756
+ static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t blockSize1,
757
+ ZSTD_buffered_policy_e buffPol2,
758
+ ZSTD_compressionParameters cParams2,
759
+ U64 pledgedSrcSize)
760
+ {
761
+ size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
762
+ size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
763
+ size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
764
+ DEBUGLOG(4, "ZSTD_sufficientBuff: windowSize2=%u from wlog=%u",
765
+ (U32)windowSize2, cParams2.windowLog);
766
+ DEBUGLOG(4, "ZSTD_sufficientBuff: blockSize2 %u <=? blockSize1 %u",
767
+ (U32)blockSize2, (U32)blockSize1);
768
+ return (blockSize2 <= blockSize1) /* seqStore space depends on blockSize */
769
+ & (neededBufferSize2 <= bufferSize1);
770
+ }
771
+
781
772
  /** Equivalence for resetCCtx purposes */
782
773
  static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
783
- ZSTD_CCtx_params params2)
774
+ ZSTD_CCtx_params params2,
775
+ size_t buffSize1, size_t blockSize1,
776
+ ZSTD_buffered_policy_e buffPol2,
777
+ U64 pledgedSrcSize)
784
778
  {
779
+ DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
785
780
  return ZSTD_equivalentCParams(params1.cParams, params2.cParams) &&
786
- ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams);
781
+ ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams) &&
782
+ ZSTD_sufficientBuff(buffSize1, blockSize1, buffPol2, params2.cParams, pledgedSrcSize);
787
783
  }
788
784
 
789
785
  /*! ZSTD_continueCCtx() :
@@ -791,7 +787,11 @@ static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
791
787
  static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
792
788
  {
793
789
  U32 const end = (U32)(cctx->nextSrc - cctx->base);
794
- DEBUGLOG(4, "continue mode");
790
+ size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
791
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
792
+ DEBUGLOG(4, "ZSTD_continueCCtx");
793
+
794
+ cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
795
795
  cctx->appliedParams = params;
796
796
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
797
797
  cctx->consumedSrcSize = 0;
@@ -812,7 +812,6 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pl
812
812
  }
813
813
 
814
814
  typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
815
- typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
816
815
 
817
816
  /*! ZSTD_resetCCtx_internal() :
818
817
  note : `params` are assumed fully validated at this stage */
@@ -821,13 +820,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
821
820
  ZSTD_compResetPolicy_e const crp,
822
821
  ZSTD_buffered_policy_e const zbuff)
823
822
  {
824
- DEBUGLOG(4, "ZSTD_resetCCtx_internal");
823
+ DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
824
+ (U32)pledgedSrcSize, params.cParams.windowLog);
825
825
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
826
- DEBUGLOG(4, "pledgedSrcSize: %u", (U32)pledgedSrcSize);
827
826
 
828
827
  if (crp == ZSTDcrp_continue) {
829
- if (ZSTD_equivalentParams(params, zc->appliedParams)) {
830
- DEBUGLOG(4, "ZSTD_equivalentParams()==1");
828
+ if (ZSTD_equivalentParams(zc->appliedParams, params,
829
+ zc->inBuffSize, zc->blockSize,
830
+ zbuff, pledgedSrcSize)) {
831
+ DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%u)",
832
+ zc->appliedParams.cParams.windowLog, (U32)zc->blockSize);
831
833
  assert(!(params.ldmParams.enableLdm &&
832
834
  params.ldmParams.hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET));
833
835
  zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
@@ -836,6 +838,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
836
838
  zc->entropy->litlength_repeatMode = FSE_repeat_none;
837
839
  return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
838
840
  } }
841
+ DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
839
842
 
840
843
  if (params.ldmParams.enableLdm) {
841
844
  /* Adjust long distance matching parameters */
@@ -846,7 +849,8 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
846
849
  ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
847
850
  }
848
851
 
849
- { size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
852
+ { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
853
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
850
854
  U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
851
855
  size_t const maxNbSeq = blockSize / divider;
852
856
  size_t const tokenSpace = blockSize + 11*maxNbSeq;
@@ -858,7 +862,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
858
862
  size_t const h3Size = ((size_t)1) << hashLog3;
859
863
  size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
860
864
  size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
861
- size_t const buffInSize = (zbuff==ZSTDb_buffered) ? ((size_t)1 << params.cParams.windowLog) + blockSize : 0;
865
+ size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
862
866
  void* ptr;
863
867
 
864
868
  /* Check if workSpace is large enough, alloc a new one if needed */
@@ -874,11 +878,15 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
874
878
  : 0;
875
879
  size_t const neededSpace = entropySpace + optSpace + ldmSpace +
876
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);
877
885
 
878
886
  if (zc->workSpaceSize < neededSpace) { /* too small : resize */
879
- DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
880
- (unsigned)zc->workSpaceSize>>10,
881
- (unsigned)neededSpace>>10);
887
+ DEBUGLOG(4, "Need to update workSpaceSize from %uK to %uK",
888
+ (unsigned)(zc->workSpaceSize>>10),
889
+ (unsigned)(neededSpace>>10));
882
890
  /* static cctx : no resize, error out */
883
891
  if (zc->staticSize) return ERROR(memory_allocation);
884
892
 
@@ -901,7 +909,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
901
909
  zc->consumedSrcSize = 0;
902
910
  if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
903
911
  zc->appliedParams.fParams.contentSizeFlag = 0;
904
- DEBUGLOG(5, "pledged content size : %u ; flag : %u",
912
+ DEBUGLOG(4, "pledged content size : %u ; flag : %u",
905
913
  (U32)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);
906
914
  zc->blockSize = blockSize;
907
915
 
@@ -927,7 +935,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
927
935
 
928
936
  /* opt parser space */
929
937
  if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) {
930
- DEBUGLOG(5, "reserving optimal parser space");
938
+ DEBUGLOG(4, "reserving optimal parser space");
931
939
  assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
932
940
  zc->optState.litFreq = (U32*)ptr;
933
941
  zc->optState.litLengthFreq = zc->optState.litFreq + (1<<Litbits);
@@ -951,6 +959,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
951
959
  }
952
960
 
953
961
  /* table Space */
962
+ DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
954
963
  if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
955
964
  assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
956
965
  zc->hashTable = (U32*)(ptr);
@@ -999,15 +1008,16 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
999
1008
 
1000
1009
  /*! ZSTD_copyCCtx_internal() :
1001
1010
  * Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
1002
- * The "context", in this case, refers to the hash and chain tables, entropy
1003
- * tables, and dictionary offsets.
1004
1011
  * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
1005
- * pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
1006
- * @return : 0, or an error code */
1012
+ * The "context", in this case, refers to the hash and chain tables,
1013
+ * entropy tables, and dictionary references.
1014
+ * `windowLog` value is enforced if != 0, otherwise value is copied from srcCCtx.
1015
+ * @return : 0, or an error code */
1007
1016
  static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1008
1017
  const ZSTD_CCtx* srcCCtx,
1018
+ unsigned windowLog,
1009
1019
  ZSTD_frameParameters fParams,
1010
- unsigned long long pledgedSrcSize,
1020
+ U64 pledgedSrcSize,
1011
1021
  ZSTD_buffered_policy_e zbuff)
1012
1022
  {
1013
1023
  DEBUGLOG(5, "ZSTD_copyCCtx_internal");
@@ -1017,6 +1027,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1017
1027
  { ZSTD_CCtx_params params = dstCCtx->requestedParams;
1018
1028
  /* Copy only compression parameters related to tables. */
1019
1029
  params.cParams = srcCCtx->appliedParams.cParams;
1030
+ if (windowLog) params.cParams.windowLog = windowLog;
1020
1031
  params.fParams = fParams;
1021
1032
  ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
1022
1033
  ZSTDcrp_noMemset, zbuff);
@@ -1045,6 +1056,12 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1045
1056
 
1046
1057
  /* copy entropy tables */
1047
1058
  memcpy(dstCCtx->entropy, srcCCtx->entropy, sizeof(ZSTD_entropyCTables_t));
1059
+ /* copy repcodes */
1060
+ {
1061
+ int i;
1062
+ for (i = 0; i < ZSTD_REP_NUM; ++i)
1063
+ dstCCtx->seqStore.rep[i] = srcCCtx->seqStore.rep[i];
1064
+ }
1048
1065
 
1049
1066
  return 0;
1050
1067
  }
@@ -1059,9 +1076,12 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long
1059
1076
  ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
1060
1077
  ZSTD_buffered_policy_e const zbuff = (ZSTD_buffered_policy_e)(srcCCtx->inBuffSize>0);
1061
1078
  ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);
1062
- fParams.contentSizeFlag = pledgedSrcSize>0;
1079
+ if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
1080
+ fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);
1063
1081
 
1064
- return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, fParams, pledgedSrcSize, zbuff);
1082
+ return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx,
1083
+ 0 /*windowLog from srcCCtx*/, fParams, pledgedSrcSize,
1084
+ zbuff);
1065
1085
  }
1066
1086
 
1067
1087
 
@@ -1238,7 +1258,7 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
1238
1258
  ostart[4] = (BYTE)(cLitSize >> 10);
1239
1259
  break;
1240
1260
  }
1241
- default: /* not possible : lhSize is {3,4,5} */
1261
+ default: /* not possible : lhSize is {3,4,5} */
1242
1262
  assert(0);
1243
1263
  }
1244
1264
  return lhSize+cLitSize;
@@ -1247,8 +1267,6 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
1247
1267
 
1248
1268
  void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1249
1269
  {
1250
- BYTE const LL_deltaCode = 19;
1251
- BYTE const ML_deltaCode = 36;
1252
1270
  const seqDef* const sequences = seqStorePtr->sequencesStart;
1253
1271
  BYTE* const llCodeTable = seqStorePtr->llCode;
1254
1272
  BYTE* const ofCodeTable = seqStorePtr->ofCode;
@@ -1258,9 +1276,9 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1258
1276
  for (u=0; u<nbSeq; u++) {
1259
1277
  U32 const llv = sequences[u].litLength;
1260
1278
  U32 const mlv = sequences[u].matchLength;
1261
- llCodeTable[u] = (llv> 63) ? (BYTE)ZSTD_highbit32(llv) + LL_deltaCode : LL_Code[llv];
1279
+ llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
1262
1280
  ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
1263
- mlCodeTable[u] = (mlv>127) ? (BYTE)ZSTD_highbit32(mlv) + ML_deltaCode : ML_Code[mlv];
1281
+ mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
1264
1282
  }
1265
1283
  if (seqStorePtr->longLengthID==1)
1266
1284
  llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
@@ -1273,7 +1291,8 @@ typedef enum {
1273
1291
  ZSTD_defaultAllowed = 1
1274
1292
  } ZSTD_defaultPolicy_e;
1275
1293
 
1276
- MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(
1294
+ MEM_STATIC
1295
+ symbolEncodingType_e ZSTD_selectEncodingType(
1277
1296
  FSE_repeat* repeatMode, size_t const mostFrequent, size_t nbSeq,
1278
1297
  U32 defaultNormLog, ZSTD_defaultPolicy_e const isDefaultAllowed)
1279
1298
  {
@@ -1281,6 +1300,7 @@ MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(
1281
1300
  #define MAX_SEQ_FOR_STATIC_FSE 1000
1282
1301
  ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
1283
1302
  if ((mostFrequent == nbSeq) && (!isDefaultAllowed || nbSeq > 2)) {
1303
+ DEBUGLOG(5, "Selected set_rle");
1284
1304
  /* Prefer set_basic over set_rle when there are 2 or less symbols,
1285
1305
  * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
1286
1306
  * If basic encoding isn't possible, always choose RLE.
@@ -1288,18 +1308,30 @@ MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(
1288
1308
  *repeatMode = FSE_repeat_check;
1289
1309
  return set_rle;
1290
1310
  }
1291
- if (isDefaultAllowed && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
1311
+ if ( isDefaultAllowed
1312
+ && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
1313
+ DEBUGLOG(5, "Selected set_repeat");
1292
1314
  return set_repeat;
1293
1315
  }
1294
- if (isDefaultAllowed && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1))))) {
1295
- *repeatMode = FSE_repeat_valid;
1316
+ if ( isDefaultAllowed
1317
+ && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1)))) ) {
1318
+ DEBUGLOG(5, "Selected set_basic");
1319
+ /* The format allows default tables to be repeated, but it isn't useful.
1320
+ * When using simple heuristics to select encoding type, we don't want
1321
+ * to confuse these tables with dictionaries. When running more careful
1322
+ * analysis, we don't need to waste time checking both repeating tables
1323
+ * and default tables.
1324
+ */
1325
+ *repeatMode = FSE_repeat_none;
1296
1326
  return set_basic;
1297
1327
  }
1328
+ DEBUGLOG(5, "Selected set_compressed");
1298
1329
  *repeatMode = FSE_repeat_check;
1299
1330
  return set_compressed;
1300
1331
  }
1301
1332
 
1302
- MEM_STATIC size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1333
+ MEM_STATIC
1334
+ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1303
1335
  FSE_CTable* CTable, U32 FSELog, symbolEncodingType_e type,
1304
1336
  U32* count, U32 max,
1305
1337
  BYTE const* codeTable, size_t nbSeq,
@@ -1317,7 +1349,7 @@ MEM_STATIC size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1317
1349
  case set_repeat:
1318
1350
  return 0;
1319
1351
  case set_basic:
1320
- CHECK_F(FSE_buildCTable_wksp(CTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize));
1352
+ CHECK_F(FSE_buildCTable_wksp(CTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
1321
1353
  return 0;
1322
1354
  case set_compressed: {
1323
1355
  S16 norm[MaxSeq + 1];
@@ -1339,11 +1371,13 @@ MEM_STATIC size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1339
1371
  }
1340
1372
  }
1341
1373
 
1342
- MEM_STATIC size_t ZSTD_encodeSequences(void* dst, size_t dstCapacity,
1343
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1344
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1345
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1346
- seqDef const* sequences, size_t nbSeq, int longOffsets)
1374
+ MEM_STATIC
1375
+ size_t ZSTD_encodeSequences(
1376
+ void* dst, size_t dstCapacity,
1377
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1378
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1379
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1380
+ seqDef const* sequences, size_t nbSeq, int longOffsets)
1347
1381
  {
1348
1382
  BIT_CStream_t blockStream;
1349
1383
  FSE_CState_t stateMatchLength;
@@ -1380,8 +1414,12 @@ MEM_STATIC size_t ZSTD_encodeSequences(void* dst, size_t dstCapacity,
1380
1414
  BYTE const ofCode = ofCodeTable[n];
1381
1415
  BYTE const mlCode = mlCodeTable[n];
1382
1416
  U32 const llBits = LL_bits[llCode];
1383
- U32 const ofBits = ofCode; /* 32b*/ /* 64b*/
1417
+ U32 const ofBits = ofCode;
1384
1418
  U32 const mlBits = ML_bits[mlCode];
1419
+ DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
1420
+ sequences[n].litLength,
1421
+ sequences[n].matchLength + MINMATCH,
1422
+ sequences[n].offset); /* 32b*/ /* 64b*/
1385
1423
  /* (7)*/ /* (7)*/
1386
1424
  FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
1387
1425
  FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
@@ -1447,14 +1485,18 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1447
1485
  entropy, cParams->strategy, op, dstCapacity, literals, litSize);
1448
1486
  if (ZSTD_isError(cSize))
1449
1487
  return cSize;
1488
+ assert(cSize <= dstCapacity);
1450
1489
  op += cSize;
1451
1490
  }
1452
1491
 
1453
1492
  /* Sequences Header */
1454
- if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
1455
- if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
1456
- else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
1457
- else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1493
+ if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/) return ERROR(dstSize_tooSmall);
1494
+ if (nbSeq < 0x7F)
1495
+ *op++ = (BYTE)nbSeq;
1496
+ else if (nbSeq < LONGNBSEQ)
1497
+ op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
1498
+ else
1499
+ op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1458
1500
  if (nbSeq==0) return op - ostart;
1459
1501
 
1460
1502
  /* seqHead : flags for FSE encoding type */
@@ -1462,9 +1504,10 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1462
1504
 
1463
1505
  /* convert length/distances into codes */
1464
1506
  ZSTD_seqToCodes(seqStorePtr);
1465
- /* CTable for Literal Lengths */
1507
+ /* build CTable for Literal Lengths */
1466
1508
  { U32 max = MaxLL;
1467
1509
  size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
1510
+ DEBUGLOG(5, "Building LL table");
1468
1511
  LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
1469
1512
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
1470
1513
  count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
@@ -1472,11 +1515,12 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1472
1515
  if (ZSTD_isError(countSize)) return countSize;
1473
1516
  op += countSize;
1474
1517
  } }
1475
- /* CTable for Offsets */
1518
+ /* build CTable for Offsets */
1476
1519
  { U32 max = MaxOff;
1477
1520
  size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
1478
1521
  /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
1479
- ZSTD_defaultPolicy_e const defaultPolicy = max <= DefaultMaxOff ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
1522
+ ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
1523
+ DEBUGLOG(5, "Building OF table");
1480
1524
  Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
1481
1525
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
1482
1526
  count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
@@ -1484,9 +1528,10 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1484
1528
  if (ZSTD_isError(countSize)) return countSize;
1485
1529
  op += countSize;
1486
1530
  } }
1487
- /* CTable for MatchLengths */
1531
+ /* build CTable for MatchLengths */
1488
1532
  { U32 max = MaxML;
1489
1533
  size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
1534
+ DEBUGLOG(5, "Building ML table");
1490
1535
  MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
1491
1536
  { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
1492
1537
  count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
@@ -1497,13 +1542,15 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1497
1542
 
1498
1543
  *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
1499
1544
 
1500
- { size_t const streamSize = ZSTD_encodeSequences(op, oend - op,
1501
- CTable_MatchLength, mlCodeTable,
1502
- CTable_OffsetBits, ofCodeTable,
1503
- CTable_LitLength, llCodeTable,
1504
- sequences, nbSeq, longOffsets);
1505
- if (ZSTD_isError(streamSize)) return streamSize;
1506
- op += streamSize;
1545
+ { size_t const bitstreamSize = ZSTD_encodeSequences(
1546
+ op, oend - op,
1547
+ CTable_MatchLength, mlCodeTable,
1548
+ CTable_OffsetBits, ofCodeTable,
1549
+ CTable_LitLength, llCodeTable,
1550
+ sequences, nbSeq,
1551
+ longOffsets);
1552
+ if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
1553
+ op += bitstreamSize;
1507
1554
  }
1508
1555
 
1509
1556
  return op - ostart;
@@ -1517,27 +1564,33 @@ MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1517
1564
  {
1518
1565
  size_t const cSize = ZSTD_compressSequences_internal(seqStorePtr, entropy, cParams,
1519
1566
  dst, dstCapacity);
1520
- size_t const minGain = ZSTD_minGain(srcSize);
1521
- size_t const maxCSize = srcSize - minGain;
1522
1567
  /* If the srcSize <= dstCapacity, then there is enough space to write a
1523
1568
  * raw uncompressed block. Since we ran out of space, the block must not
1524
1569
  * be compressible, so fall back to a raw uncompressed block.
1525
1570
  */
1526
- int const uncompressibleError = cSize == ERROR(dstSize_tooSmall) && srcSize <= dstCapacity;
1527
-
1571
+ int const uncompressibleError = (cSize == ERROR(dstSize_tooSmall)) && (srcSize <= dstCapacity);
1528
1572
  if (ZSTD_isError(cSize) && !uncompressibleError)
1529
1573
  return cSize;
1574
+ /* We check that dictionaries have offset codes available for the first
1575
+ * block. After the first block, the offcode table might not have large
1576
+ * enough codes to represent the offsets in the data.
1577
+ */
1578
+ if (entropy->offcode_repeatMode == FSE_repeat_valid)
1579
+ entropy->offcode_repeatMode = FSE_repeat_check;
1580
+
1530
1581
  /* Check compressibility */
1531
- if (cSize >= maxCSize || uncompressibleError) {
1532
- entropy->hufCTable_repeatMode = HUF_repeat_none;
1533
- entropy->offcode_repeatMode = FSE_repeat_none;
1534
- entropy->matchlength_repeatMode = FSE_repeat_none;
1535
- entropy->litlength_repeatMode = FSE_repeat_none;
1536
- return 0;
1537
- }
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
+ } }
1538
1591
  assert(!ZSTD_isError(cSize));
1539
1592
 
1540
- /* confirm repcodes */
1593
+ /* block is compressed => confirm repcodes in history */
1541
1594
  { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->rep[i] = seqStorePtr->repToConfirm[i]; }
1542
1595
  return cSize;
1543
1596
  }
@@ -1559,9 +1612,9 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict
1559
1612
  ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btultra_extDict }
1560
1613
  };
1561
1614
  ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
1615
+
1562
1616
  assert((U32)strat >= (U32)ZSTD_fast);
1563
1617
  assert((U32)strat <= (U32)ZSTD_btultra);
1564
-
1565
1618
  return blockCompressor[extDict!=0][(U32)strat];
1566
1619
  }
1567
1620
 
@@ -1572,30 +1625,38 @@ static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
1572
1625
  seqStorePtr->lit += lastLLSize;
1573
1626
  }
1574
1627
 
1628
+ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
1629
+ {
1630
+ ssPtr->lit = ssPtr->litStart;
1631
+ ssPtr->sequences = ssPtr->sequencesStart;
1632
+ ssPtr->longLengthID = 0;
1633
+ }
1634
+
1575
1635
  static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1576
1636
  {
1577
- const BYTE* const base = zc->base;
1578
- const BYTE* const istart = (const BYTE*)src;
1579
- const U32 current = (U32)(istart-base);
1580
- size_t lastLLSize;
1581
- const BYTE* anchor;
1582
- U32 const extDict = zc->lowLimit < zc->dictLimit;
1583
- const ZSTD_blockCompressor blockCompressor =
1584
- zc->appliedParams.ldmParams.enableLdm
1585
- ? (extDict ? ZSTD_compressBlock_ldm_extDict : ZSTD_compressBlock_ldm)
1586
- : ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
1587
-
1588
- if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0; /* don't even attempt compression below a certain srcSize */
1637
+ DEBUGLOG(5, "ZSTD_compressBlock_internal : dstCapacity = %u", (U32)dstCapacity);
1638
+ if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1)
1639
+ return 0; /* don't even attempt compression below a certain srcSize */
1589
1640
  ZSTD_resetSeqStore(&(zc->seqStore));
1590
- if (current > zc->nextToUpdate + 384)
1591
- zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384)); /* limited update after finding a very long match */
1592
-
1593
- lastLLSize = blockCompressor(zc, src, srcSize);
1594
-
1595
- /* Last literals */
1596
- anchor = (const BYTE*)src + srcSize - lastLLSize;
1597
- ZSTD_storeLastLiterals(&zc->seqStore, anchor, lastLLSize);
1598
1641
 
1642
+ /* limited update after a very long match */
1643
+ { const BYTE* const base = zc->base;
1644
+ const BYTE* const istart = (const BYTE*)src;
1645
+ const U32 current = (U32)(istart-base);
1646
+ if (current > zc->nextToUpdate + 384)
1647
+ zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384));
1648
+ }
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);
1658
+ }
1659
+ /* encode */
1599
1660
  return ZSTD_compressSequences(&zc->seqStore, zc->entropy, &zc->appliedParams.cParams, dst, dstCapacity, srcSize);
1600
1661
  }
1601
1662
 
@@ -1618,13 +1679,14 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
1618
1679
  BYTE* const ostart = (BYTE*)dst;
1619
1680
  BYTE* op = ostart;
1620
1681
  U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
1682
+ assert(cctx->appliedParams.cParams.windowLog <= 31);
1621
1683
 
1684
+ DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (U32)blockSize);
1622
1685
  if (cctx->appliedParams.fParams.checksumFlag && srcSize)
1623
1686
  XXH64_update(&cctx->xxhState, src, srcSize);
1624
1687
 
1625
1688
  while (remaining) {
1626
1689
  U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
1627
- size_t cSize;
1628
1690
 
1629
1691
  if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE)
1630
1692
  return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
@@ -1666,34 +1728,39 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
1666
1728
  else cctx->nextToUpdate -= correction;
1667
1729
  DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x\n", correction, cctx->lowLimit);
1668
1730
  }
1669
-
1731
+ /* enforce maxDist */
1670
1732
  if ((U32)(ip+blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) {
1671
- /* enforce maxDist */
1672
1733
  U32 const newLowLimit = (U32)(ip+blockSize - cctx->base) - maxDist;
1673
1734
  if (cctx->lowLimit < newLowLimit) cctx->lowLimit = newLowLimit;
1674
1735
  if (cctx->dictLimit < cctx->lowLimit) cctx->dictLimit = cctx->lowLimit;
1675
1736
  }
1676
1737
 
1677
- cSize = ZSTD_compressBlock_internal(cctx, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, ip, blockSize);
1678
- if (ZSTD_isError(cSize)) return cSize;
1679
-
1680
- if (cSize == 0) { /* block is not compressible */
1681
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(blockSize << 3);
1682
- if (blockSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
1683
- MEM_writeLE32(op, cBlockHeader24); /* no pb, 4th byte will be overwritten */
1684
- memcpy(op + ZSTD_blockHeaderSize, ip, blockSize);
1685
- cSize = ZSTD_blockHeaderSize+blockSize;
1686
- } else {
1687
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
1688
- MEM_writeLE24(op, cBlockHeader24);
1689
- cSize += ZSTD_blockHeaderSize;
1690
- }
1738
+ { size_t cSize = ZSTD_compressBlock_internal(cctx,
1739
+ op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
1740
+ ip, blockSize);
1741
+ if (ZSTD_isError(cSize)) return cSize;
1742
+
1743
+ if (cSize == 0) { /* block is not compressible */
1744
+ U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(blockSize << 3);
1745
+ if (blockSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
1746
+ MEM_writeLE32(op, cBlockHeader24); /* 4th byte will be overwritten */
1747
+ memcpy(op + ZSTD_blockHeaderSize, ip, blockSize);
1748
+ cSize = ZSTD_blockHeaderSize + blockSize;
1749
+ } else {
1750
+ U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
1751
+ MEM_writeLE24(op, cBlockHeader24);
1752
+ cSize += ZSTD_blockHeaderSize;
1753
+ }
1691
1754
 
1692
- remaining -= blockSize;
1693
- dstCapacity -= cSize;
1694
- ip += blockSize;
1695
- op += cSize;
1696
- }
1755
+ ip += blockSize;
1756
+ assert(remaining >= blockSize);
1757
+ remaining -= blockSize;
1758
+ op += cSize;
1759
+ assert(dstCapacity >= cSize);
1760
+ dstCapacity -= cSize;
1761
+ DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
1762
+ (U32)cSize);
1763
+ } }
1697
1764
 
1698
1765
  if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
1699
1766
  return op-ostart;
@@ -1719,7 +1786,6 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
1719
1786
  !params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
1720
1787
 
1721
1788
  if (params.format == ZSTD_f_zstd1) {
1722
- DEBUGLOG(4, "writing zstd magic number");
1723
1789
  MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
1724
1790
  pos = 4;
1725
1791
  }
@@ -1753,8 +1819,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
1753
1819
  const BYTE* const ip = (const BYTE*) src;
1754
1820
  size_t fhSize = 0;
1755
1821
 
1756
- DEBUGLOG(5, "ZSTD_compressContinue_internal");
1757
- DEBUGLOG(5, "stage: %u", cctx->stage);
1822
+ DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u", cctx->stage);
1758
1823
  if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
1759
1824
 
1760
1825
  if (frame && (cctx->stage==ZSTDcs_init)) {
@@ -1766,17 +1831,21 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
1766
1831
  cctx->stage = ZSTDcs_ongoing;
1767
1832
  }
1768
1833
 
1834
+ if (!srcSize) return fhSize; /* do not generate an empty block if no input */
1835
+
1769
1836
  /* Check if blocks follow each other */
1770
1837
  if (src != cctx->nextSrc) {
1771
1838
  /* not contiguous */
1772
- ptrdiff_t const delta = cctx->nextSrc - ip;
1839
+ size_t const distanceFromBase = (size_t)(cctx->nextSrc - cctx->base);
1773
1840
  cctx->lowLimit = cctx->dictLimit;
1774
- cctx->dictLimit = (U32)(cctx->nextSrc - cctx->base);
1841
+ assert(distanceFromBase == (size_t)(U32)distanceFromBase); /* should never overflow */
1842
+ cctx->dictLimit = (U32)distanceFromBase;
1775
1843
  cctx->dictBase = cctx->base;
1776
- cctx->base -= delta;
1844
+ cctx->base = ip - distanceFromBase;
1777
1845
  cctx->nextToUpdate = cctx->dictLimit;
1778
1846
  if (cctx->dictLimit - cctx->lowLimit < HASH_READ_SIZE) cctx->lowLimit = cctx->dictLimit; /* too small extDict */
1779
1847
  }
1848
+ cctx->nextSrc = ip + srcSize;
1780
1849
 
1781
1850
  /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
1782
1851
  if ((ip+srcSize > cctx->dictBase + cctx->lowLimit) & (ip < cctx->dictBase + cctx->dictLimit)) {
@@ -1785,17 +1854,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
1785
1854
  cctx->lowLimit = lowLimitMax;
1786
1855
  }
1787
1856
 
1788
- cctx->nextSrc = ip + srcSize;
1789
-
1790
- if (srcSize) {
1791
- size_t const cSize = frame ?
1857
+ DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (U32)cctx->blockSize);
1858
+ { size_t const cSize = frame ?
1792
1859
  ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
1793
1860
  ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
1794
1861
  if (ZSTD_isError(cSize)) return cSize;
1795
1862
  cctx->consumedSrcSize += srcSize;
1796
1863
  return cSize + fhSize;
1797
- } else
1798
- return fhSize;
1864
+ }
1799
1865
  }
1800
1866
 
1801
1867
  size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
@@ -1832,7 +1898,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
1832
1898
  zc->lowLimit = zc->dictLimit;
1833
1899
  zc->dictLimit = (U32)(zc->nextSrc - zc->base);
1834
1900
  zc->dictBase = zc->base;
1835
- zc->base += ip - zc->nextSrc;
1901
+ zc->base = ip - zc->dictLimit;
1836
1902
  zc->nextToUpdate = zc->dictLimit;
1837
1903
  zc->loadedDictEnd = zc->appliedParams.forceWindow ? 0 : (U32)(iend - zc->base);
1838
1904
 
@@ -1983,7 +2049,7 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx,
1983
2049
  const void* dict, size_t dictSize,
1984
2050
  ZSTD_dictMode_e dictMode)
1985
2051
  {
1986
- DEBUGLOG(5, "ZSTD_compress_insertDictionary");
2052
+ DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
1987
2053
  if ((dict==NULL) || (dictSize<=8)) return 0;
1988
2054
 
1989
2055
  /* dict restricted modes */
@@ -1992,7 +2058,7 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx,
1992
2058
 
1993
2059
  if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
1994
2060
  if (dictMode == ZSTD_dm_auto) {
1995
- DEBUGLOG(5, "raw content dictionary detected");
2061
+ DEBUGLOG(4, "raw content dictionary detected");
1996
2062
  return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
1997
2063
  }
1998
2064
  if (dictMode == ZSTD_dm_fullDict)
@@ -2006,21 +2072,22 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx,
2006
2072
 
2007
2073
  /*! ZSTD_compressBegin_internal() :
2008
2074
  * @return : 0, or an error code */
2009
- static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2075
+ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2010
2076
  const void* dict, size_t dictSize,
2011
2077
  ZSTD_dictMode_e dictMode,
2012
2078
  const ZSTD_CDict* cdict,
2013
- ZSTD_CCtx_params params, U64 pledgedSrcSize,
2014
- ZSTD_buffered_policy_e zbuff)
2079
+ ZSTD_CCtx_params params, U64 pledgedSrcSize,
2080
+ ZSTD_buffered_policy_e zbuff)
2015
2081
  {
2016
- DEBUGLOG(4, "ZSTD_compressBegin_internal");
2082
+ DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params.cParams.windowLog);
2017
2083
  /* params are supposed to be fully validated at this point */
2018
2084
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
2019
2085
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2020
2086
 
2021
2087
  if (cdict && cdict->dictContentSize>0) {
2088
+ cctx->requestedParams = params;
2022
2089
  return ZSTD_copyCCtx_internal(cctx, cdict->refContext,
2023
- params.fParams, pledgedSrcSize,
2090
+ params.cParams.windowLog, params.fParams, pledgedSrcSize,
2024
2091
  zbuff);
2025
2092
  }
2026
2093
 
@@ -2029,16 +2096,19 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2029
2096
  return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
2030
2097
  }
2031
2098
 
2032
- size_t ZSTD_compressBegin_advanced_internal(
2033
- ZSTD_CCtx* cctx,
2099
+ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
2034
2100
  const void* dict, size_t dictSize,
2035
2101
  ZSTD_dictMode_e dictMode,
2102
+ const ZSTD_CDict* cdict,
2036
2103
  ZSTD_CCtx_params params,
2037
2104
  unsigned long long pledgedSrcSize)
2038
2105
  {
2106
+ DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
2039
2107
  /* compression parameters verification and optimization */
2040
2108
  CHECK_F( ZSTD_checkCParams(params.cParams) );
2041
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, dictMode, NULL,
2109
+ return ZSTD_compressBegin_internal(cctx,
2110
+ dict, dictSize, dictMode,
2111
+ cdict,
2042
2112
  params, pledgedSrcSize,
2043
2113
  ZSTDb_not_buffered);
2044
2114
  }
@@ -2051,9 +2121,10 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
2051
2121
  {
2052
2122
  ZSTD_CCtx_params const cctxParams =
2053
2123
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2054
- return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dm_auto,
2055
- cctxParams,
2056
- pledgedSrcSize);
2124
+ return ZSTD_compressBegin_advanced_internal(cctx,
2125
+ dict, dictSize, ZSTD_dm_auto,
2126
+ NULL /*cdict*/,
2127
+ cctxParams, pledgedSrcSize);
2057
2128
  }
2058
2129
 
2059
2130
  size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
@@ -2061,8 +2132,9 @@ size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t di
2061
2132
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
2062
2133
  ZSTD_CCtx_params const cctxParams =
2063
2134
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2135
+ DEBUGLOG(4, "ZSTD_compressBegin_usingDict");
2064
2136
  return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
2065
- cctxParams, 0, ZSTDb_not_buffered);
2137
+ cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
2066
2138
  }
2067
2139
 
2068
2140
  size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
@@ -2143,6 +2215,7 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
2143
2215
  {
2144
2216
  ZSTD_CCtx_params const cctxParams =
2145
2217
  ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2218
+ DEBUGLOG(4, "ZSTD_compress_internal");
2146
2219
  return ZSTD_compress_advanced_internal(cctx,
2147
2220
  dst, dstCapacity,
2148
2221
  src, srcSize,
@@ -2156,6 +2229,7 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
2156
2229
  const void* dict,size_t dictSize,
2157
2230
  ZSTD_parameters params)
2158
2231
  {
2232
+ DEBUGLOG(4, "ZSTD_compress_advanced");
2159
2233
  CHECK_F(ZSTD_checkCParams(params.cParams));
2160
2234
  return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2161
2235
  }
@@ -2168,6 +2242,7 @@ size_t ZSTD_compress_advanced_internal(
2168
2242
  const void* dict,size_t dictSize,
2169
2243
  ZSTD_CCtx_params params)
2170
2244
  {
2245
+ DEBUGLOG(4, "ZSTD_compress_advanced_internal");
2171
2246
  CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
2172
2247
  params, srcSize, ZSTDb_not_buffered) );
2173
2248
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
@@ -2176,8 +2251,10 @@ size_t ZSTD_compress_advanced_internal(
2176
2251
  size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
2177
2252
  const void* dict, size_t dictSize, int compressionLevel)
2178
2253
  {
2179
- ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, dict ? dictSize : 0);
2254
+ ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0);
2180
2255
  params.fParams.contentSizeFlag = 1;
2256
+ DEBUGLOG(4, "ZSTD_compress_usingDict (level=%i, srcSize=%u, dictSize=%u)",
2257
+ compressionLevel, (U32)srcSize, (U32)dictSize);
2181
2258
  return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2182
2259
  }
2183
2260
 
@@ -2234,7 +2311,7 @@ static size_t ZSTD_initCDict_internal(
2234
2311
  ZSTD_dictMode_e dictMode,
2235
2312
  ZSTD_compressionParameters cParams)
2236
2313
  {
2237
- DEBUGLOG(5, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
2314
+ DEBUGLOG(3, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
2238
2315
  if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
2239
2316
  cdict->dictBuffer = NULL;
2240
2317
  cdict->dictContent = dictBuffer;
@@ -2264,7 +2341,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
2264
2341
  ZSTD_dictMode_e dictMode,
2265
2342
  ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
2266
2343
  {
2267
- DEBUGLOG(5, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
2344
+ DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
2268
2345
  if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
2269
2346
 
2270
2347
  { ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
@@ -2339,9 +2416,9 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
2339
2416
  + cctxSize;
2340
2417
  ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
2341
2418
  void* ptr;
2342
- DEBUGLOG(5, "(size_t)workspace & 7 : %u", (U32)(size_t)workspace & 7);
2419
+ DEBUGLOG(4, "(size_t)workspace & 7 : %u", (U32)(size_t)workspace & 7);
2343
2420
  if ((size_t)workspace & 7) return NULL; /* 8-aligned */
2344
- DEBUGLOG(5, "(workspaceSize < neededSize) : (%u < %u) => %u",
2421
+ DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
2345
2422
  (U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
2346
2423
  if (workspaceSize < neededSize) return NULL;
2347
2424
 
@@ -2373,11 +2450,11 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
2373
2450
  ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
2374
2451
  ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
2375
2452
  {
2453
+ DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
2376
2454
  if (cdict==NULL) return ERROR(dictionary_wrong);
2377
2455
  { ZSTD_CCtx_params params = cctx->requestedParams;
2378
2456
  params.cParams = ZSTD_getCParamsFromCDict(cdict);
2379
2457
  params.fParams = fParams;
2380
- DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced");
2381
2458
  return ZSTD_compressBegin_internal(cctx,
2382
2459
  NULL, 0, ZSTD_dm_auto,
2383
2460
  cdict,
@@ -2392,7 +2469,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
2392
2469
  size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
2393
2470
  {
2394
2471
  ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
2395
- DEBUGLOG(5, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
2472
+ DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
2396
2473
  return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0);
2397
2474
  }
2398
2475
 
@@ -2427,6 +2504,7 @@ size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
2427
2504
 
2428
2505
  ZSTD_CStream* ZSTD_createCStream(void)
2429
2506
  {
2507
+ DEBUGLOG(3, "ZSTD_createCStream");
2430
2508
  return ZSTD_createCStream_advanced(ZSTD_defaultCMem);
2431
2509
  }
2432
2510
 
@@ -2457,9 +2535,9 @@ size_t ZSTD_CStreamOutSize(void)
2457
2535
  }
2458
2536
 
2459
2537
  static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
2460
- const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
2461
- const ZSTD_CDict* cdict,
2462
- const ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
2538
+ const void* const dict, size_t const dictSize, ZSTD_dictMode_e const dictMode,
2539
+ const ZSTD_CDict* const cdict,
2540
+ ZSTD_CCtx_params const params, unsigned long long const pledgedSrcSize)
2463
2541
  {
2464
2542
  DEBUGLOG(4, "ZSTD_resetCStream_internal");
2465
2543
  /* params are supposed to be fully validated at this point */
@@ -2467,31 +2545,35 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
2467
2545
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2468
2546
 
2469
2547
  CHECK_F( ZSTD_compressBegin_internal(zcs,
2470
- dict, dictSize, dictMode,
2471
- cdict,
2472
- params, pledgedSrcSize,
2473
- ZSTDb_buffered) );
2548
+ dict, dictSize, dictMode,
2549
+ cdict,
2550
+ params, pledgedSrcSize,
2551
+ ZSTDb_buffered) );
2474
2552
 
2475
2553
  zcs->inToCompress = 0;
2476
2554
  zcs->inBuffPos = 0;
2477
- zcs->inBuffTarget = zcs->blockSize;
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 */
2478
2557
  zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
2479
2558
  zcs->streamStage = zcss_load;
2480
2559
  zcs->frameEnded = 0;
2481
2560
  return 0; /* ready to go */
2482
2561
  }
2483
2562
 
2563
+ /* ZSTD_resetCStream():
2564
+ * pledgedSrcSize == 0 means "unknown" */
2484
2565
  size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
2485
2566
  {
2486
2567
  ZSTD_CCtx_params params = zcs->requestedParams;
2487
- params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
2568
+ DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (U32)pledgedSrcSize);
2569
+ if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
2570
+ params.fParams.contentSizeFlag = 1;
2488
2571
  params.cParams = ZSTD_getCParamsFromCCtxParams(params, pledgedSrcSize, 0);
2489
- DEBUGLOG(4, "ZSTD_resetCStream");
2490
2572
  return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
2491
2573
  }
2492
2574
 
2493
2575
  /*! ZSTD_initCStream_internal() :
2494
- * Note : not static, but hidden (not exposed). Used by zstdmt_compress.c
2576
+ * Note : for lib/compress only. Used by zstdmt_compress.c.
2495
2577
  * Assumption 1 : params are valid
2496
2578
  * Assumption 2 : either dict, or cdict, is defined, not both */
2497
2579
  size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
@@ -2503,7 +2585,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
2503
2585
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
2504
2586
 
2505
2587
  if (dict && dictSize >= 8) {
2506
- DEBUGLOG(5, "loading dictionary of size %u", (U32)dictSize);
2588
+ DEBUGLOG(4, "loading dictionary of size %u", (U32)dictSize);
2507
2589
  if (zcs->staticSize) { /* static CCtx : never uses malloc */
2508
2590
  /* incompatible with internal cdict creation */
2509
2591
  return ERROR(memory_allocation);
@@ -2516,14 +2598,14 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
2516
2598
  if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
2517
2599
  } else {
2518
2600
  if (cdict) {
2519
- params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict */
2601
+ params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict; it includes windowLog */
2520
2602
  }
2521
2603
  ZSTD_freeCDict(zcs->cdictLocal);
2522
2604
  zcs->cdictLocal = NULL;
2523
2605
  zcs->cdict = cdict;
2524
2606
  }
2525
2607
 
2526
- params.compressionLevel = ZSTD_CLEVEL_CUSTOM;
2608
+ params.compressionLevel = ZSTD_CLEVEL_CUSTOM; /* enforce usage of cParams, instead of a dynamic derivation from cLevel (but does that happen ?) */
2527
2609
  zcs->requestedParams = params;
2528
2610
 
2529
2611
  return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
@@ -2535,8 +2617,9 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
2535
2617
  const ZSTD_CDict* cdict,
2536
2618
  ZSTD_frameParameters fParams,
2537
2619
  unsigned long long pledgedSrcSize)
2538
- { /* cannot handle NULL cdict (does not know what to do) */
2539
- if (!cdict) return ERROR(dictionary_wrong);
2620
+ {
2621
+ DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
2622
+ if (!cdict) return ERROR(dictionary_wrong); /* cannot handle NULL cdict (does not know what to do) */
2540
2623
  { ZSTD_CCtx_params params = zcs->requestedParams;
2541
2624
  params.cParams = ZSTD_getCParamsFromCDict(cdict);
2542
2625
  params.fParams = fParams;
@@ -2549,18 +2632,25 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
2549
2632
  /* note : cdict must outlive compression session */
2550
2633
  size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
2551
2634
  {
2552
- ZSTD_frameParameters const fParams = { 0 /* contentSize */, 0 /* checksum */, 0 /* hideDictID */ };
2553
- return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, 0); /* note : will check that cdict != NULL */
2635
+ ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksum */, 0 /* hideDictID */ };
2636
+ DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
2637
+ return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */
2554
2638
  }
2555
2639
 
2640
+ /* ZSTD_initCStream_advanced() :
2641
+ * pledgedSrcSize must be correct.
2642
+ * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
2643
+ * dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
2556
2644
  size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
2557
2645
  const void* dict, size_t dictSize,
2558
2646
  ZSTD_parameters params, unsigned long long pledgedSrcSize)
2559
2647
  {
2560
- ZSTD_CCtx_params const cctxParams =
2561
- ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2648
+ ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2649
+ DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u",
2650
+ (U32)pledgedSrcSize, params.fParams.contentSizeFlag);
2562
2651
  CHECK_F( ZSTD_checkCParams(params.cParams) );
2563
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, pledgedSrcSize);
2652
+ 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);
2564
2654
  }
2565
2655
 
2566
2656
  size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
@@ -2568,21 +2658,21 @@ size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t di
2568
2658
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
2569
2659
  ZSTD_CCtx_params const cctxParams =
2570
2660
  ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2571
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, 0);
2661
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
2572
2662
  }
2573
2663
 
2574
- size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
2664
+ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
2575
2665
  {
2576
- ZSTD_CCtx_params cctxParams;
2666
+ U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */
2577
2667
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
2578
- cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2579
- cctxParams.fParams.contentSizeFlag = (pledgedSrcSize>0);
2668
+ ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2580
2669
  return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, cctxParams, pledgedSrcSize);
2581
2670
  }
2582
2671
 
2583
2672
  size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
2584
2673
  {
2585
- return ZSTD_initCStream_srcSize(zcs, compressionLevel, 0);
2674
+ DEBUGLOG(4, "ZSTD_initCStream");
2675
+ return ZSTD_initCStream_srcSize(zcs, compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN);
2586
2676
  }
2587
2677
 
2588
2678
  /*====== Compression ======*/
@@ -2615,9 +2705,9 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
2615
2705
  /* check expectations */
2616
2706
  DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (U32)flushMode);
2617
2707
  assert(zcs->inBuff != NULL);
2618
- assert(zcs->inBuffSize>0);
2619
- assert(zcs->outBuff!= NULL);
2620
- assert(zcs->outBuffSize>0);
2708
+ assert(zcs->inBuffSize > 0);
2709
+ assert(zcs->outBuff != NULL);
2710
+ assert(zcs->outBuffSize > 0);
2621
2711
  assert(output->pos <= output->size);
2622
2712
  assert(input->pos <= input->size);
2623
2713
 
@@ -2757,7 +2847,7 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
2757
2847
  ZSTD_inBuffer* input,
2758
2848
  ZSTD_EndDirective endOp)
2759
2849
  {
2760
- DEBUGLOG(5, "ZSTD_compress_generic");
2850
+ DEBUGLOG(5, "ZSTD_compress_generic, endOp=%u ", (U32)endOp);
2761
2851
  /* check conditions */
2762
2852
  if (output->pos > output->size) return ERROR(GENERIC);
2763
2853
  if (input->pos > input->size) return ERROR(GENERIC);
@@ -2765,42 +2855,47 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
2765
2855
 
2766
2856
  /* transparent initialization stage */
2767
2857
  if (cctx->streamStage == zcss_init) {
2768
- ZSTD_prefixDict const prefixDict = cctx->prefixDict;
2769
2858
  ZSTD_CCtx_params params = cctx->requestedParams;
2770
- params.cParams = ZSTD_getCParamsFromCCtxParams(
2771
- cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
2859
+ ZSTD_prefixDict const prefixDict = cctx->prefixDict;
2772
2860
  memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
2773
2861
  assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
2774
2862
  DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
2863
+ if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
2864
+ params.cParams = ZSTD_getCParamsFromCCtxParams(
2865
+ cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
2775
2866
 
2776
2867
  #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 */
2777
2870
  if (params.nbThreads > 1) {
2778
- if (cctx->mtctx == NULL || cctx->appliedParams.nbThreads != params.nbThreads) {
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));
2779
2874
  ZSTDMT_freeCCtx(cctx->mtctx);
2780
2875
  cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbThreads, cctx->customMem);
2781
2876
  if (cctx->mtctx == NULL) return ERROR(memory_allocation);
2782
2877
  }
2783
2878
  DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", params.nbThreads);
2784
2879
  CHECK_F( ZSTDMT_initCStream_internal(
2785
- cctx->mtctx,
2786
- prefixDict.dict, prefixDict.dictSize, ZSTD_dm_rawContent,
2787
- cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
2880
+ cctx->mtctx,
2881
+ prefixDict.dict, prefixDict.dictSize, ZSTD_dm_rawContent,
2882
+ cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
2788
2883
  cctx->streamStage = zcss_load;
2789
2884
  cctx->appliedParams.nbThreads = params.nbThreads;
2790
2885
  } else
2791
2886
  #endif
2792
- {
2793
- CHECK_F( ZSTD_resetCStream_internal(
2887
+ { CHECK_F( ZSTD_resetCStream_internal(
2794
2888
  cctx, prefixDict.dict, prefixDict.dictSize,
2795
2889
  prefixDict.dictMode, cctx->cdict, params,
2796
2890
  cctx->pledgedSrcSizePlusOne-1) );
2891
+ assert(cctx->streamStage == zcss_load);
2892
+ assert(cctx->appliedParams.nbThreads <= 1);
2797
2893
  } }
2798
2894
 
2799
2895
  /* compression stage */
2800
2896
  #ifdef ZSTD_MULTITHREAD
2801
2897
  if (cctx->appliedParams.nbThreads > 1) {
2802
2898
  size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
2803
- DEBUGLOG(5, "ZSTDMT_compressStream_generic result : %u", (U32)flushMin);
2804
2899
  if ( ZSTD_isError(flushMin)
2805
2900
  || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
2806
2901
  ZSTD_startNewCompression(cctx);
@@ -2850,8 +2945,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
2850
2945
  { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
2851
2946
  size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4;
2852
2947
  size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize + lastBlockSize + checksumSize;
2853
- DEBUGLOG(5, "ZSTD_endStream : remaining to flush : %u",
2854
- (unsigned)toFlush);
2948
+ DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (U32)toFlush);
2855
2949
  return toFlush;
2856
2950
  }
2857
2951
  }
@@ -2880,12 +2974,12 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
2880
2974
  { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
2881
2975
  { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 13 */
2882
2976
  { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 14 */
2883
- { 22, 21, 22, 5, 5, 16, ZSTD_btlazy2 }, /* level 15 */
2884
- { 23, 22, 22, 5, 5, 16, ZSTD_btlazy2 }, /* level 16 */
2885
- { 23, 22, 22, 4, 5, 24, ZSTD_btopt }, /* level 17 */
2886
- { 23, 22, 22, 5, 4, 32, ZSTD_btopt }, /* level 18 */
2887
- { 23, 23, 22, 6, 3, 48, ZSTD_btopt }, /* level 19 */
2888
- { 25, 25, 23, 7, 3, 64, ZSTD_btultra }, /* level 20 */
2977
+ { 22, 21, 22, 4, 5, 16, ZSTD_btlazy2 }, /* level 15 */
2978
+ { 22, 21, 22, 4, 5, 48, ZSTD_btopt }, /* level 16 */
2979
+ { 23, 22, 22, 4, 4, 48, ZSTD_btopt }, /* level 17 */
2980
+ { 23, 22, 22, 5, 3, 64, ZSTD_btopt }, /* level 18 */
2981
+ { 23, 23, 22, 7, 3,128, ZSTD_btopt }, /* level 19 */
2982
+ { 25, 25, 23, 7, 3,128, ZSTD_btultra }, /* level 20 */
2889
2983
  { 26, 26, 24, 7, 3,256, ZSTD_btultra }, /* level 21 */
2890
2984
  { 27, 27, 25, 9, 3,512, ZSTD_btultra }, /* level 22 */
2891
2985
  },
@@ -3004,6 +3098,8 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
3004
3098
  }
3005
3099
  #endif
3006
3100
 
3101
+ DEBUGLOG(4, "ZSTD_getCParams: cLevel=%i, srcSize=%u, dictSize=%u => table %u",
3102
+ compressionLevel, (U32)srcSizeHint, (U32)dictSize, tableID);
3007
3103
  if (compressionLevel <= 0) compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default; no negative compressionLevel yet */
3008
3104
  if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
3009
3105
  { ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
@@ -3019,5 +3115,6 @@ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeH
3019
3115
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
3020
3116
  memset(&params, 0, sizeof(params));
3021
3117
  params.cParams = cParams;
3118
+ params.fParams.contentSizeFlag = 1;
3022
3119
  return params;
3023
3120
  }