zstdlib 0.2.0 → 0.7.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +30 -1
  3. data/README.md +2 -2
  4. data/Rakefile +1 -1
  5. data/ext/zstdlib/extconf.rb +3 -3
  6. data/ext/zstdlib/ruby/zlib-2.7/zstdlib.c +4895 -0
  7. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/bitstream.h +38 -39
  8. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/compiler.h +40 -5
  9. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/cpu.h +1 -1
  10. data/ext/zstdlib/zstd-1.4.5/lib/common/debug.c +24 -0
  11. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/debug.h +11 -31
  12. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/entropy_common.c +13 -33
  13. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/error_private.c +2 -1
  14. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/error_private.h +6 -2
  15. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/fse.h +12 -32
  16. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/fse_decompress.c +12 -35
  17. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/huf.h +15 -33
  18. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/mem.h +75 -2
  19. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/pool.c +8 -4
  20. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/pool.h +2 -2
  21. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/threading.c +50 -4
  22. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/threading.h +36 -4
  23. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/xxhash.c +23 -35
  24. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/xxhash.h +11 -31
  25. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_common.c +1 -1
  26. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_errors.h +2 -1
  27. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_internal.h +154 -26
  28. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/fse_compress.c +17 -40
  29. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/hist.c +15 -35
  30. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/hist.h +12 -32
  31. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/huf_compress.c +92 -92
  32. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_compress.c +1191 -1330
  33. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_compress_internal.h +317 -55
  34. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_literals.c +158 -0
  35. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_literals.h +29 -0
  36. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_sequences.c +419 -0
  37. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_sequences.h +54 -0
  38. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_superblock.c +845 -0
  39. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_superblock.h +32 -0
  40. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_cwksp.h +525 -0
  41. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_double_fast.c +65 -43
  42. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_double_fast.h +2 -2
  43. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_fast.c +92 -66
  44. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_fast.h +2 -2
  45. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_lazy.c +74 -42
  46. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_lazy.h +1 -1
  47. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_ldm.c +32 -10
  48. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_ldm.h +7 -2
  49. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_opt.c +81 -114
  50. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_opt.h +1 -1
  51. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstdmt_compress.c +95 -51
  52. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstdmt_compress.h +3 -2
  53. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/huf_decompress.c +76 -60
  54. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_ddict.c +12 -8
  55. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_ddict.h +2 -2
  56. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress.c +292 -172
  57. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_block.c +459 -338
  58. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_block.h +3 -3
  59. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_internal.h +18 -4
  60. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/zstd.h +265 -88
  61. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzclose.c +1 -1
  62. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzcompatibility.h +1 -1
  63. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzguts.h +0 -0
  64. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzlib.c +9 -9
  65. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzread.c +16 -8
  66. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzwrite.c +8 -8
  67. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/zstd_zlibwrapper.c +16 -12
  68. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/zstd_zlibwrapper.h +1 -1
  69. metadata +69 -62
  70. data/ext/zstdlib/zstd-1.4.0/lib/common/debug.c +0 -44
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -13,24 +13,34 @@
13
13
  ***************************************/
14
14
  #include <limits.h> /* INT_MAX */
15
15
  #include <string.h> /* memset */
16
- #include "cpu.h"
17
- #include "mem.h"
16
+ #include "../common/cpu.h"
17
+ #include "../common/mem.h"
18
18
  #include "hist.h" /* HIST_countFast_wksp */
19
19
  #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
20
- #include "fse.h"
20
+ #include "../common/fse.h"
21
21
  #define HUF_STATIC_LINKING_ONLY
22
- #include "huf.h"
22
+ #include "../common/huf.h"
23
23
  #include "zstd_compress_internal.h"
24
+ #include "zstd_compress_sequences.h"
25
+ #include "zstd_compress_literals.h"
24
26
  #include "zstd_fast.h"
25
27
  #include "zstd_double_fast.h"
26
28
  #include "zstd_lazy.h"
27
29
  #include "zstd_opt.h"
28
30
  #include "zstd_ldm.h"
31
+ #include "zstd_compress_superblock.h"
29
32
 
30
33
 
31
34
  /*-*************************************
32
35
  * Helper functions
33
36
  ***************************************/
37
+ /* ZSTD_compressBound()
38
+ * Note that the result from this function is only compatible with the "normal"
39
+ * full-block strategy.
40
+ * When there are a lot of small blocks due to frequent flush in streaming mode
41
+ * the overhead of headers can make the compressed data to be larger than the
42
+ * return value of ZSTD_compressBound().
43
+ */
34
44
  size_t ZSTD_compressBound(size_t srcSize) {
35
45
  return ZSTD_COMPRESSBOUND(srcSize);
36
46
  }
@@ -40,15 +50,15 @@ size_t ZSTD_compressBound(size_t srcSize) {
40
50
  * Context memory management
41
51
  ***************************************/
42
52
  struct ZSTD_CDict_s {
43
- void* dictBuffer;
44
53
  const void* dictContent;
45
54
  size_t dictContentSize;
46
- void* workspace;
47
- size_t workspaceSize;
55
+ U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
56
+ ZSTD_cwksp workspace;
48
57
  ZSTD_matchState_t matchState;
49
58
  ZSTD_compressedBlockState_t cBlockState;
50
59
  ZSTD_customMem customMem;
51
60
  U32 dictID;
61
+ int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */
52
62
  }; /* typedef'd to ZSTD_CDict within "zstd.h" */
53
63
 
54
64
  ZSTD_CCtx* ZSTD_createCCtx(void)
@@ -80,25 +90,26 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
80
90
  }
81
91
  }
82
92
 
83
- ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
93
+ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
84
94
  {
85
- ZSTD_CCtx* const cctx = (ZSTD_CCtx*) workspace;
95
+ ZSTD_cwksp ws;
96
+ ZSTD_CCtx* cctx;
86
97
  if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
87
98
  if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
88
- memset(workspace, 0, workspaceSize); /* may be a bit generous, could memset be smaller ? */
99
+ ZSTD_cwksp_init(&ws, workspace, workspaceSize);
100
+
101
+ cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));
102
+ if (cctx == NULL) return NULL;
103
+
104
+ memset(cctx, 0, sizeof(ZSTD_CCtx));
105
+ ZSTD_cwksp_move(&cctx->workspace, &ws);
89
106
  cctx->staticSize = workspaceSize;
90
- cctx->workSpace = (void*)(cctx+1);
91
- cctx->workSpaceSize = workspaceSize - sizeof(ZSTD_CCtx);
92
107
 
93
108
  /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
94
- if (cctx->workSpaceSize < HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t)) return NULL;
95
- assert(((size_t)cctx->workSpace & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
96
- cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)cctx->workSpace;
97
- cctx->blockState.nextCBlock = cctx->blockState.prevCBlock + 1;
98
- {
99
- void* const ptr = cctx->blockState.nextCBlock + 1;
100
- cctx->entropyWorkspace = (U32*)ptr;
101
- }
109
+ if (!ZSTD_cwksp_check_available(&cctx->workspace, HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;
110
+ cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
111
+ cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
112
+ cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, HUF_WORKSPACE_SIZE);
102
113
  cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
103
114
  return cctx;
104
115
  }
@@ -126,11 +137,11 @@ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
126
137
  {
127
138
  assert(cctx != NULL);
128
139
  assert(cctx->staticSize == 0);
129
- ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
130
140
  ZSTD_clearAllDicts(cctx);
131
141
  #ifdef ZSTD_MULTITHREAD
132
142
  ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
133
143
  #endif
144
+ ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);
134
145
  }
135
146
 
136
147
  size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
@@ -138,8 +149,13 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
138
149
  if (cctx==NULL) return 0; /* support free on NULL */
139
150
  RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
140
151
  "not compatible with static CCtx");
141
- ZSTD_freeCCtxContent(cctx);
142
- ZSTD_free(cctx, cctx->customMem);
152
+ {
153
+ int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);
154
+ ZSTD_freeCCtxContent(cctx);
155
+ if (!cctxInWorkspace) {
156
+ ZSTD_free(cctx, cctx->customMem);
157
+ }
158
+ }
143
159
  return 0;
144
160
  }
145
161
 
@@ -158,7 +174,9 @@ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
158
174
  size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
159
175
  {
160
176
  if (cctx==NULL) return 0; /* support sizeof on NULL */
161
- return sizeof(*cctx) + cctx->workSpaceSize
177
+ /* cctx may be in the workspace */
178
+ return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))
179
+ + ZSTD_cwksp_sizeof(&cctx->workspace)
162
180
  + ZSTD_sizeof_localDict(cctx->localDict)
163
181
  + ZSTD_sizeof_mtctx(cctx);
164
182
  }
@@ -215,7 +233,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
215
233
  }
216
234
 
217
235
  size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
218
- RETURN_ERROR_IF(!cctxParams, GENERIC);
236
+ RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
219
237
  memset(cctxParams, 0, sizeof(*cctxParams));
220
238
  cctxParams->compressionLevel = compressionLevel;
221
239
  cctxParams->fParams.contentSizeFlag = 1;
@@ -224,26 +242,26 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
224
242
 
225
243
  size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
226
244
  {
227
- RETURN_ERROR_IF(!cctxParams, GENERIC);
228
- FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
245
+ RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
246
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
229
247
  memset(cctxParams, 0, sizeof(*cctxParams));
248
+ assert(!ZSTD_checkCParams(params.cParams));
230
249
  cctxParams->cParams = params.cParams;
231
250
  cctxParams->fParams = params.fParams;
232
251
  cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
233
- assert(!ZSTD_checkCParams(params.cParams));
234
252
  return 0;
235
253
  }
236
254
 
237
255
  /* ZSTD_assignParamsToCCtxParams() :
238
256
  * params is presumed valid at this stage */
239
257
  static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
240
- ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
258
+ const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
241
259
  {
242
- ZSTD_CCtx_params ret = cctxParams;
243
- ret.cParams = params.cParams;
244
- ret.fParams = params.fParams;
260
+ ZSTD_CCtx_params ret = *cctxParams;
261
+ assert(!ZSTD_checkCParams(params->cParams));
262
+ ret.cParams = params->cParams;
263
+ ret.fParams = params->fParams;
245
264
  ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
246
- assert(!ZSTD_checkCParams(params.cParams));
247
265
  return ret;
248
266
  }
249
267
 
@@ -327,8 +345,13 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
327
345
  return bounds;
328
346
 
329
347
  case ZSTD_c_overlapLog:
348
+ #ifdef ZSTD_MULTITHREAD
330
349
  bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;
331
350
  bounds.upperBound = ZSTD_OVERLAPLOG_MAX;
351
+ #else
352
+ bounds.lowerBound = 0;
353
+ bounds.upperBound = 0;
354
+ #endif
332
355
  return bounds;
333
356
 
334
357
  case ZSTD_c_enableLongDistanceMatching:
@@ -376,7 +399,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
376
399
  case ZSTD_c_forceAttachDict:
377
400
  ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy);
378
401
  bounds.lowerBound = ZSTD_dictDefaultAttach;
379
- bounds.upperBound = ZSTD_dictForceCopy; /* note : how to ensure at compile time that this is the highest value enum ? */
402
+ bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */
380
403
  return bounds;
381
404
 
382
405
  case ZSTD_c_literalCompressionMode:
@@ -385,25 +408,22 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
385
408
  bounds.upperBound = ZSTD_lcm_uncompressed;
386
409
  return bounds;
387
410
 
411
+ case ZSTD_c_targetCBlockSize:
412
+ bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;
413
+ bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;
414
+ return bounds;
415
+
416
+ case ZSTD_c_srcSizeHint:
417
+ bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN;
418
+ bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;
419
+ return bounds;
420
+
388
421
  default:
389
- { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 };
390
- return boundError;
391
- }
422
+ bounds.error = ERROR(parameter_unsupported);
423
+ return bounds;
392
424
  }
393
425
  }
394
426
 
395
- /* ZSTD_cParam_withinBounds:
396
- * @return 1 if value is within cParam bounds,
397
- * 0 otherwise */
398
- static int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
399
- {
400
- ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
401
- if (ZSTD_isError(bounds.error)) return 0;
402
- if (value < bounds.lowerBound) return 0;
403
- if (value > bounds.upperBound) return 0;
404
- return 1;
405
- }
406
-
407
427
  /* ZSTD_cParam_clampBounds:
408
428
  * Clamps the value into the bounded range.
409
429
  */
@@ -418,7 +438,7 @@ static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
418
438
 
419
439
  #define BOUNDCHECK(cParam, val) { \
420
440
  RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
421
- parameter_outOfBound); \
441
+ parameter_outOfBound, "Param out of bounds"); \
422
442
  }
423
443
 
424
444
 
@@ -452,6 +472,8 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
452
472
  case ZSTD_c_ldmHashRateLog:
453
473
  case ZSTD_c_forceAttachDict:
454
474
  case ZSTD_c_literalCompressionMode:
475
+ case ZSTD_c_targetCBlockSize:
476
+ case ZSTD_c_srcSizeHint:
455
477
  default:
456
478
  return 0;
457
479
  }
@@ -464,7 +486,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
464
486
  if (ZSTD_isUpdateAuthorized(param)) {
465
487
  cctx->cParamsChanged = 1;
466
488
  } else {
467
- RETURN_ERROR(stage_wrong);
489
+ RETURN_ERROR(stage_wrong, "can only set params in ctx init stage");
468
490
  } }
469
491
 
470
492
  switch(param)
@@ -497,9 +519,11 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
497
519
  case ZSTD_c_ldmHashLog:
498
520
  case ZSTD_c_ldmMinMatch:
499
521
  case ZSTD_c_ldmBucketSizeLog:
522
+ case ZSTD_c_targetCBlockSize:
523
+ case ZSTD_c_srcSizeHint:
500
524
  break;
501
525
 
502
- default: RETURN_ERROR(parameter_unsupported);
526
+ default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
503
527
  }
504
528
  return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
505
529
  }
@@ -516,37 +540,37 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
516
540
  return (size_t)CCtxParams->format;
517
541
 
518
542
  case ZSTD_c_compressionLevel : {
519
- FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
543
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
520
544
  if (value) { /* 0 : does not change current level */
521
545
  CCtxParams->compressionLevel = value;
522
546
  }
523
- if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
547
+ if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
524
548
  return 0; /* return type (size_t) cannot represent negative values */
525
549
  }
526
550
 
527
551
  case ZSTD_c_windowLog :
528
552
  if (value!=0) /* 0 => use default */
529
553
  BOUNDCHECK(ZSTD_c_windowLog, value);
530
- CCtxParams->cParams.windowLog = value;
554
+ CCtxParams->cParams.windowLog = (U32)value;
531
555
  return CCtxParams->cParams.windowLog;
532
556
 
533
557
  case ZSTD_c_hashLog :
534
558
  if (value!=0) /* 0 => use default */
535
559
  BOUNDCHECK(ZSTD_c_hashLog, value);
536
- CCtxParams->cParams.hashLog = value;
560
+ CCtxParams->cParams.hashLog = (U32)value;
537
561
  return CCtxParams->cParams.hashLog;
538
562
 
539
563
  case ZSTD_c_chainLog :
540
564
  if (value!=0) /* 0 => use default */
541
565
  BOUNDCHECK(ZSTD_c_chainLog, value);
542
- CCtxParams->cParams.chainLog = value;
566
+ CCtxParams->cParams.chainLog = (U32)value;
543
567
  return CCtxParams->cParams.chainLog;
544
568
 
545
569
  case ZSTD_c_searchLog :
546
570
  if (value!=0) /* 0 => use default */
547
571
  BOUNDCHECK(ZSTD_c_searchLog, value);
548
- CCtxParams->cParams.searchLog = value;
549
- return value;
572
+ CCtxParams->cParams.searchLog = (U32)value;
573
+ return (size_t)value;
550
574
 
551
575
  case ZSTD_c_minMatch :
552
576
  if (value!=0) /* 0 => use default */
@@ -604,7 +628,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
604
628
  RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
605
629
  return 0;
606
630
  #else
607
- FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
631
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
608
632
  CCtxParams->nbWorkers = value;
609
633
  return CCtxParams->nbWorkers;
610
634
  #endif
@@ -617,7 +641,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
617
641
  /* Adjust to the minimum non-default value. */
618
642
  if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
619
643
  value = ZSTDMT_JOBSIZE_MIN;
620
- FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
644
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
621
645
  assert(value >= 0);
622
646
  CCtxParams->jobSize = value;
623
647
  return CCtxParams->jobSize;
@@ -628,7 +652,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
628
652
  RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
629
653
  return 0;
630
654
  #else
631
- FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
655
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
632
656
  CCtxParams->overlapLog = value;
633
657
  return CCtxParams->overlapLog;
634
658
  #endif
@@ -638,7 +662,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
638
662
  RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
639
663
  return 0;
640
664
  #else
641
- FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
665
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
642
666
  CCtxParams->rsyncable = value;
643
667
  return CCtxParams->rsyncable;
644
668
  #endif
@@ -667,10 +691,22 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
667
691
 
668
692
  case ZSTD_c_ldmHashRateLog :
669
693
  RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
670
- parameter_outOfBound);
694
+ parameter_outOfBound, "Param out of bounds!");
671
695
  CCtxParams->ldmParams.hashRateLog = value;
672
696
  return CCtxParams->ldmParams.hashRateLog;
673
697
 
698
+ case ZSTD_c_targetCBlockSize :
699
+ if (value!=0) /* 0 ==> default */
700
+ BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
701
+ CCtxParams->targetCBlockSize = value;
702
+ return CCtxParams->targetCBlockSize;
703
+
704
+ case ZSTD_c_srcSizeHint :
705
+ if (value!=0) /* 0 ==> default */
706
+ BOUNDCHECK(ZSTD_c_srcSizeHint, value);
707
+ CCtxParams->srcSizeHint = value;
708
+ return CCtxParams->srcSizeHint;
709
+
674
710
  default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
675
711
  }
676
712
  }
@@ -692,13 +728,13 @@ size_t ZSTD_CCtxParams_getParameter(
692
728
  *value = CCtxParams->compressionLevel;
693
729
  break;
694
730
  case ZSTD_c_windowLog :
695
- *value = CCtxParams->cParams.windowLog;
731
+ *value = (int)CCtxParams->cParams.windowLog;
696
732
  break;
697
733
  case ZSTD_c_hashLog :
698
- *value = CCtxParams->cParams.hashLog;
734
+ *value = (int)CCtxParams->cParams.hashLog;
699
735
  break;
700
736
  case ZSTD_c_chainLog :
701
- *value = CCtxParams->cParams.chainLog;
737
+ *value = (int)CCtxParams->cParams.chainLog;
702
738
  break;
703
739
  case ZSTD_c_searchLog :
704
740
  *value = CCtxParams->cParams.searchLog;
@@ -773,6 +809,12 @@ size_t ZSTD_CCtxParams_getParameter(
773
809
  case ZSTD_c_ldmHashRateLog :
774
810
  *value = CCtxParams->ldmParams.hashRateLog;
775
811
  break;
812
+ case ZSTD_c_targetCBlockSize :
813
+ *value = (int)CCtxParams->targetCBlockSize;
814
+ break;
815
+ case ZSTD_c_srcSizeHint :
816
+ *value = (int)CCtxParams->srcSizeHint;
817
+ break;
776
818
  default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
777
819
  }
778
820
  return 0;
@@ -789,8 +831,11 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
789
831
  ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
790
832
  {
791
833
  DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
792
- RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
793
- RETURN_ERROR_IF(cctx->cdict, stage_wrong);
834
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
835
+ "The context is in the wrong stage!");
836
+ RETURN_ERROR_IF(cctx->cdict, stage_wrong,
837
+ "Can't override parameters with cdict attached (some must "
838
+ "be inherited from the cdict).");
794
839
 
795
840
  cctx->requestedParams = *params;
796
841
  return 0;
@@ -799,7 +844,8 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
799
844
  ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
800
845
  {
801
846
  DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
802
- RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
847
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
848
+ "Can't set pledgedSrcSize when not in init stage.");
803
849
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
804
850
  return 0;
805
851
  }
@@ -813,7 +859,7 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
813
859
  {
814
860
  ZSTD_localDict* const dl = &cctx->localDict;
815
861
  ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
816
- &cctx->requestedParams, 0, dl->dictSize);
862
+ &cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize);
817
863
  if (dl->dict == NULL) {
818
864
  /* No local dictionary. */
819
865
  assert(dl->dictBuffer == NULL);
@@ -837,7 +883,7 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
837
883
  dl->dictContentType,
838
884
  cParams,
839
885
  cctx->customMem);
840
- RETURN_ERROR_IF(!dl->cdict, memory_allocation);
886
+ RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
841
887
  cctx->cdict = dl->cdict;
842
888
  return 0;
843
889
  }
@@ -846,7 +892,8 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
846
892
  ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
847
893
  ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
848
894
  {
849
- RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
895
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
896
+ "Can't load a dictionary when ctx is not in init stage.");
850
897
  RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
851
898
  "no malloc for static CCtx");
852
899
  DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
@@ -857,7 +904,7 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
857
904
  cctx->localDict.dict = dict;
858
905
  } else {
859
906
  void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
860
- RETURN_ERROR_IF(!dictBuffer, memory_allocation);
907
+ RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
861
908
  memcpy(dictBuffer, dict, dictSize);
862
909
  cctx->localDict.dictBuffer = dictBuffer;
863
910
  cctx->localDict.dict = dictBuffer;
@@ -883,7 +930,8 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
883
930
 
884
931
  size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
885
932
  {
886
- RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
933
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
934
+ "Can't ref a dict when ctx not in init stage.");
887
935
  /* Free the existing local cdict (if any) to save memory. */
888
936
  ZSTD_clearAllDicts(cctx);
889
937
  cctx->cdict = cdict;
@@ -898,11 +946,14 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz
898
946
  size_t ZSTD_CCtx_refPrefix_advanced(
899
947
  ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
900
948
  {
901
- RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
949
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
950
+ "Can't ref a prefix when ctx not in init stage.");
902
951
  ZSTD_clearAllDicts(cctx);
903
- cctx->prefixDict.dict = prefix;
904
- cctx->prefixDict.dictSize = prefixSize;
905
- cctx->prefixDict.dictContentType = dictContentType;
952
+ if (prefix != NULL && prefixSize > 0) {
953
+ cctx->prefixDict.dict = prefix;
954
+ cctx->prefixDict.dictSize = prefixSize;
955
+ cctx->prefixDict.dictContentType = dictContentType;
956
+ }
906
957
  return 0;
907
958
  }
908
959
 
@@ -917,7 +968,8 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
917
968
  }
918
969
  if ( (reset == ZSTD_reset_parameters)
919
970
  || (reset == ZSTD_reset_session_and_parameters) ) {
920
- RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
971
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
972
+ "Can't reset parameters only when not in init stage.");
921
973
  ZSTD_clearAllDicts(cctx);
922
974
  return ZSTD_CCtxParams_reset(&cctx->requestedParams);
923
975
  }
@@ -930,12 +982,12 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
930
982
  @return : 0, or an error code if one value is beyond authorized range */
931
983
  size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
932
984
  {
933
- BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog);
934
- BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog);
935
- BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog);
936
- BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog);
937
- BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch);
938
- BOUNDCHECK(ZSTD_c_targetLength,cParams.targetLength);
985
+ BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);
986
+ BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog);
987
+ BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog);
988
+ BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);
989
+ BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch);
990
+ BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);
939
991
  BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
940
992
  return 0;
941
993
  }
@@ -951,7 +1003,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
951
1003
  if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
952
1004
  else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
953
1005
  }
954
- # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, int)
1006
+ # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
955
1007
  CLAMP(ZSTD_c_windowLog, cParams.windowLog);
956
1008
  CLAMP(ZSTD_c_chainLog, cParams.chainLog);
957
1009
  CLAMP(ZSTD_c_hashLog, cParams.hashLog);
@@ -964,7 +1016,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
964
1016
 
965
1017
  /** ZSTD_cycleLog() :
966
1018
  * condition for correct operation : hashLog > 1 */
967
- static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
1019
+ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
968
1020
  {
969
1021
  U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
970
1022
  return hashLog - btScale;
@@ -974,7 +1026,7 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
974
1026
  * optimize `cPar` for a specified input (`srcSize` and `dictSize`).
975
1027
  * mostly downsize to reduce memory consumption and initialization latency.
976
1028
  * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
977
- * note : for the time being, `srcSize==0` means "unknown" too, for compatibility with older convention.
1029
+ * note : `srcSize==0` means 0!
978
1030
  * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
979
1031
  static ZSTD_compressionParameters
980
1032
  ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
@@ -985,10 +1037,8 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
985
1037
  static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
986
1038
  assert(ZSTD_checkCParams(cPar)==0);
987
1039
 
988
- if (dictSize && (srcSize+1<2) /* ZSTD_CONTENTSIZE_UNKNOWN and 0 mean "unknown" */ )
989
- srcSize = minSrcSize; /* presumed small when there is a dictionary */
990
- else if (srcSize == 0)
991
- srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
1040
+ if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
1041
+ srcSize = minSrcSize;
992
1042
 
993
1043
  /* resize windowLog if input is small enough, to use less memory */
994
1044
  if ( (srcSize < maxWindowResize)
@@ -1017,13 +1067,21 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
1017
1067
  size_t dictSize)
1018
1068
  {
1019
1069
  cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
1070
+ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
1020
1071
  return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
1021
1072
  }
1022
1073
 
1074
+ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
1075
+ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
1076
+
1023
1077
  ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
1024
1078
  const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
1025
1079
  {
1026
- ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
1080
+ ZSTD_compressionParameters cParams;
1081
+ if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {
1082
+ srcSizeHint = CCtxParams->srcSizeHint;
1083
+ }
1084
+ cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize);
1027
1085
  if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
1028
1086
  if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
1029
1087
  if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
@@ -1033,6 +1091,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
1033
1091
  if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
1034
1092
  if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
1035
1093
  assert(!ZSTD_checkCParams(cParams));
1094
+ /* srcSizeHint == 0 means 0 */
1036
1095
  return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
1037
1096
  }
1038
1097
 
@@ -1043,10 +1102,19 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
1043
1102
  size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
1044
1103
  size_t const hSize = ((size_t)1) << cParams->hashLog;
1045
1104
  U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
1046
- size_t const h3Size = ((size_t)1) << hashLog3;
1047
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
1048
- size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
1049
- + (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
1105
+ size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
1106
+ /* We don't use ZSTD_cwksp_alloc_size() here because the tables aren't
1107
+ * surrounded by redzones in ASAN. */
1108
+ size_t const tableSpace = chainSize * sizeof(U32)
1109
+ + hSize * sizeof(U32)
1110
+ + h3Size * sizeof(U32);
1111
+ size_t const optPotentialSpace =
1112
+ ZSTD_cwksp_alloc_size((MaxML+1) * sizeof(U32))
1113
+ + ZSTD_cwksp_alloc_size((MaxLL+1) * sizeof(U32))
1114
+ + ZSTD_cwksp_alloc_size((MaxOff+1) * sizeof(U32))
1115
+ + ZSTD_cwksp_alloc_size((1<<Litbits) * sizeof(U32))
1116
+ + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
1117
+ + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
1050
1118
  size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
1051
1119
  ? optPotentialSpace
1052
1120
  : 0;
@@ -1059,24 +1127,40 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1059
1127
  {
1060
1128
  RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
1061
1129
  { ZSTD_compressionParameters const cParams =
1062
- ZSTD_getCParamsFromCCtxParams(params, 0, 0);
1130
+ ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1063
1131
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
1064
1132
  U32 const divider = (cParams.minMatch==3) ? 3 : 4;
1065
1133
  size_t const maxNbSeq = blockSize / divider;
1066
- size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
1067
- size_t const entropySpace = HUF_WORKSPACE_SIZE;
1068
- size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
1134
+ size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
1135
+ + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
1136
+ + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
1137
+ size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE);
1138
+ size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
1069
1139
  size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
1070
1140
 
1071
1141
  size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
1072
- size_t const ldmSeqSpace = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq);
1073
-
1074
- size_t const neededSpace = entropySpace + blockStateSpace + tokenSpace +
1075
- matchStateSize + ldmSpace + ldmSeqSpace;
1076
-
1077
- DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
1078
- DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
1079
- return sizeof(ZSTD_CCtx) + neededSpace;
1142
+ size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq));
1143
+
1144
+ /* estimateCCtxSize is for one-shot compression. So no buffers should
1145
+ * be needed. However, we still allocate two 0-sized buffers, which can
1146
+ * take space under ASAN. */
1147
+ size_t const bufferSpace = ZSTD_cwksp_alloc_size(0)
1148
+ + ZSTD_cwksp_alloc_size(0);
1149
+
1150
+ size_t const cctxSpace = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx));
1151
+
1152
+ size_t const neededSpace =
1153
+ cctxSpace +
1154
+ entropySpace +
1155
+ blockStateSpace +
1156
+ ldmSpace +
1157
+ ldmSeqSpace +
1158
+ matchStateSize +
1159
+ tokenSpace +
1160
+ bufferSpace;
1161
+
1162
+ DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
1163
+ return neededSpace;
1080
1164
  }
1081
1165
  }
1082
1166
 
@@ -1088,7 +1172,7 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
1088
1172
 
1089
1173
  static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
1090
1174
  {
1091
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
1175
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1092
1176
  return ZSTD_estimateCCtxSize_usingCParams(cParams);
1093
1177
  }
1094
1178
 
@@ -1107,12 +1191,13 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1107
1191
  {
1108
1192
  RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
1109
1193
  { ZSTD_compressionParameters const cParams =
1110
- ZSTD_getCParamsFromCCtxParams(params, 0, 0);
1194
+ ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1111
1195
  size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
1112
1196
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
1113
1197
  size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
1114
1198
  size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
1115
- size_t const streamingSize = inBuffSize + outBuffSize;
1199
+ size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize)
1200
+ + ZSTD_cwksp_alloc_size(outBuffSize);
1116
1201
 
1117
1202
  return CCtxSize + streamingSize;
1118
1203
  }
@@ -1126,7 +1211,7 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
1126
1211
 
1127
1212
  static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
1128
1213
  {
1129
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
1214
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1130
1215
  return ZSTD_estimateCStreamSize_usingCParams(cParams);
1131
1216
  }
1132
1217
 
@@ -1180,17 +1265,6 @@ size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
1180
1265
  return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */
1181
1266
  }
1182
1267
 
1183
-
1184
-
1185
- static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
1186
- ZSTD_compressionParameters cParams2)
1187
- {
1188
- return (cParams1.hashLog == cParams2.hashLog)
1189
- & (cParams1.chainLog == cParams2.chainLog)
1190
- & (cParams1.strategy == cParams2.strategy) /* opt parser space */
1191
- & ((cParams1.minMatch==3) == (cParams2.minMatch==3)); /* hashlog3 space */
1192
- }
1193
-
1194
1268
  static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
1195
1269
  ZSTD_compressionParameters cParams2)
1196
1270
  {
@@ -1205,72 +1279,7 @@ static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
1205
1279
  assert(cParams1.strategy == cParams2.strategy);
1206
1280
  }
1207
1281
 
1208
- /** The parameters are equivalent if ldm is not enabled in both sets or
1209
- * all the parameters are equivalent. */
1210
- static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
1211
- ldmParams_t ldmParams2)
1212
- {
1213
- return (!ldmParams1.enableLdm && !ldmParams2.enableLdm) ||
1214
- (ldmParams1.enableLdm == ldmParams2.enableLdm &&
1215
- ldmParams1.hashLog == ldmParams2.hashLog &&
1216
- ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
1217
- ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
1218
- ldmParams1.hashRateLog == ldmParams2.hashRateLog);
1219
- }
1220
-
1221
- typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
1222
-
1223
- /* ZSTD_sufficientBuff() :
1224
- * check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
1225
- * Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
1226
- static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t maxNbSeq1,
1227
- size_t maxNbLit1,
1228
- ZSTD_buffered_policy_e buffPol2,
1229
- ZSTD_compressionParameters cParams2,
1230
- U64 pledgedSrcSize)
1231
- {
1232
- size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
1233
- size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
1234
- size_t const maxNbSeq2 = blockSize2 / ((cParams2.minMatch == 3) ? 3 : 4);
1235
- size_t const maxNbLit2 = blockSize2;
1236
- size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
1237
- DEBUGLOG(4, "ZSTD_sufficientBuff: is neededBufferSize2=%u <= bufferSize1=%u",
1238
- (U32)neededBufferSize2, (U32)bufferSize1);
1239
- DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbSeq2=%u <= maxNbSeq1=%u",
1240
- (U32)maxNbSeq2, (U32)maxNbSeq1);
1241
- DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbLit2=%u <= maxNbLit1=%u",
1242
- (U32)maxNbLit2, (U32)maxNbLit1);
1243
- return (maxNbLit2 <= maxNbLit1)
1244
- & (maxNbSeq2 <= maxNbSeq1)
1245
- & (neededBufferSize2 <= bufferSize1);
1246
- }
1247
-
1248
- /** Equivalence for resetCCtx purposes */
1249
- static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
1250
- ZSTD_CCtx_params params2,
1251
- size_t buffSize1,
1252
- size_t maxNbSeq1, size_t maxNbLit1,
1253
- ZSTD_buffered_policy_e buffPol2,
1254
- U64 pledgedSrcSize)
1255
- {
1256
- DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
1257
- if (!ZSTD_equivalentCParams(params1.cParams, params2.cParams)) {
1258
- DEBUGLOG(4, "ZSTD_equivalentCParams() == 0");
1259
- return 0;
1260
- }
1261
- if (!ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams)) {
1262
- DEBUGLOG(4, "ZSTD_equivalentLdmParams() == 0");
1263
- return 0;
1264
- }
1265
- if (!ZSTD_sufficientBuff(buffSize1, maxNbSeq1, maxNbLit1, buffPol2,
1266
- params2.cParams, pledgedSrcSize)) {
1267
- DEBUGLOG(4, "ZSTD_sufficientBuff() == 0");
1268
- return 0;
1269
- }
1270
- return 1;
1271
- }
1272
-
1273
- static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
1282
+ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
1274
1283
  {
1275
1284
  int i;
1276
1285
  for (i = 0; i < ZSTD_REP_NUM; ++i)
@@ -1282,132 +1291,143 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
1282
1291
  }
1283
1292
 
1284
1293
  /*! ZSTD_invalidateMatchState()
1285
- * Invalidate all the matches in the match finder tables.
1286
- * Requires nextSrc and base to be set (can be NULL).
1294
+ * Invalidate all the matches in the match finder tables.
1295
+ * Requires nextSrc and base to be set (can be NULL).
1287
1296
  */
1288
1297
  static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
1289
1298
  {
1290
1299
  ZSTD_window_clear(&ms->window);
1291
1300
 
1292
1301
  ms->nextToUpdate = ms->window.dictLimit;
1293
- ms->nextToUpdate3 = ms->window.dictLimit;
1294
1302
  ms->loadedDictEnd = 0;
1295
1303
  ms->opt.litLengthSum = 0; /* force reset of btopt stats */
1296
1304
  ms->dictMatchState = NULL;
1297
1305
  }
1298
1306
 
1299
- /*! ZSTD_continueCCtx() :
1300
- * reuse CCtx without reset (note : requires no dictionary) */
1301
- static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
1302
- {
1303
- size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
1304
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
1305
- DEBUGLOG(4, "ZSTD_continueCCtx: re-use context in place");
1307
+ /**
1308
+ * Indicates whether this compression proceeds directly from user-provided
1309
+ * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or
1310
+ * whether the context needs to buffer the input/output (ZSTDb_buffered).
1311
+ */
1312
+ typedef enum {
1313
+ ZSTDb_not_buffered,
1314
+ ZSTDb_buffered
1315
+ } ZSTD_buffered_policy_e;
1306
1316
 
1307
- cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
1308
- cctx->appliedParams = params;
1309
- cctx->blockState.matchState.cParams = params.cParams;
1310
- cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
1311
- cctx->consumedSrcSize = 0;
1312
- cctx->producedCSize = 0;
1313
- if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
1314
- cctx->appliedParams.fParams.contentSizeFlag = 0;
1315
- DEBUGLOG(4, "pledged content size : %u ; flag : %u",
1316
- (U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
1317
- cctx->stage = ZSTDcs_init;
1318
- cctx->dictID = 0;
1319
- if (params.ldmParams.enableLdm)
1320
- ZSTD_window_clear(&cctx->ldmState.window);
1321
- ZSTD_referenceExternalSequences(cctx, NULL, 0);
1322
- ZSTD_invalidateMatchState(&cctx->blockState.matchState);
1323
- ZSTD_reset_compressedBlockState(cctx->blockState.prevCBlock);
1324
- XXH64_reset(&cctx->xxhState, 0);
1325
- return 0;
1326
- }
1317
+ /**
1318
+ * Controls, for this matchState reset, whether the tables need to be cleared /
1319
+ * prepared for the coming compression (ZSTDcrp_makeClean), or whether the
1320
+ * tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a
1321
+ * subsequent operation will overwrite the table space anyways (e.g., copying
1322
+ * the matchState contents in from a CDict).
1323
+ */
1324
+ typedef enum {
1325
+ ZSTDcrp_makeClean,
1326
+ ZSTDcrp_leaveDirty
1327
+ } ZSTD_compResetPolicy_e;
1327
1328
 
1328
- typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
1329
+ /**
1330
+ * Controls, for this matchState reset, whether indexing can continue where it
1331
+ * left off (ZSTDirp_continue), or whether it needs to be restarted from zero
1332
+ * (ZSTDirp_reset).
1333
+ */
1334
+ typedef enum {
1335
+ ZSTDirp_continue,
1336
+ ZSTDirp_reset
1337
+ } ZSTD_indexResetPolicy_e;
1338
+
1339
+ typedef enum {
1340
+ ZSTD_resetTarget_CDict,
1341
+ ZSTD_resetTarget_CCtx
1342
+ } ZSTD_resetTarget_e;
1329
1343
 
1330
- static void*
1344
+ static size_t
1331
1345
  ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1332
- void* ptr,
1346
+ ZSTD_cwksp* ws,
1333
1347
  const ZSTD_compressionParameters* cParams,
1334
- ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
1348
+ const ZSTD_compResetPolicy_e crp,
1349
+ const ZSTD_indexResetPolicy_e forceResetIndex,
1350
+ const ZSTD_resetTarget_e forWho)
1335
1351
  {
1336
1352
  size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
1337
1353
  size_t const hSize = ((size_t)1) << cParams->hashLog;
1338
- U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
1339
- size_t const h3Size = ((size_t)1) << hashLog3;
1340
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
1354
+ U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
1355
+ size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
1341
1356
 
1342
- assert(((size_t)ptr & 3) == 0);
1357
+ DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset);
1358
+ if (forceResetIndex == ZSTDirp_reset) {
1359
+ ZSTD_window_init(&ms->window);
1360
+ ZSTD_cwksp_mark_tables_dirty(ws);
1361
+ }
1343
1362
 
1344
1363
  ms->hashLog3 = hashLog3;
1345
- memset(&ms->window, 0, sizeof(ms->window));
1346
- ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */
1347
- ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
1348
- ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
1364
+
1349
1365
  ZSTD_invalidateMatchState(ms);
1350
1366
 
1367
+ assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */
1368
+
1369
+ ZSTD_cwksp_clear_tables(ws);
1370
+
1371
+ DEBUGLOG(5, "reserving table space");
1372
+ /* table Space */
1373
+ ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32));
1374
+ ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32));
1375
+ ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32));
1376
+ RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
1377
+ "failed a workspace allocation in ZSTD_reset_matchState");
1378
+
1379
+ DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_leaveDirty);
1380
+ if (crp!=ZSTDcrp_leaveDirty) {
1381
+ /* reset tables only */
1382
+ ZSTD_cwksp_clean_tables(ws);
1383
+ }
1384
+
1351
1385
  /* opt parser space */
1352
- if (forCCtx && (cParams->strategy >= ZSTD_btopt)) {
1386
+ if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
1353
1387
  DEBUGLOG(4, "reserving optimal parser space");
1354
- ms->opt.litFreq = (unsigned*)ptr;
1355
- ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits);
1356
- ms->opt.matchLengthFreq = ms->opt.litLengthFreq + (MaxLL+1);
1357
- ms->opt.offCodeFreq = ms->opt.matchLengthFreq + (MaxML+1);
1358
- ptr = ms->opt.offCodeFreq + (MaxOff+1);
1359
- ms->opt.matchTable = (ZSTD_match_t*)ptr;
1360
- ptr = ms->opt.matchTable + ZSTD_OPT_NUM+1;
1361
- ms->opt.priceTable = (ZSTD_optimal_t*)ptr;
1362
- ptr = ms->opt.priceTable + ZSTD_OPT_NUM+1;
1388
+ ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<<Litbits) * sizeof(unsigned));
1389
+ ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned));
1390
+ ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned));
1391
+ ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned));
1392
+ ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t));
1393
+ ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
1363
1394
  }
1364
1395
 
1365
- /* table Space */
1366
- DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
1367
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1368
- if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
1369
- ms->hashTable = (U32*)(ptr);
1370
- ms->chainTable = ms->hashTable + hSize;
1371
- ms->hashTable3 = ms->chainTable + chainSize;
1372
- ptr = ms->hashTable3 + h3Size;
1373
-
1374
1396
  ms->cParams = *cParams;
1375
1397
 
1376
- assert(((size_t)ptr & 3) == 0);
1377
- return ptr;
1398
+ RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
1399
+ "failed a workspace allocation in ZSTD_reset_matchState");
1400
+
1401
+ return 0;
1378
1402
  }
1379
1403
 
1380
- #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */
1381
- #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large
1382
- * during at least this number of times,
1383
- * context's memory usage is considered wasteful,
1384
- * because it's sized to handle a worst case scenario which rarely happens.
1385
- * In which case, resize it down to free some memory */
1404
+ /* ZSTD_indexTooCloseToMax() :
1405
+ * minor optimization : prefer memset() rather than reduceIndex()
1406
+ * which is measurably slow in some circumstances (reported for Visual Studio).
1407
+ * Works when re-using a context for a lot of smallish inputs :
1408
+ * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN,
1409
+ * memset() will be triggered before reduceIndex().
1410
+ */
1411
+ #define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)
1412
+ static int ZSTD_indexTooCloseToMax(ZSTD_window_t w)
1413
+ {
1414
+ return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
1415
+ }
1386
1416
 
1387
1417
  /*! ZSTD_resetCCtx_internal() :
1388
1418
  note : `params` are assumed fully validated at this stage */
1389
1419
  static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1390
1420
  ZSTD_CCtx_params params,
1391
- U64 pledgedSrcSize,
1421
+ U64 const pledgedSrcSize,
1392
1422
  ZSTD_compResetPolicy_e const crp,
1393
1423
  ZSTD_buffered_policy_e const zbuff)
1394
1424
  {
1425
+ ZSTD_cwksp* const ws = &zc->workspace;
1395
1426
  DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
1396
1427
  (U32)pledgedSrcSize, params.cParams.windowLog);
1397
1428
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
1398
1429
 
1399
- if (crp == ZSTDcrp_continue) {
1400
- if (ZSTD_equivalentParams(zc->appliedParams, params,
1401
- zc->inBuffSize,
1402
- zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
1403
- zbuff, pledgedSrcSize)) {
1404
- DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
1405
- zc->appliedParams.cParams.windowLog, zc->blockSize);
1406
- zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
1407
- if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
1408
- return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
1409
- } }
1410
- DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
1430
+ zc->isFirstBlock = 1;
1411
1431
 
1412
1432
  if (params.ldmParams.enableLdm) {
1413
1433
  /* Adjust long distance matching parameters */
@@ -1421,58 +1441,74 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1421
1441
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
1422
1442
  U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
1423
1443
  size_t const maxNbSeq = blockSize / divider;
1424
- size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
1444
+ size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
1445
+ + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
1446
+ + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
1425
1447
  size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
1426
1448
  size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
1427
1449
  size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
1428
1450
  size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
1429
- void* ptr; /* used to partition workSpace */
1430
1451
 
1431
- /* Check if workSpace is large enough, alloc a new one if needed */
1432
- { size_t const entropySpace = HUF_WORKSPACE_SIZE;
1433
- size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
1434
- size_t const bufferSpace = buffInSize + buffOutSize;
1452
+ ZSTD_indexResetPolicy_e needsIndexReset = zc->initialized ? ZSTDirp_continue : ZSTDirp_reset;
1453
+
1454
+ if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) {
1455
+ needsIndexReset = ZSTDirp_reset;
1456
+ }
1457
+
1458
+ if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
1459
+
1460
+ /* Check if workspace is large enough, alloc a new one if needed */
1461
+ { size_t const cctxSpace = zc->staticSize ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
1462
+ size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE);
1463
+ size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
1464
+ size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + ZSTD_cwksp_alloc_size(buffOutSize);
1435
1465
  size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
1436
- size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq);
1466
+ size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq));
1437
1467
 
1438
- size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
1439
- ldmSeqSpace + matchStateSize + tokenSpace +
1440
- bufferSpace;
1468
+ size_t const neededSpace =
1469
+ cctxSpace +
1470
+ entropySpace +
1471
+ blockStateSpace +
1472
+ ldmSpace +
1473
+ ldmSeqSpace +
1474
+ matchStateSize +
1475
+ tokenSpace +
1476
+ bufferSpace;
1441
1477
 
1442
- int const workSpaceTooSmall = zc->workSpaceSize < neededSpace;
1443
- int const workSpaceTooLarge = zc->workSpaceSize > ZSTD_WORKSPACETOOLARGE_FACTOR * neededSpace;
1444
- int const workSpaceWasteful = workSpaceTooLarge && (zc->workSpaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION);
1445
- zc->workSpaceOversizedDuration = workSpaceTooLarge ? zc->workSpaceOversizedDuration+1 : 0;
1478
+ int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
1479
+ int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
1446
1480
 
1447
1481
  DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
1448
1482
  neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
1449
1483
  DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
1450
1484
 
1451
- if (workSpaceTooSmall || workSpaceWasteful) {
1452
- DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB",
1453
- zc->workSpaceSize >> 10,
1485
+ if (workspaceTooSmall || workspaceWasteful) {
1486
+ DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
1487
+ ZSTD_cwksp_sizeof(ws) >> 10,
1454
1488
  neededSpace >> 10);
1455
1489
 
1456
1490
  RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
1457
1491
 
1458
- zc->workSpaceSize = 0;
1459
- ZSTD_free(zc->workSpace, zc->customMem);
1460
- zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
1461
- RETURN_ERROR_IF(zc->workSpace == NULL, memory_allocation);
1462
- zc->workSpaceSize = neededSpace;
1463
- zc->workSpaceOversizedDuration = 0;
1492
+ needsIndexReset = ZSTDirp_reset;
1464
1493
 
1494
+ ZSTD_cwksp_free(ws, zc->customMem);
1495
+ FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), "");
1496
+
1497
+ DEBUGLOG(5, "reserving object space");
1465
1498
  /* Statically sized space.
1466
1499
  * entropyWorkspace never moves,
1467
1500
  * though prev/next block swap places */
1468
- assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */
1469
- assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t));
1470
- zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace;
1471
- zc->blockState.nextCBlock = zc->blockState.prevCBlock + 1;
1472
- ptr = zc->blockState.nextCBlock + 1;
1473
- zc->entropyWorkspace = (U32*)ptr;
1501
+ assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t)));
1502
+ zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
1503
+ RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
1504
+ zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
1505
+ RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
1506
+ zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, HUF_WORKSPACE_SIZE);
1507
+ RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
1474
1508
  } }
1475
1509
 
1510
+ ZSTD_cwksp_clear(ws);
1511
+
1476
1512
  /* init params */
1477
1513
  zc->appliedParams = params;
1478
1514
  zc->blockState.matchState.cParams = params.cParams;
@@ -1491,57 +1527,60 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1491
1527
 
1492
1528
  ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
1493
1529
 
1494
- ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32;
1495
-
1496
- /* ldm hash table */
1497
- /* initialize bucketOffsets table later for pointer alignment */
1498
- if (params.ldmParams.enableLdm) {
1499
- size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
1500
- memset(ptr, 0, ldmHSize * sizeof(ldmEntry_t));
1501
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1502
- zc->ldmState.hashTable = (ldmEntry_t*)ptr;
1503
- ptr = zc->ldmState.hashTable + ldmHSize;
1504
- zc->ldmSequences = (rawSeq*)ptr;
1505
- ptr = zc->ldmSequences + maxNbLdmSeq;
1506
- zc->maxNbLdmSequences = maxNbLdmSeq;
1507
-
1508
- memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window));
1509
- }
1510
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1511
-
1512
- ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
1513
-
1514
- /* sequences storage */
1515
- zc->seqStore.maxNbSeq = maxNbSeq;
1516
- zc->seqStore.sequencesStart = (seqDef*)ptr;
1517
- ptr = zc->seqStore.sequencesStart + maxNbSeq;
1518
- zc->seqStore.llCode = (BYTE*) ptr;
1519
- zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
1520
- zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
1521
- zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
1522
1530
  /* ZSTD_wildcopy() is used to copy into the literals buffer,
1523
1531
  * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
1524
1532
  */
1533
+ zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);
1525
1534
  zc->seqStore.maxNbLit = blockSize;
1526
- ptr = zc->seqStore.litStart + blockSize + WILDCOPY_OVERLENGTH;
1535
+
1536
+ /* buffers */
1537
+ zc->inBuffSize = buffInSize;
1538
+ zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);
1539
+ zc->outBuffSize = buffOutSize;
1540
+ zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);
1527
1541
 
1528
1542
  /* ldm bucketOffsets table */
1529
1543
  if (params.ldmParams.enableLdm) {
1544
+ /* TODO: avoid memset? */
1530
1545
  size_t const ldmBucketSize =
1531
1546
  ((size_t)1) << (params.ldmParams.hashLog -
1532
1547
  params.ldmParams.bucketSizeLog);
1533
- memset(ptr, 0, ldmBucketSize);
1534
- zc->ldmState.bucketOffsets = (BYTE*)ptr;
1535
- ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
1536
- ZSTD_window_clear(&zc->ldmState.window);
1548
+ zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize);
1549
+ memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize);
1537
1550
  }
1551
+
1552
+ /* sequences storage */
1538
1553
  ZSTD_referenceExternalSequences(zc, NULL, 0);
1554
+ zc->seqStore.maxNbSeq = maxNbSeq;
1555
+ zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
1556
+ zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
1557
+ zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
1558
+ zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef));
1559
+
1560
+ FORWARD_IF_ERROR(ZSTD_reset_matchState(
1561
+ &zc->blockState.matchState,
1562
+ ws,
1563
+ &params.cParams,
1564
+ crp,
1565
+ needsIndexReset,
1566
+ ZSTD_resetTarget_CCtx), "");
1539
1567
 
1540
- /* buffers */
1541
- zc->inBuffSize = buffInSize;
1542
- zc->inBuff = (char*)ptr;
1543
- zc->outBuffSize = buffOutSize;
1544
- zc->outBuff = zc->inBuff + buffInSize;
1568
+ /* ldm hash table */
1569
+ if (params.ldmParams.enableLdm) {
1570
+ /* TODO: avoid memset? */
1571
+ size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
1572
+ zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t));
1573
+ memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));
1574
+ zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq));
1575
+ zc->maxNbLdmSequences = maxNbLdmSeq;
1576
+
1577
+ ZSTD_window_init(&zc->ldmState.window);
1578
+ ZSTD_window_clear(&zc->ldmState.window);
1579
+ zc->ldmState.loadedDictEnd = 0;
1580
+ }
1581
+
1582
+ DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
1583
+ zc->initialized = 1;
1545
1584
 
1546
1585
  return 0;
1547
1586
  }
@@ -1575,40 +1614,39 @@ static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {
1575
1614
  };
1576
1615
 
1577
1616
  static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
1578
- ZSTD_CCtx_params params,
1617
+ const ZSTD_CCtx_params* params,
1579
1618
  U64 pledgedSrcSize)
1580
1619
  {
1581
1620
  size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
1582
1621
  return ( pledgedSrcSize <= cutoff
1583
1622
  || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
1584
- || params.attachDictPref == ZSTD_dictForceAttach )
1585
- && params.attachDictPref != ZSTD_dictForceCopy
1586
- && !params.forceWindow; /* dictMatchState isn't correctly
1623
+ || params->attachDictPref == ZSTD_dictForceAttach )
1624
+ && params->attachDictPref != ZSTD_dictForceCopy
1625
+ && !params->forceWindow; /* dictMatchState isn't correctly
1587
1626
  * handled in _enforceMaxDist */
1588
1627
  }
1589
1628
 
1590
- static size_t ZSTD_resetCCtx_byAttachingCDict(
1591
- ZSTD_CCtx* cctx,
1592
- const ZSTD_CDict* cdict,
1593
- ZSTD_CCtx_params params,
1594
- U64 pledgedSrcSize,
1595
- ZSTD_buffered_policy_e zbuff)
1629
+ static size_t
1630
+ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
1631
+ const ZSTD_CDict* cdict,
1632
+ ZSTD_CCtx_params params,
1633
+ U64 pledgedSrcSize,
1634
+ ZSTD_buffered_policy_e zbuff)
1596
1635
  {
1597
- {
1598
- const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1636
+ { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams;
1599
1637
  unsigned const windowLog = params.cParams.windowLog;
1600
1638
  assert(windowLog != 0);
1601
1639
  /* Resize working context table params for input only, since the dict
1602
1640
  * has its own tables. */
1641
+ /* pledgeSrcSize == 0 means 0! */
1603
1642
  params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
1604
1643
  params.cParams.windowLog = windowLog;
1605
- ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1606
- ZSTDcrp_continue, zbuff);
1644
+ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1645
+ ZSTDcrp_makeClean, zbuff), "");
1607
1646
  assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1608
1647
  }
1609
1648
 
1610
- {
1611
- const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1649
+ { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1612
1650
  - cdict->matchState.window.base);
1613
1651
  const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
1614
1652
  if (cdictLen == 0) {
@@ -1625,9 +1663,9 @@ static size_t ZSTD_resetCCtx_byAttachingCDict(
1625
1663
  cctx->blockState.matchState.window.base + cdictEnd;
1626
1664
  ZSTD_window_clear(&cctx->blockState.matchState.window);
1627
1665
  }
1666
+ /* loadedDictEnd is expressed within the referential of the active context */
1628
1667
  cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
1629
- }
1630
- }
1668
+ } }
1631
1669
 
1632
1670
  cctx->dictID = cdict->dictID;
1633
1671
 
@@ -1652,36 +1690,41 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
1652
1690
  /* Copy only compression parameters related to tables. */
1653
1691
  params.cParams = *cdict_cParams;
1654
1692
  params.cParams.windowLog = windowLog;
1655
- ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1656
- ZSTDcrp_noMemset, zbuff);
1693
+ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1694
+ ZSTDcrp_leaveDirty, zbuff), "");
1657
1695
  assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1658
1696
  assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
1659
1697
  assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
1660
1698
  }
1661
1699
 
1700
+ ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
1701
+
1662
1702
  /* copy tables */
1663
1703
  { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
1664
1704
  size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
1665
- size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
1666
- assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1667
- assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
1668
- assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
1669
- assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
1670
- memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1705
+
1706
+ memcpy(cctx->blockState.matchState.hashTable,
1707
+ cdict->matchState.hashTable,
1708
+ hSize * sizeof(U32));
1709
+ memcpy(cctx->blockState.matchState.chainTable,
1710
+ cdict->matchState.chainTable,
1711
+ chainSize * sizeof(U32));
1671
1712
  }
1672
1713
 
1673
1714
  /* Zero the hashTable3, since the cdict never fills it */
1674
- { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
1715
+ { int const h3log = cctx->blockState.matchState.hashLog3;
1716
+ size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
1675
1717
  assert(cdict->matchState.hashLog3 == 0);
1676
1718
  memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1677
1719
  }
1678
1720
 
1721
+ ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
1722
+
1679
1723
  /* copy dictionary offsets */
1680
1724
  { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1681
1725
  ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1682
1726
  dstMatchState->window = srcMatchState->window;
1683
1727
  dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1684
- dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1685
1728
  dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1686
1729
  }
1687
1730
 
@@ -1698,7 +1741,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
1698
1741
  * in-place. We decide here which strategy to use. */
1699
1742
  static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1700
1743
  const ZSTD_CDict* cdict,
1701
- ZSTD_CCtx_params params,
1744
+ const ZSTD_CCtx_params* params,
1702
1745
  U64 pledgedSrcSize,
1703
1746
  ZSTD_buffered_policy_e zbuff)
1704
1747
  {
@@ -1708,10 +1751,10 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1708
1751
 
1709
1752
  if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
1710
1753
  return ZSTD_resetCCtx_byAttachingCDict(
1711
- cctx, cdict, params, pledgedSrcSize, zbuff);
1754
+ cctx, cdict, *params, pledgedSrcSize, zbuff);
1712
1755
  } else {
1713
1756
  return ZSTD_resetCCtx_byCopyingCDict(
1714
- cctx, cdict, params, pledgedSrcSize, zbuff);
1757
+ cctx, cdict, *params, pledgedSrcSize, zbuff);
1715
1758
  }
1716
1759
  }
1717
1760
 
@@ -1729,7 +1772,8 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1729
1772
  ZSTD_buffered_policy_e zbuff)
1730
1773
  {
1731
1774
  DEBUGLOG(5, "ZSTD_copyCCtx_internal");
1732
- RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong);
1775
+ RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
1776
+ "Can't copy a ctx that's not in init stage.");
1733
1777
 
1734
1778
  memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
1735
1779
  { ZSTD_CCtx_params params = dstCCtx->requestedParams;
@@ -1737,7 +1781,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1737
1781
  params.cParams = srcCCtx->appliedParams.cParams;
1738
1782
  params.fParams = fParams;
1739
1783
  ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
1740
- ZSTDcrp_noMemset, zbuff);
1784
+ ZSTDcrp_leaveDirty, zbuff);
1741
1785
  assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
1742
1786
  assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
1743
1787
  assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
@@ -1745,23 +1789,33 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1745
1789
  assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
1746
1790
  }
1747
1791
 
1792
+ ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);
1793
+
1748
1794
  /* copy tables */
1749
1795
  { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
1750
1796
  size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
1751
- size_t const h3Size = (size_t)1 << srcCCtx->blockState.matchState.hashLog3;
1752
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
1753
- assert((U32*)dstCCtx->blockState.matchState.chainTable == (U32*)dstCCtx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1754
- assert((U32*)dstCCtx->blockState.matchState.hashTable3 == (U32*)dstCCtx->blockState.matchState.chainTable + chainSize);
1755
- memcpy(dstCCtx->blockState.matchState.hashTable, srcCCtx->blockState.matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1797
+ int const h3log = srcCCtx->blockState.matchState.hashLog3;
1798
+ size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
1799
+
1800
+ memcpy(dstCCtx->blockState.matchState.hashTable,
1801
+ srcCCtx->blockState.matchState.hashTable,
1802
+ hSize * sizeof(U32));
1803
+ memcpy(dstCCtx->blockState.matchState.chainTable,
1804
+ srcCCtx->blockState.matchState.chainTable,
1805
+ chainSize * sizeof(U32));
1806
+ memcpy(dstCCtx->blockState.matchState.hashTable3,
1807
+ srcCCtx->blockState.matchState.hashTable3,
1808
+ h3Size * sizeof(U32));
1756
1809
  }
1757
1810
 
1811
+ ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);
1812
+
1758
1813
  /* copy dictionary offsets */
1759
1814
  {
1760
1815
  const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
1761
1816
  ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
1762
1817
  dstMatchState->window = srcMatchState->window;
1763
1818
  dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1764
- dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1765
1819
  dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1766
1820
  }
1767
1821
  dstCCtx->dictID = srcCCtx->dictID;
@@ -1806,6 +1860,20 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
1806
1860
  int rowNb;
1807
1861
  assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
1808
1862
  assert(size < (1U<<31)); /* can be casted to int */
1863
+
1864
+ #if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
1865
+ /* To validate that the table re-use logic is sound, and that we don't
1866
+ * access table space that we haven't cleaned, we re-"poison" the table
1867
+ * space every time we mark it dirty.
1868
+ *
1869
+ * This function however is intended to operate on those dirty tables and
1870
+ * re-clean them. So when this function is used correctly, we can unpoison
1871
+ * the memory it operated on. This introduces a blind spot though, since
1872
+ * if we now try to operate on __actually__ poisoned memory, we will not
1873
+ * detect that. */
1874
+ __msan_unpoison(table, size * sizeof(U32));
1875
+ #endif
1876
+
1809
1877
  for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
1810
1878
  int column;
1811
1879
  for (column=0; column<ZSTD_ROWSIZE; column++) {
@@ -1831,16 +1899,15 @@ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const
1831
1899
 
1832
1900
  /*! ZSTD_reduceIndex() :
1833
1901
  * rescale all indexes to avoid future overflow (indexes are U32) */
1834
- static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
1902
+ static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
1835
1903
  {
1836
- ZSTD_matchState_t* const ms = &zc->blockState.matchState;
1837
- { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
1904
+ { U32 const hSize = (U32)1 << params->cParams.hashLog;
1838
1905
  ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
1839
1906
  }
1840
1907
 
1841
- if (zc->appliedParams.cParams.strategy != ZSTD_fast) {
1842
- U32 const chainSize = (U32)1 << zc->appliedParams.cParams.chainLog;
1843
- if (zc->appliedParams.cParams.strategy == ZSTD_btlazy2)
1908
+ if (params->cParams.strategy != ZSTD_fast) {
1909
+ U32 const chainSize = (U32)1 << params->cParams.chainLog;
1910
+ if (params->cParams.strategy == ZSTD_btlazy2)
1844
1911
  ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
1845
1912
  else
1846
1913
  ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
@@ -1859,165 +1926,6 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
1859
1926
 
1860
1927
  /* See doc/zstd_compression_format.md for detailed format description */
1861
1928
 
1862
- static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
1863
- {
1864
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
1865
- RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
1866
- dstSize_tooSmall);
1867
- MEM_writeLE24(dst, cBlockHeader24);
1868
- memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
1869
- return ZSTD_blockHeaderSize + srcSize;
1870
- }
1871
-
1872
- static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1873
- {
1874
- BYTE* const ostart = (BYTE* const)dst;
1875
- U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
1876
-
1877
- RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall);
1878
-
1879
- switch(flSize)
1880
- {
1881
- case 1: /* 2 - 1 - 5 */
1882
- ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3));
1883
- break;
1884
- case 2: /* 2 - 2 - 12 */
1885
- MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));
1886
- break;
1887
- case 3: /* 2 - 2 - 20 */
1888
- MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));
1889
- break;
1890
- default: /* not necessary : flSize is {1,2,3} */
1891
- assert(0);
1892
- }
1893
-
1894
- memcpy(ostart + flSize, src, srcSize);
1895
- return srcSize + flSize;
1896
- }
1897
-
1898
- static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1899
- {
1900
- BYTE* const ostart = (BYTE* const)dst;
1901
- U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
1902
-
1903
- (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
1904
-
1905
- switch(flSize)
1906
- {
1907
- case 1: /* 2 - 1 - 5 */
1908
- ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3));
1909
- break;
1910
- case 2: /* 2 - 2 - 12 */
1911
- MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));
1912
- break;
1913
- case 3: /* 2 - 2 - 20 */
1914
- MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));
1915
- break;
1916
- default: /* not necessary : flSize is {1,2,3} */
1917
- assert(0);
1918
- }
1919
-
1920
- ostart[flSize] = *(const BYTE*)src;
1921
- return flSize+1;
1922
- }
1923
-
1924
-
1925
- /* ZSTD_minGain() :
1926
- * minimum compression required
1927
- * to generate a compress block or a compressed literals section.
1928
- * note : use same formula for both situations */
1929
- static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
1930
- {
1931
- U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
1932
- ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
1933
- assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
1934
- return (srcSize >> minlog) + 2;
1935
- }
1936
-
1937
- static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
1938
- ZSTD_hufCTables_t* nextHuf,
1939
- ZSTD_strategy strategy, int disableLiteralCompression,
1940
- void* dst, size_t dstCapacity,
1941
- const void* src, size_t srcSize,
1942
- void* workspace, size_t wkspSize,
1943
- const int bmi2)
1944
- {
1945
- size_t const minGain = ZSTD_minGain(srcSize, strategy);
1946
- size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
1947
- BYTE* const ostart = (BYTE*)dst;
1948
- U32 singleStream = srcSize < 256;
1949
- symbolEncodingType_e hType = set_compressed;
1950
- size_t cLitSize;
1951
-
1952
- DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
1953
- disableLiteralCompression);
1954
-
1955
- /* Prepare nextEntropy assuming reusing the existing table */
1956
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1957
-
1958
- if (disableLiteralCompression)
1959
- return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1960
-
1961
- /* small ? don't even attempt compression (speed opt) */
1962
- # define COMPRESS_LITERALS_SIZE_MIN 63
1963
- { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
1964
- if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1965
- }
1966
-
1967
- RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression");
1968
- { HUF_repeat repeat = prevHuf->repeatMode;
1969
- int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
1970
- if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
1971
- cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1972
- workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
1973
- : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1974
- workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
1975
- if (repeat != HUF_repeat_none) {
1976
- /* reused the existing table */
1977
- hType = set_repeat;
1978
- }
1979
- }
1980
-
1981
- if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
1982
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1983
- return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1984
- }
1985
- if (cLitSize==1) {
1986
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1987
- return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
1988
- }
1989
-
1990
- if (hType == set_compressed) {
1991
- /* using a newly constructed table */
1992
- nextHuf->repeatMode = HUF_repeat_check;
1993
- }
1994
-
1995
- /* Build header */
1996
- switch(lhSize)
1997
- {
1998
- case 3: /* 2 - 2 - 10 - 10 */
1999
- { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
2000
- MEM_writeLE24(ostart, lhc);
2001
- break;
2002
- }
2003
- case 4: /* 2 - 2 - 14 - 14 */
2004
- { U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);
2005
- MEM_writeLE32(ostart, lhc);
2006
- break;
2007
- }
2008
- case 5: /* 2 - 2 - 18 - 18 */
2009
- { U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
2010
- MEM_writeLE32(ostart, lhc);
2011
- ostart[4] = (BYTE)(cLitSize >> 10);
2012
- break;
2013
- }
2014
- default: /* not possible : lhSize is {3,4,5} */
2015
- assert(0);
2016
- }
2017
- return lhSize+cLitSize;
2018
- }
2019
-
2020
-
2021
1929
  void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
2022
1930
  {
2023
1931
  const seqDef* const sequences = seqStorePtr->sequencesStart;
@@ -2040,431 +1948,14 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
2040
1948
  mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
2041
1949
  }
2042
1950
 
2043
-
2044
- /**
2045
- * -log2(x / 256) lookup table for x in [0, 256).
2046
- * If x == 0: Return 0
2047
- * Else: Return floor(-log2(x / 256) * 256)
2048
- */
2049
- static unsigned const kInverseProbabilityLog256[256] = {
2050
- 0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
2051
- 1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
2052
- 874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
2053
- 724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
2054
- 618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
2055
- 535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
2056
- 468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
2057
- 411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
2058
- 362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
2059
- 318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
2060
- 279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
2061
- 244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
2062
- 212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
2063
- 182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
2064
- 155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
2065
- 130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
2066
- 106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
2067
- 83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
2068
- 62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
2069
- 42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
2070
- 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
2071
- 5, 4, 2, 1,
2072
- };
2073
-
2074
-
2075
- /**
2076
- * Returns the cost in bits of encoding the distribution described by count
2077
- * using the entropy bound.
2078
- */
2079
- static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
2080
- {
2081
- unsigned cost = 0;
2082
- unsigned s;
2083
- for (s = 0; s <= max; ++s) {
2084
- unsigned norm = (unsigned)((256 * count[s]) / total);
2085
- if (count[s] != 0 && norm == 0)
2086
- norm = 1;
2087
- assert(count[s] < total);
2088
- cost += count[s] * kInverseProbabilityLog256[norm];
2089
- }
2090
- return cost >> 8;
2091
- }
2092
-
2093
-
2094
- /**
2095
- * Returns the cost in bits of encoding the distribution in count using the
2096
- * table described by norm. The max symbol support by norm is assumed >= max.
2097
- * norm must be valid for every symbol with non-zero probability in count.
2098
- */
2099
- static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
2100
- unsigned const* count, unsigned const max)
2101
- {
2102
- unsigned const shift = 8 - accuracyLog;
2103
- size_t cost = 0;
2104
- unsigned s;
2105
- assert(accuracyLog <= 8);
2106
- for (s = 0; s <= max; ++s) {
2107
- unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
2108
- unsigned const norm256 = normAcc << shift;
2109
- assert(norm256 > 0);
2110
- assert(norm256 < 256);
2111
- cost += count[s] * kInverseProbabilityLog256[norm256];
2112
- }
2113
- return cost >> 8;
2114
- }
2115
-
2116
-
2117
- static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
2118
- void const* ptr = ctable;
2119
- U16 const* u16ptr = (U16 const*)ptr;
2120
- U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
2121
- return maxSymbolValue;
2122
- }
2123
-
2124
-
2125
- /**
2126
- * Returns the cost in bits of encoding the distribution in count using ctable.
2127
- * Returns an error if ctable cannot represent all the symbols in count.
2128
- */
2129
- static size_t ZSTD_fseBitCost(
2130
- FSE_CTable const* ctable,
2131
- unsigned const* count,
2132
- unsigned const max)
2133
- {
2134
- unsigned const kAccuracyLog = 8;
2135
- size_t cost = 0;
2136
- unsigned s;
2137
- FSE_CState_t cstate;
2138
- FSE_initCState(&cstate, ctable);
2139
- RETURN_ERROR_IF(ZSTD_getFSEMaxSymbolValue(ctable) < max, GENERIC,
2140
- "Repeat FSE_CTable has maxSymbolValue %u < %u",
2141
- ZSTD_getFSEMaxSymbolValue(ctable), max);
2142
- for (s = 0; s <= max; ++s) {
2143
- unsigned const tableLog = cstate.stateLog;
2144
- unsigned const badCost = (tableLog + 1) << kAccuracyLog;
2145
- unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
2146
- if (count[s] == 0)
2147
- continue;
2148
- RETURN_ERROR_IF(bitCost >= badCost, GENERIC,
2149
- "Repeat FSE_CTable has Prob[%u] == 0", s);
2150
- cost += count[s] * bitCost;
2151
- }
2152
- return cost >> kAccuracyLog;
2153
- }
2154
-
2155
- /**
2156
- * Returns the cost in bytes of encoding the normalized count header.
2157
- * Returns an error if any of the helper functions return an error.
2158
- */
2159
- static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
2160
- size_t const nbSeq, unsigned const FSELog)
2161
- {
2162
- BYTE wksp[FSE_NCOUNTBOUND];
2163
- S16 norm[MaxSeq + 1];
2164
- const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
2165
- FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
2166
- return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
2167
- }
2168
-
2169
-
2170
- typedef enum {
2171
- ZSTD_defaultDisallowed = 0,
2172
- ZSTD_defaultAllowed = 1
2173
- } ZSTD_defaultPolicy_e;
2174
-
2175
- MEM_STATIC symbolEncodingType_e
2176
- ZSTD_selectEncodingType(
2177
- FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
2178
- size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
2179
- FSE_CTable const* prevCTable,
2180
- short const* defaultNorm, U32 defaultNormLog,
2181
- ZSTD_defaultPolicy_e const isDefaultAllowed,
2182
- ZSTD_strategy const strategy)
2183
- {
2184
- ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
2185
- if (mostFrequent == nbSeq) {
2186
- *repeatMode = FSE_repeat_none;
2187
- if (isDefaultAllowed && nbSeq <= 2) {
2188
- /* Prefer set_basic over set_rle when there are 2 or less symbols,
2189
- * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
2190
- * If basic encoding isn't possible, always choose RLE.
2191
- */
2192
- DEBUGLOG(5, "Selected set_basic");
2193
- return set_basic;
2194
- }
2195
- DEBUGLOG(5, "Selected set_rle");
2196
- return set_rle;
2197
- }
2198
- if (strategy < ZSTD_lazy) {
2199
- if (isDefaultAllowed) {
2200
- size_t const staticFse_nbSeq_max = 1000;
2201
- size_t const mult = 10 - strategy;
2202
- size_t const baseLog = 3;
2203
- size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
2204
- assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
2205
- assert(mult <= 9 && mult >= 7);
2206
- if ( (*repeatMode == FSE_repeat_valid)
2207
- && (nbSeq < staticFse_nbSeq_max) ) {
2208
- DEBUGLOG(5, "Selected set_repeat");
2209
- return set_repeat;
2210
- }
2211
- if ( (nbSeq < dynamicFse_nbSeq_min)
2212
- || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
2213
- DEBUGLOG(5, "Selected set_basic");
2214
- /* The format allows default tables to be repeated, but it isn't useful.
2215
- * When using simple heuristics to select encoding type, we don't want
2216
- * to confuse these tables with dictionaries. When running more careful
2217
- * analysis, we don't need to waste time checking both repeating tables
2218
- * and default tables.
2219
- */
2220
- *repeatMode = FSE_repeat_none;
2221
- return set_basic;
2222
- }
2223
- }
2224
- } else {
2225
- size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
2226
- size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
2227
- size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
2228
- size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
2229
-
2230
- if (isDefaultAllowed) {
2231
- assert(!ZSTD_isError(basicCost));
2232
- assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
2233
- }
2234
- assert(!ZSTD_isError(NCountCost));
2235
- assert(compressedCost < ERROR(maxCode));
2236
- DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
2237
- (unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);
2238
- if (basicCost <= repeatCost && basicCost <= compressedCost) {
2239
- DEBUGLOG(5, "Selected set_basic");
2240
- assert(isDefaultAllowed);
2241
- *repeatMode = FSE_repeat_none;
2242
- return set_basic;
2243
- }
2244
- if (repeatCost <= compressedCost) {
2245
- DEBUGLOG(5, "Selected set_repeat");
2246
- assert(!ZSTD_isError(repeatCost));
2247
- return set_repeat;
2248
- }
2249
- assert(compressedCost < basicCost && compressedCost < repeatCost);
2250
- }
2251
- DEBUGLOG(5, "Selected set_compressed");
2252
- *repeatMode = FSE_repeat_check;
2253
- return set_compressed;
2254
- }
2255
-
2256
- MEM_STATIC size_t
2257
- ZSTD_buildCTable(void* dst, size_t dstCapacity,
2258
- FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
2259
- unsigned* count, U32 max,
2260
- const BYTE* codeTable, size_t nbSeq,
2261
- const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
2262
- const FSE_CTable* prevCTable, size_t prevCTableSize,
2263
- void* workspace, size_t workspaceSize)
2264
- {
2265
- BYTE* op = (BYTE*)dst;
2266
- const BYTE* const oend = op + dstCapacity;
2267
- DEBUGLOG(6, "ZSTD_buildCTable (dstCapacity=%u)", (unsigned)dstCapacity);
2268
-
2269
- switch (type) {
2270
- case set_rle:
2271
- FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max));
2272
- RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall);
2273
- *op = codeTable[0];
2274
- return 1;
2275
- case set_repeat:
2276
- memcpy(nextCTable, prevCTable, prevCTableSize);
2277
- return 0;
2278
- case set_basic:
2279
- FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
2280
- return 0;
2281
- case set_compressed: {
2282
- S16 norm[MaxSeq + 1];
2283
- size_t nbSeq_1 = nbSeq;
2284
- const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
2285
- if (count[codeTable[nbSeq-1]] > 1) {
2286
- count[codeTable[nbSeq-1]]--;
2287
- nbSeq_1--;
2288
- }
2289
- assert(nbSeq_1 > 1);
2290
- FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
2291
- { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
2292
- FORWARD_IF_ERROR(NCountSize);
2293
- FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
2294
- return NCountSize;
2295
- }
2296
- }
2297
- default: assert(0); RETURN_ERROR(GENERIC);
2298
- }
2299
- }
2300
-
2301
- FORCE_INLINE_TEMPLATE size_t
2302
- ZSTD_encodeSequences_body(
2303
- void* dst, size_t dstCapacity,
2304
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2305
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2306
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2307
- seqDef const* sequences, size_t nbSeq, int longOffsets)
2308
- {
2309
- BIT_CStream_t blockStream;
2310
- FSE_CState_t stateMatchLength;
2311
- FSE_CState_t stateOffsetBits;
2312
- FSE_CState_t stateLitLength;
2313
-
2314
- RETURN_ERROR_IF(
2315
- ERR_isError(BIT_initCStream(&blockStream, dst, dstCapacity)),
2316
- dstSize_tooSmall, "not enough space remaining");
2317
- DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
2318
- (int)(blockStream.endPtr - blockStream.startPtr),
2319
- (unsigned)dstCapacity);
2320
-
2321
- /* first symbols */
2322
- FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
2323
- FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
2324
- FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
2325
- BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
2326
- if (MEM_32bits()) BIT_flushBits(&blockStream);
2327
- BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
2328
- if (MEM_32bits()) BIT_flushBits(&blockStream);
2329
- if (longOffsets) {
2330
- U32 const ofBits = ofCodeTable[nbSeq-1];
2331
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
2332
- if (extraBits) {
2333
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
2334
- BIT_flushBits(&blockStream);
2335
- }
2336
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
2337
- ofBits - extraBits);
2338
- } else {
2339
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
2340
- }
2341
- BIT_flushBits(&blockStream);
2342
-
2343
- { size_t n;
2344
- for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
2345
- BYTE const llCode = llCodeTable[n];
2346
- BYTE const ofCode = ofCodeTable[n];
2347
- BYTE const mlCode = mlCodeTable[n];
2348
- U32 const llBits = LL_bits[llCode];
2349
- U32 const ofBits = ofCode;
2350
- U32 const mlBits = ML_bits[mlCode];
2351
- DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
2352
- (unsigned)sequences[n].litLength,
2353
- (unsigned)sequences[n].matchLength + MINMATCH,
2354
- (unsigned)sequences[n].offset);
2355
- /* 32b*/ /* 64b*/
2356
- /* (7)*/ /* (7)*/
2357
- FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
2358
- FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
2359
- if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
2360
- FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
2361
- if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
2362
- BIT_flushBits(&blockStream); /* (7)*/
2363
- BIT_addBits(&blockStream, sequences[n].litLength, llBits);
2364
- if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
2365
- BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
2366
- if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
2367
- if (longOffsets) {
2368
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
2369
- if (extraBits) {
2370
- BIT_addBits(&blockStream, sequences[n].offset, extraBits);
2371
- BIT_flushBits(&blockStream); /* (7)*/
2372
- }
2373
- BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
2374
- ofBits - extraBits); /* 31 */
2375
- } else {
2376
- BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
2377
- }
2378
- BIT_flushBits(&blockStream); /* (7)*/
2379
- DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
2380
- } }
2381
-
2382
- DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
2383
- FSE_flushCState(&blockStream, &stateMatchLength);
2384
- DEBUGLOG(6, "ZSTD_encodeSequences: flushing Off state with %u bits", stateOffsetBits.stateLog);
2385
- FSE_flushCState(&blockStream, &stateOffsetBits);
2386
- DEBUGLOG(6, "ZSTD_encodeSequences: flushing LL state with %u bits", stateLitLength.stateLog);
2387
- FSE_flushCState(&blockStream, &stateLitLength);
2388
-
2389
- { size_t const streamSize = BIT_closeCStream(&blockStream);
2390
- RETURN_ERROR_IF(streamSize==0, dstSize_tooSmall, "not enough space");
2391
- return streamSize;
2392
- }
2393
- }
2394
-
2395
- static size_t
2396
- ZSTD_encodeSequences_default(
2397
- void* dst, size_t dstCapacity,
2398
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2399
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2400
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2401
- seqDef const* sequences, size_t nbSeq, int longOffsets)
2402
- {
2403
- return ZSTD_encodeSequences_body(dst, dstCapacity,
2404
- CTable_MatchLength, mlCodeTable,
2405
- CTable_OffsetBits, ofCodeTable,
2406
- CTable_LitLength, llCodeTable,
2407
- sequences, nbSeq, longOffsets);
2408
- }
2409
-
2410
-
2411
- #if DYNAMIC_BMI2
2412
-
2413
- static TARGET_ATTRIBUTE("bmi2") size_t
2414
- ZSTD_encodeSequences_bmi2(
2415
- void* dst, size_t dstCapacity,
2416
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2417
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2418
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2419
- seqDef const* sequences, size_t nbSeq, int longOffsets)
1951
+ /* ZSTD_useTargetCBlockSize():
1952
+ * Returns if target compressed block size param is being used.
1953
+ * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize.
1954
+ * Returns 1 if true, 0 otherwise. */
1955
+ static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
2420
1956
  {
2421
- return ZSTD_encodeSequences_body(dst, dstCapacity,
2422
- CTable_MatchLength, mlCodeTable,
2423
- CTable_OffsetBits, ofCodeTable,
2424
- CTable_LitLength, llCodeTable,
2425
- sequences, nbSeq, longOffsets);
2426
- }
2427
-
2428
- #endif
2429
-
2430
- static size_t ZSTD_encodeSequences(
2431
- void* dst, size_t dstCapacity,
2432
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2433
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2434
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2435
- seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
2436
- {
2437
- DEBUGLOG(5, "ZSTD_encodeSequences: dstCapacity = %u", (unsigned)dstCapacity);
2438
- #if DYNAMIC_BMI2
2439
- if (bmi2) {
2440
- return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
2441
- CTable_MatchLength, mlCodeTable,
2442
- CTable_OffsetBits, ofCodeTable,
2443
- CTable_LitLength, llCodeTable,
2444
- sequences, nbSeq, longOffsets);
2445
- }
2446
- #endif
2447
- (void)bmi2;
2448
- return ZSTD_encodeSequences_default(dst, dstCapacity,
2449
- CTable_MatchLength, mlCodeTable,
2450
- CTable_OffsetBits, ofCodeTable,
2451
- CTable_LitLength, llCodeTable,
2452
- sequences, nbSeq, longOffsets);
2453
- }
2454
-
2455
- static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
2456
- {
2457
- switch (cctxParams->literalCompressionMode) {
2458
- case ZSTD_lcm_huffman:
2459
- return 0;
2460
- case ZSTD_lcm_uncompressed:
2461
- return 1;
2462
- default:
2463
- assert(0 /* impossible: pre-validated */);
2464
- /* fall-through */
2465
- case ZSTD_lcm_auto:
2466
- return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
2467
- }
1957
+ DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize);
1958
+ return (cctxParams->targetCBlockSize != 0);
2468
1959
  }
2469
1960
 
2470
1961
  /* ZSTD_compressSequences_internal():
@@ -2475,7 +1966,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2475
1966
  ZSTD_entropyCTables_t* nextEntropy,
2476
1967
  const ZSTD_CCtx_params* cctxParams,
2477
1968
  void* dst, size_t dstCapacity,
2478
- void* workspace, size_t wkspSize,
1969
+ void* entropyWorkspace, size_t entropyWkspSize,
2479
1970
  const int bmi2)
2480
1971
  {
2481
1972
  const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
@@ -2492,52 +1983,59 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2492
1983
  BYTE* const ostart = (BYTE*)dst;
2493
1984
  BYTE* const oend = ostart + dstCapacity;
2494
1985
  BYTE* op = ostart;
2495
- size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
1986
+ size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
2496
1987
  BYTE* seqHead;
2497
1988
  BYTE* lastNCount = NULL;
2498
1989
 
1990
+ DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq);
2499
1991
  ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
2500
- DEBUGLOG(5, "ZSTD_compressSequences_internal");
2501
1992
 
2502
1993
  /* Compress literals */
2503
1994
  { const BYTE* const literals = seqStorePtr->litStart;
2504
- size_t const litSize = seqStorePtr->lit - literals;
1995
+ size_t const litSize = (size_t)(seqStorePtr->lit - literals);
2505
1996
  size_t const cSize = ZSTD_compressLiterals(
2506
1997
  &prevEntropy->huf, &nextEntropy->huf,
2507
1998
  cctxParams->cParams.strategy,
2508
1999
  ZSTD_disableLiteralsCompression(cctxParams),
2509
2000
  op, dstCapacity,
2510
2001
  literals, litSize,
2511
- workspace, wkspSize,
2002
+ entropyWorkspace, entropyWkspSize,
2512
2003
  bmi2);
2513
- FORWARD_IF_ERROR(cSize);
2004
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
2514
2005
  assert(cSize <= dstCapacity);
2515
2006
  op += cSize;
2516
2007
  }
2517
2008
 
2518
2009
  /* Sequences Header */
2519
2010
  RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
2520
- dstSize_tooSmall);
2521
- if (nbSeq < 0x7F)
2011
+ dstSize_tooSmall, "Can't fit seq hdr in output buf!");
2012
+ if (nbSeq < 128) {
2522
2013
  *op++ = (BYTE)nbSeq;
2523
- else if (nbSeq < LONGNBSEQ)
2524
- op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
2525
- else
2526
- op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
2014
+ } else if (nbSeq < LONGNBSEQ) {
2015
+ op[0] = (BYTE)((nbSeq>>8) + 0x80);
2016
+ op[1] = (BYTE)nbSeq;
2017
+ op+=2;
2018
+ } else {
2019
+ op[0]=0xFF;
2020
+ MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ));
2021
+ op+=3;
2022
+ }
2023
+ assert(op <= oend);
2527
2024
  if (nbSeq==0) {
2528
2025
  /* Copy the old tables over as if we repeated them */
2529
2026
  memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
2530
- return op - ostart;
2027
+ return (size_t)(op - ostart);
2531
2028
  }
2532
2029
 
2533
2030
  /* seqHead : flags for FSE encoding type */
2534
2031
  seqHead = op++;
2032
+ assert(op <= oend);
2535
2033
 
2536
2034
  /* convert length/distances into codes */
2537
2035
  ZSTD_seqToCodes(seqStorePtr);
2538
2036
  /* build CTable for Literal Lengths */
2539
2037
  { unsigned max = MaxLL;
2540
- size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
2038
+ size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
2541
2039
  DEBUGLOG(5, "Building LL table");
2542
2040
  nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
2543
2041
  LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
@@ -2547,18 +2045,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2547
2045
  ZSTD_defaultAllowed, strategy);
2548
2046
  assert(set_basic < set_compressed && set_rle < set_compressed);
2549
2047
  assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2550
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
2551
- count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
2552
- prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
2553
- workspace, wkspSize);
2554
- FORWARD_IF_ERROR(countSize);
2048
+ { size_t const countSize = ZSTD_buildCTable(
2049
+ op, (size_t)(oend - op),
2050
+ CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
2051
+ count, max, llCodeTable, nbSeq,
2052
+ LL_defaultNorm, LL_defaultNormLog, MaxLL,
2053
+ prevEntropy->fse.litlengthCTable,
2054
+ sizeof(prevEntropy->fse.litlengthCTable),
2055
+ entropyWorkspace, entropyWkspSize);
2056
+ FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
2555
2057
  if (LLtype == set_compressed)
2556
2058
  lastNCount = op;
2557
2059
  op += countSize;
2060
+ assert(op <= oend);
2558
2061
  } }
2559
2062
  /* build CTable for Offsets */
2560
2063
  { unsigned max = MaxOff;
2561
- size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
2064
+ size_t const mostFrequent = HIST_countFast_wksp(
2065
+ count, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
2562
2066
  /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
2563
2067
  ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
2564
2068
  DEBUGLOG(5, "Building OF table");
@@ -2569,18 +2073,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2569
2073
  OF_defaultNorm, OF_defaultNormLog,
2570
2074
  defaultPolicy, strategy);
2571
2075
  assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2572
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
2573
- count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
2574
- prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
2575
- workspace, wkspSize);
2576
- FORWARD_IF_ERROR(countSize);
2076
+ { size_t const countSize = ZSTD_buildCTable(
2077
+ op, (size_t)(oend - op),
2078
+ CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
2079
+ count, max, ofCodeTable, nbSeq,
2080
+ OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
2081
+ prevEntropy->fse.offcodeCTable,
2082
+ sizeof(prevEntropy->fse.offcodeCTable),
2083
+ entropyWorkspace, entropyWkspSize);
2084
+ FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
2577
2085
  if (Offtype == set_compressed)
2578
2086
  lastNCount = op;
2579
2087
  op += countSize;
2088
+ assert(op <= oend);
2580
2089
  } }
2581
2090
  /* build CTable for MatchLengths */
2582
2091
  { unsigned max = MaxML;
2583
- size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
2092
+ size_t const mostFrequent = HIST_countFast_wksp(
2093
+ count, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
2584
2094
  DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
2585
2095
  nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
2586
2096
  MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
@@ -2589,27 +2099,33 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2589
2099
  ML_defaultNorm, ML_defaultNormLog,
2590
2100
  ZSTD_defaultAllowed, strategy);
2591
2101
  assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2592
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
2593
- count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
2594
- prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
2595
- workspace, wkspSize);
2596
- FORWARD_IF_ERROR(countSize);
2102
+ { size_t const countSize = ZSTD_buildCTable(
2103
+ op, (size_t)(oend - op),
2104
+ CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
2105
+ count, max, mlCodeTable, nbSeq,
2106
+ ML_defaultNorm, ML_defaultNormLog, MaxML,
2107
+ prevEntropy->fse.matchlengthCTable,
2108
+ sizeof(prevEntropy->fse.matchlengthCTable),
2109
+ entropyWorkspace, entropyWkspSize);
2110
+ FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
2597
2111
  if (MLtype == set_compressed)
2598
2112
  lastNCount = op;
2599
2113
  op += countSize;
2114
+ assert(op <= oend);
2600
2115
  } }
2601
2116
 
2602
2117
  *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
2603
2118
 
2604
2119
  { size_t const bitstreamSize = ZSTD_encodeSequences(
2605
- op, oend - op,
2120
+ op, (size_t)(oend - op),
2606
2121
  CTable_MatchLength, mlCodeTable,
2607
2122
  CTable_OffsetBits, ofCodeTable,
2608
2123
  CTable_LitLength, llCodeTable,
2609
2124
  sequences, nbSeq,
2610
2125
  longOffsets, bmi2);
2611
- FORWARD_IF_ERROR(bitstreamSize);
2126
+ FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
2612
2127
  op += bitstreamSize;
2128
+ assert(op <= oend);
2613
2129
  /* zstd versions <= 1.3.4 mistakenly report corruption when
2614
2130
  * FSE_readNCount() receives a buffer < 4 bytes.
2615
2131
  * Fixed by https://github.com/facebook/zstd/pull/1146.
@@ -2628,7 +2144,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2628
2144
  }
2629
2145
 
2630
2146
  DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
2631
- return op - ostart;
2147
+ return (size_t)(op - ostart);
2632
2148
  }
2633
2149
 
2634
2150
  MEM_STATIC size_t
@@ -2638,20 +2154,20 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
2638
2154
  const ZSTD_CCtx_params* cctxParams,
2639
2155
  void* dst, size_t dstCapacity,
2640
2156
  size_t srcSize,
2641
- void* workspace, size_t wkspSize,
2157
+ void* entropyWorkspace, size_t entropyWkspSize,
2642
2158
  int bmi2)
2643
2159
  {
2644
2160
  size_t const cSize = ZSTD_compressSequences_internal(
2645
2161
  seqStorePtr, prevEntropy, nextEntropy, cctxParams,
2646
2162
  dst, dstCapacity,
2647
- workspace, wkspSize, bmi2);
2163
+ entropyWorkspace, entropyWkspSize, bmi2);
2648
2164
  if (cSize == 0) return 0;
2649
2165
  /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
2650
2166
  * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
2651
2167
  */
2652
2168
  if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
2653
2169
  return 0; /* block not compressed */
2654
- FORWARD_IF_ERROR(cSize);
2170
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed");
2655
2171
 
2656
2172
  /* Check compressibility */
2657
2173
  { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
@@ -2721,30 +2237,24 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
2721
2237
  ssPtr->longLengthID = 0;
2722
2238
  }
2723
2239
 
2724
- static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2725
- void* dst, size_t dstCapacity,
2726
- const void* src, size_t srcSize)
2240
+ typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
2241
+
2242
+ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
2727
2243
  {
2728
2244
  ZSTD_matchState_t* const ms = &zc->blockState.matchState;
2729
- size_t cSize;
2730
- DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
2731
- (unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate);
2245
+ DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
2732
2246
  assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
2733
-
2734
2247
  /* Assert that we have correctly flushed the ctx params into the ms's copy */
2735
2248
  ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
2736
-
2737
2249
  if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
2738
2250
  ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
2739
- cSize = 0;
2740
- goto out; /* don't even attempt compression below a certain srcSize */
2251
+ return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
2741
2252
  }
2742
2253
  ZSTD_resetSeqStore(&(zc->seqStore));
2743
2254
  /* required for optimal parser to read stats from dictionary */
2744
2255
  ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
2745
2256
  /* tell the optimal parser how we expect to compress literals */
2746
2257
  ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
2747
-
2748
2258
  /* a gap between an attached dict and the current window is not safe,
2749
2259
  * they must remain adjacent,
2750
2260
  * and when that stops being the case, the dict must be unset */
@@ -2783,7 +2293,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2783
2293
  /* Updates ldmSeqStore.size */
2784
2294
  FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
2785
2295
  &zc->appliedParams.ldmParams,
2786
- src, srcSize));
2296
+ src, srcSize), "");
2787
2297
  /* Updates ldmSeqStore.pos */
2788
2298
  lastLLSize =
2789
2299
  ZSTD_ldm_blockCompress(&ldmSeqStore,
@@ -2798,6 +2308,134 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2798
2308
  { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
2799
2309
  ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
2800
2310
  } }
2311
+ return ZSTDbss_compress;
2312
+ }
2313
+
2314
+ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
2315
+ {
2316
+ const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
2317
+ const seqDef* seqs = seqStore->sequencesStart;
2318
+ size_t seqsSize = seqStore->sequences - seqs;
2319
+
2320
+ ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
2321
+ size_t i; size_t position; int repIdx;
2322
+
2323
+ assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
2324
+ for (i = 0, position = 0; i < seqsSize; ++i) {
2325
+ outSeqs[i].offset = seqs[i].offset;
2326
+ outSeqs[i].litLength = seqs[i].litLength;
2327
+ outSeqs[i].matchLength = seqs[i].matchLength + MINMATCH;
2328
+
2329
+ if (i == seqStore->longLengthPos) {
2330
+ if (seqStore->longLengthID == 1) {
2331
+ outSeqs[i].litLength += 0x10000;
2332
+ } else if (seqStore->longLengthID == 2) {
2333
+ outSeqs[i].matchLength += 0x10000;
2334
+ }
2335
+ }
2336
+
2337
+ if (outSeqs[i].offset <= ZSTD_REP_NUM) {
2338
+ outSeqs[i].rep = outSeqs[i].offset;
2339
+ repIdx = (unsigned int)i - outSeqs[i].offset;
2340
+
2341
+ if (outSeqs[i].litLength == 0) {
2342
+ if (outSeqs[i].offset < 3) {
2343
+ --repIdx;
2344
+ } else {
2345
+ repIdx = (unsigned int)i - 1;
2346
+ }
2347
+ ++outSeqs[i].rep;
2348
+ }
2349
+ assert(repIdx >= -3);
2350
+ outSeqs[i].offset = repIdx >= 0 ? outSeqs[repIdx].offset : repStartValue[-repIdx - 1];
2351
+ if (outSeqs[i].rep == 4) {
2352
+ --outSeqs[i].offset;
2353
+ }
2354
+ } else {
2355
+ outSeqs[i].offset -= ZSTD_REP_NUM;
2356
+ }
2357
+
2358
+ position += outSeqs[i].litLength;
2359
+ outSeqs[i].matchPos = (unsigned int)position;
2360
+ position += outSeqs[i].matchLength;
2361
+ }
2362
+ zc->seqCollector.seqIndex += seqsSize;
2363
+ }
2364
+
2365
+ size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
2366
+ size_t outSeqsSize, const void* src, size_t srcSize)
2367
+ {
2368
+ const size_t dstCapacity = ZSTD_compressBound(srcSize);
2369
+ void* dst = ZSTD_malloc(dstCapacity, ZSTD_defaultCMem);
2370
+ SeqCollector seqCollector;
2371
+
2372
+ RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
2373
+
2374
+ seqCollector.collectSequences = 1;
2375
+ seqCollector.seqStart = outSeqs;
2376
+ seqCollector.seqIndex = 0;
2377
+ seqCollector.maxSequences = outSeqsSize;
2378
+ zc->seqCollector = seqCollector;
2379
+
2380
+ ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
2381
+ ZSTD_free(dst, ZSTD_defaultCMem);
2382
+ return zc->seqCollector.seqIndex;
2383
+ }
2384
+
2385
+ /* Returns true if the given block is a RLE block */
2386
+ static int ZSTD_isRLE(const BYTE *ip, size_t length) {
2387
+ size_t i;
2388
+ if (length < 2) return 1;
2389
+ for (i = 1; i < length; ++i) {
2390
+ if (ip[0] != ip[i]) return 0;
2391
+ }
2392
+ return 1;
2393
+ }
2394
+
2395
+ /* Returns true if the given block may be RLE.
2396
+ * This is just a heuristic based on the compressibility.
2397
+ * It may return both false positives and false negatives.
2398
+ */
2399
+ static int ZSTD_maybeRLE(seqStore_t const* seqStore)
2400
+ {
2401
+ size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);
2402
+ size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart);
2403
+
2404
+ return nbSeqs < 4 && nbLits < 10;
2405
+ }
2406
+
2407
+ static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc)
2408
+ {
2409
+ ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
2410
+ zc->blockState.prevCBlock = zc->blockState.nextCBlock;
2411
+ zc->blockState.nextCBlock = tmp;
2412
+ }
2413
+
2414
+ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2415
+ void* dst, size_t dstCapacity,
2416
+ const void* src, size_t srcSize, U32 frame)
2417
+ {
2418
+ /* This the upper bound for the length of an rle block.
2419
+ * This isn't the actual upper bound. Finding the real threshold
2420
+ * needs further investigation.
2421
+ */
2422
+ const U32 rleMaxLength = 25;
2423
+ size_t cSize;
2424
+ const BYTE* ip = (const BYTE*)src;
2425
+ BYTE* op = (BYTE*)dst;
2426
+ DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
2427
+ (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
2428
+ (unsigned)zc->blockState.matchState.nextToUpdate);
2429
+
2430
+ { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
2431
+ FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
2432
+ if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
2433
+ }
2434
+
2435
+ if (zc->seqCollector.collectSequences) {
2436
+ ZSTD_copyBlockSequences(zc);
2437
+ return 0;
2438
+ }
2801
2439
 
2802
2440
  /* encode sequences and literals */
2803
2441
  cSize = ZSTD_compressSequences(&zc->seqStore,
@@ -2808,12 +2446,22 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2808
2446
  zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
2809
2447
  zc->bmi2);
2810
2448
 
2449
+ if (frame &&
2450
+ /* We don't want to emit our first block as a RLE even if it qualifies because
2451
+ * doing so will cause the decoder (cli only) to throw a "should consume all input error."
2452
+ * This is only an issue for zstd <= v1.4.3
2453
+ */
2454
+ !zc->isFirstBlock &&
2455
+ cSize < rleMaxLength &&
2456
+ ZSTD_isRLE(ip, srcSize))
2457
+ {
2458
+ cSize = 1;
2459
+ op[0] = ip[0];
2460
+ }
2461
+
2811
2462
  out:
2812
- if (!ZSTD_isError(cSize) && cSize != 0) {
2813
- /* confirm repcodes and entropy tables when emitting a compressed block */
2814
- ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
2815
- zc->blockState.prevCBlock = zc->blockState.nextCBlock;
2816
- zc->blockState.nextCBlock = tmp;
2463
+ if (!ZSTD_isError(cSize) && cSize > 1) {
2464
+ ZSTD_confirmRepcodesAndEntropyTables(zc);
2817
2465
  }
2818
2466
  /* We check that dictionaries have offset codes available for the first
2819
2467
  * block. After the first block, the offcode table might not have large
@@ -2825,6 +2473,104 @@ out:
2825
2473
  return cSize;
2826
2474
  }
2827
2475
 
2476
+ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,
2477
+ void* dst, size_t dstCapacity,
2478
+ const void* src, size_t srcSize,
2479
+ const size_t bss, U32 lastBlock)
2480
+ {
2481
+ DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()");
2482
+ if (bss == ZSTDbss_compress) {
2483
+ if (/* We don't want to emit our first block as a RLE even if it qualifies because
2484
+ * doing so will cause the decoder (cli only) to throw a "should consume all input error."
2485
+ * This is only an issue for zstd <= v1.4.3
2486
+ */
2487
+ !zc->isFirstBlock &&
2488
+ ZSTD_maybeRLE(&zc->seqStore) &&
2489
+ ZSTD_isRLE((BYTE const*)src, srcSize))
2490
+ {
2491
+ return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock);
2492
+ }
2493
+ /* Attempt superblock compression.
2494
+ *
2495
+ * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the
2496
+ * standard ZSTD_compressBound(). This is a problem, because even if we have
2497
+ * space now, taking an extra byte now could cause us to run out of space later
2498
+ * and violate ZSTD_compressBound().
2499
+ *
2500
+ * Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize.
2501
+ *
2502
+ * In order to respect ZSTD_compressBound() we must attempt to emit a raw
2503
+ * uncompressed block in these cases:
2504
+ * * cSize == 0: Return code for an uncompressed block.
2505
+ * * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize).
2506
+ * ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of
2507
+ * output space.
2508
+ * * cSize >= blockBound(srcSize): We have expanded the block too much so
2509
+ * emit an uncompressed block.
2510
+ */
2511
+ {
2512
+ size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);
2513
+ if (cSize != ERROR(dstSize_tooSmall)) {
2514
+ size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);
2515
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed");
2516
+ if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {
2517
+ ZSTD_confirmRepcodesAndEntropyTables(zc);
2518
+ return cSize;
2519
+ }
2520
+ }
2521
+ }
2522
+ }
2523
+
2524
+ DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()");
2525
+ /* Superblock compression failed, attempt to emit a single no compress block.
2526
+ * The decoder will be able to stream this block since it is uncompressed.
2527
+ */
2528
+ return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);
2529
+ }
2530
+
2531
+ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,
2532
+ void* dst, size_t dstCapacity,
2533
+ const void* src, size_t srcSize,
2534
+ U32 lastBlock)
2535
+ {
2536
+ size_t cSize = 0;
2537
+ const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
2538
+ DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)",
2539
+ (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize);
2540
+ FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
2541
+
2542
+ cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock);
2543
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize_body failed");
2544
+
2545
+ if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
2546
+ zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
2547
+
2548
+ return cSize;
2549
+ }
2550
+
2551
+ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
2552
+ ZSTD_cwksp* ws,
2553
+ ZSTD_CCtx_params const* params,
2554
+ void const* ip,
2555
+ void const* iend)
2556
+ {
2557
+ if (ZSTD_window_needOverflowCorrection(ms->window, iend)) {
2558
+ U32 const maxDist = (U32)1 << params->cParams.windowLog;
2559
+ U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
2560
+ U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
2561
+ ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2562
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2563
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2564
+ ZSTD_cwksp_mark_tables_dirty(ws);
2565
+ ZSTD_reduceIndex(ms, params, correction);
2566
+ ZSTD_cwksp_mark_tables_clean(ws);
2567
+ if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2568
+ else ms->nextToUpdate -= correction;
2569
+ /* invalidate dictionaries on overflow correction */
2570
+ ms->loadedDictEnd = 0;
2571
+ ms->dictMatchState = NULL;
2572
+ }
2573
+ }
2828
2574
 
2829
2575
  /*! ZSTD_compress_frameChunk() :
2830
2576
  * Compress a chunk of data into one or multiple blocks.
@@ -2844,7 +2590,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2844
2590
  BYTE* const ostart = (BYTE*)dst;
2845
2591
  BYTE* op = ostart;
2846
2592
  U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
2847
- assert(cctx->appliedParams.cParams.windowLog <= 31);
2593
+
2594
+ assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
2848
2595
 
2849
2596
  DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
2850
2597
  if (cctx->appliedParams.fParams.checksumFlag && srcSize)
@@ -2859,70 +2606,75 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2859
2606
  "not enough space to store compressed block");
2860
2607
  if (remaining < blockSize) blockSize = remaining;
2861
2608
 
2862
- if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) {
2863
- U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2864
- U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
2865
- ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2866
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2867
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2868
- ZSTD_reduceIndex(cctx, correction);
2869
- if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2870
- else ms->nextToUpdate -= correction;
2871
- ms->loadedDictEnd = 0;
2872
- ms->dictMatchState = NULL;
2873
- }
2874
- ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2875
- if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
2609
+ ZSTD_overflowCorrectIfNeeded(
2610
+ ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize);
2611
+ ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2876
2612
 
2877
- { size_t cSize = ZSTD_compressBlock_internal(cctx,
2878
- op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
2879
- ip, blockSize);
2880
- FORWARD_IF_ERROR(cSize);
2613
+ /* Ensure hash/chain table insertion resumes no sooner than lowlimit */
2614
+ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
2881
2615
 
2882
- if (cSize == 0) { /* block is not compressible */
2883
- cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
2884
- FORWARD_IF_ERROR(cSize);
2616
+ { size_t cSize;
2617
+ if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) {
2618
+ cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock);
2619
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed");
2620
+ assert(cSize > 0);
2621
+ assert(cSize <= blockSize + ZSTD_blockHeaderSize);
2885
2622
  } else {
2886
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
2887
- MEM_writeLE24(op, cBlockHeader24);
2888
- cSize += ZSTD_blockHeaderSize;
2623
+ cSize = ZSTD_compressBlock_internal(cctx,
2624
+ op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
2625
+ ip, blockSize, 1 /* frame */);
2626
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_internal failed");
2627
+
2628
+ if (cSize == 0) { /* block is not compressible */
2629
+ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
2630
+ FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
2631
+ } else {
2632
+ U32 const cBlockHeader = cSize == 1 ?
2633
+ lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
2634
+ lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
2635
+ MEM_writeLE24(op, cBlockHeader);
2636
+ cSize += ZSTD_blockHeaderSize;
2637
+ }
2889
2638
  }
2890
2639
 
2640
+
2891
2641
  ip += blockSize;
2892
2642
  assert(remaining >= blockSize);
2893
2643
  remaining -= blockSize;
2894
2644
  op += cSize;
2895
2645
  assert(dstCapacity >= cSize);
2896
2646
  dstCapacity -= cSize;
2647
+ cctx->isFirstBlock = 0;
2897
2648
  DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
2898
2649
  (unsigned)cSize);
2899
2650
  } }
2900
2651
 
2901
2652
  if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
2902
- return op-ostart;
2653
+ return (size_t)(op-ostart);
2903
2654
  }
2904
2655
 
2905
2656
 
2906
2657
  static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2907
- ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
2658
+ const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID)
2908
2659
  { BYTE* const op = (BYTE*)dst;
2909
2660
  U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
2910
- U32 const dictIDSizeCode = params.fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
2911
- U32 const checksumFlag = params.fParams.checksumFlag>0;
2912
- U32 const windowSize = (U32)1 << params.cParams.windowLog;
2913
- U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
2914
- BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2915
- U32 const fcsCode = params.fParams.contentSizeFlag ?
2661
+ U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
2662
+ U32 const checksumFlag = params->fParams.checksumFlag>0;
2663
+ U32 const windowSize = (U32)1 << params->cParams.windowLog;
2664
+ U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
2665
+ BYTE const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2666
+ U32 const fcsCode = params->fParams.contentSizeFlag ?
2916
2667
  (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
2917
2668
  BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2918
2669
  size_t pos=0;
2919
2670
 
2920
- assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
2921
- RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall);
2671
+ assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
2672
+ RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall,
2673
+ "dst buf is too small to fit worst-case frame header size.");
2922
2674
  DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2923
- !params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
2675
+ !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
2924
2676
 
2925
- if (params.format == ZSTD_f_zstd1) {
2677
+ if (params->format == ZSTD_f_zstd1) {
2926
2678
  MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2927
2679
  pos = 4;
2928
2680
  }
@@ -2954,7 +2706,8 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2954
2706
  */
2955
2707
  size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
2956
2708
  {
2957
- RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall);
2709
+ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,
2710
+ "dst buf is too small to write frame trailer empty block.");
2958
2711
  { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
2959
2712
  MEM_writeLE24(dst, cBlockHeader24);
2960
2713
  return ZSTD_blockHeaderSize;
@@ -2963,9 +2716,11 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
2963
2716
 
2964
2717
  size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
2965
2718
  {
2966
- RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong);
2719
+ RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
2720
+ "wrong cctx stage");
2967
2721
  RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
2968
- parameter_unsupported);
2722
+ parameter_unsupported,
2723
+ "incompatible with ldm");
2969
2724
  cctx->externSeqStore.seq = seq;
2970
2725
  cctx->externSeqStore.size = nbSeq;
2971
2726
  cctx->externSeqStore.capacity = nbSeq;
@@ -2988,9 +2743,10 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2988
2743
  "missing init (ZSTD_compressBegin)");
2989
2744
 
2990
2745
  if (frame && (cctx->stage==ZSTDcs_init)) {
2991
- fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
2746
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,
2992
2747
  cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
2993
- FORWARD_IF_ERROR(fhSize);
2748
+ FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
2749
+ assert(fhSize <= dstCapacity);
2994
2750
  dstCapacity -= fhSize;
2995
2751
  dst = (char*)dst + fhSize;
2996
2752
  cctx->stage = ZSTDcs_ongoing;
@@ -3007,25 +2763,16 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
3007
2763
 
3008
2764
  if (!frame) {
3009
2765
  /* overflow check and correction for block mode */
3010
- if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) {
3011
- U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
3012
- U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src);
3013
- ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
3014
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
3015
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
3016
- ZSTD_reduceIndex(cctx, correction);
3017
- if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
3018
- else ms->nextToUpdate -= correction;
3019
- ms->loadedDictEnd = 0;
3020
- ms->dictMatchState = NULL;
3021
- }
2766
+ ZSTD_overflowCorrectIfNeeded(
2767
+ ms, &cctx->workspace, &cctx->appliedParams,
2768
+ src, (BYTE const*)src + srcSize);
3022
2769
  }
3023
2770
 
3024
2771
  DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
3025
2772
  { size_t const cSize = frame ?
3026
2773
  ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
3027
- ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
3028
- FORWARD_IF_ERROR(cSize);
2774
+ ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */);
2775
+ FORWARD_IF_ERROR(cSize, "%s", frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed");
3029
2776
  cctx->consumedSrcSize += srcSize;
3030
2777
  cctx->producedCSize += (cSize + fhSize);
3031
2778
  assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
@@ -3060,8 +2807,9 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
3060
2807
 
3061
2808
  size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
3062
2809
  {
3063
- size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
3064
- RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong);
2810
+ DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize);
2811
+ { size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
2812
+ RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, "input is larger than a block"); }
3065
2813
 
3066
2814
  return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
3067
2815
  }
@@ -3070,47 +2818,67 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
3070
2818
  * @return : 0, or an error code
3071
2819
  */
3072
2820
  static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
2821
+ ldmState_t* ls,
2822
+ ZSTD_cwksp* ws,
3073
2823
  ZSTD_CCtx_params const* params,
3074
2824
  const void* src, size_t srcSize,
3075
2825
  ZSTD_dictTableLoadMethod_e dtlm)
3076
2826
  {
3077
- const BYTE* const ip = (const BYTE*) src;
2827
+ const BYTE* ip = (const BYTE*) src;
3078
2828
  const BYTE* const iend = ip + srcSize;
3079
2829
 
3080
2830
  ZSTD_window_update(&ms->window, src, srcSize);
3081
2831
  ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
3082
2832
 
2833
+ if (params->ldmParams.enableLdm && ls != NULL) {
2834
+ ZSTD_window_update(&ls->window, src, srcSize);
2835
+ ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base);
2836
+ }
2837
+
3083
2838
  /* Assert that we the ms params match the params we're being given */
3084
2839
  ZSTD_assertEqualCParams(params->cParams, ms->cParams);
3085
2840
 
3086
2841
  if (srcSize <= HASH_READ_SIZE) return 0;
3087
2842
 
3088
- switch(params->cParams.strategy)
3089
- {
3090
- case ZSTD_fast:
3091
- ZSTD_fillHashTable(ms, iend, dtlm);
3092
- break;
3093
- case ZSTD_dfast:
3094
- ZSTD_fillDoubleHashTable(ms, iend, dtlm);
3095
- break;
2843
+ while (iend - ip > HASH_READ_SIZE) {
2844
+ size_t const remaining = (size_t)(iend - ip);
2845
+ size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX);
2846
+ const BYTE* const ichunk = ip + chunk;
3096
2847
 
3097
- case ZSTD_greedy:
3098
- case ZSTD_lazy:
3099
- case ZSTD_lazy2:
3100
- if (srcSize >= HASH_READ_SIZE)
3101
- ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
3102
- break;
2848
+ ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk);
3103
2849
 
3104
- case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
3105
- case ZSTD_btopt:
3106
- case ZSTD_btultra:
3107
- case ZSTD_btultra2:
3108
- if (srcSize >= HASH_READ_SIZE)
3109
- ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
3110
- break;
2850
+ if (params->ldmParams.enableLdm && ls != NULL)
2851
+ ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, &params->ldmParams);
3111
2852
 
3112
- default:
3113
- assert(0); /* not possible : not a valid strategy id */
2853
+ switch(params->cParams.strategy)
2854
+ {
2855
+ case ZSTD_fast:
2856
+ ZSTD_fillHashTable(ms, ichunk, dtlm);
2857
+ break;
2858
+ case ZSTD_dfast:
2859
+ ZSTD_fillDoubleHashTable(ms, ichunk, dtlm);
2860
+ break;
2861
+
2862
+ case ZSTD_greedy:
2863
+ case ZSTD_lazy:
2864
+ case ZSTD_lazy2:
2865
+ if (chunk >= HASH_READ_SIZE)
2866
+ ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
2867
+ break;
2868
+
2869
+ case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
2870
+ case ZSTD_btopt:
2871
+ case ZSTD_btultra:
2872
+ case ZSTD_btultra2:
2873
+ if (chunk >= HASH_READ_SIZE)
2874
+ ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk);
2875
+ break;
2876
+
2877
+ default:
2878
+ assert(0); /* not possible : not a valid strategy id */
2879
+ }
2880
+
2881
+ ip = ichunk;
3114
2882
  }
3115
2883
 
3116
2884
  ms->nextToUpdate = (U32)(iend - ms->window.base);
@@ -3124,101 +2892,123 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
3124
2892
  NOTE: This behavior is not standard and could be improved in the future. */
3125
2893
  static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
3126
2894
  U32 s;
3127
- RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted);
2895
+ RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols");
3128
2896
  for (s = 0; s <= maxSymbolValue; ++s) {
3129
- RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted);
2897
+ RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols");
3130
2898
  }
3131
2899
  return 0;
3132
2900
  }
3133
2901
 
3134
-
3135
- /* Dictionary format :
3136
- * See :
3137
- * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
3138
- */
3139
- /*! ZSTD_loadZstdDictionary() :
3140
- * @return : dictID, or an error code
3141
- * assumptions : magic number supposed already checked
3142
- * dictSize supposed > 8
3143
- */
3144
- static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
3145
- ZSTD_matchState_t* ms,
3146
- ZSTD_CCtx_params const* params,
3147
- const void* dict, size_t dictSize,
3148
- ZSTD_dictTableLoadMethod_e dtlm,
3149
- void* workspace)
2902
+ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
2903
+ short* offcodeNCount, unsigned* offcodeMaxValue,
2904
+ const void* const dict, size_t dictSize)
3150
2905
  {
3151
- const BYTE* dictPtr = (const BYTE*)dict;
2906
+ const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */
3152
2907
  const BYTE* const dictEnd = dictPtr + dictSize;
3153
- short offcodeNCount[MaxOff+1];
3154
- unsigned offcodeMaxValue = MaxOff;
3155
- size_t dictID;
2908
+ dictPtr += 8;
2909
+ bs->entropy.huf.repeatMode = HUF_repeat_check;
3156
2910
 
3157
- ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
3158
- assert(dictSize > 8);
3159
- assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
2911
+ { unsigned maxSymbolValue = 255;
2912
+ unsigned hasZeroWeights = 1;
2913
+ size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr,
2914
+ dictEnd-dictPtr, &hasZeroWeights);
3160
2915
 
3161
- dictPtr += 4; /* skip magic number */
3162
- dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
3163
- dictPtr += 4;
2916
+ /* We only set the loaded table as valid if it contains all non-zero
2917
+ * weights. Otherwise, we set it to check */
2918
+ if (!hasZeroWeights)
2919
+ bs->entropy.huf.repeatMode = HUF_repeat_valid;
3164
2920
 
3165
- { unsigned maxSymbolValue = 255;
3166
- size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
3167
- RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted);
3168
- RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted);
2921
+ RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, "");
2922
+ RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, "");
3169
2923
  dictPtr += hufHeaderSize;
3170
2924
  }
3171
2925
 
3172
2926
  { unsigned offcodeLog;
3173
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
3174
- RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
3175
- RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
2927
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
2928
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
2929
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
3176
2930
  /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
3177
2931
  /* fill all offset symbols to avoid garbage at end of table */
3178
2932
  RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3179
2933
  bs->entropy.fse.offcodeCTable,
3180
2934
  offcodeNCount, MaxOff, offcodeLog,
3181
2935
  workspace, HUF_WORKSPACE_SIZE)),
3182
- dictionary_corrupted);
2936
+ dictionary_corrupted, "");
3183
2937
  dictPtr += offcodeHeaderSize;
3184
2938
  }
3185
2939
 
3186
2940
  { short matchlengthNCount[MaxML+1];
3187
2941
  unsigned matchlengthMaxValue = MaxML, matchlengthLog;
3188
2942
  size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
3189
- RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
3190
- RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
2943
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
2944
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
3191
2945
  /* Every match length code must have non-zero probability */
3192
- FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
2946
+ FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), "");
3193
2947
  RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3194
2948
  bs->entropy.fse.matchlengthCTable,
3195
2949
  matchlengthNCount, matchlengthMaxValue, matchlengthLog,
3196
2950
  workspace, HUF_WORKSPACE_SIZE)),
3197
- dictionary_corrupted);
2951
+ dictionary_corrupted, "");
3198
2952
  dictPtr += matchlengthHeaderSize;
3199
2953
  }
3200
2954
 
3201
2955
  { short litlengthNCount[MaxLL+1];
3202
2956
  unsigned litlengthMaxValue = MaxLL, litlengthLog;
3203
2957
  size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
3204
- RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
3205
- RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
2958
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
2959
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
3206
2960
  /* Every literal length code must have non-zero probability */
3207
- FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
2961
+ FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), "");
3208
2962
  RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
3209
2963
  bs->entropy.fse.litlengthCTable,
3210
2964
  litlengthNCount, litlengthMaxValue, litlengthLog,
3211
2965
  workspace, HUF_WORKSPACE_SIZE)),
3212
- dictionary_corrupted);
2966
+ dictionary_corrupted, "");
3213
2967
  dictPtr += litlengthHeaderSize;
3214
2968
  }
3215
2969
 
3216
- RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
2970
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
3217
2971
  bs->rep[0] = MEM_readLE32(dictPtr+0);
3218
2972
  bs->rep[1] = MEM_readLE32(dictPtr+4);
3219
2973
  bs->rep[2] = MEM_readLE32(dictPtr+8);
3220
2974
  dictPtr += 12;
3221
2975
 
2976
+ return dictPtr - (const BYTE*)dict;
2977
+ }
2978
+
2979
+ /* Dictionary format :
2980
+ * See :
2981
+ * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
2982
+ */
2983
+ /*! ZSTD_loadZstdDictionary() :
2984
+ * @return : dictID, or an error code
2985
+ * assumptions : magic number supposed already checked
2986
+ * dictSize supposed >= 8
2987
+ */
2988
+ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
2989
+ ZSTD_matchState_t* ms,
2990
+ ZSTD_cwksp* ws,
2991
+ ZSTD_CCtx_params const* params,
2992
+ const void* dict, size_t dictSize,
2993
+ ZSTD_dictTableLoadMethod_e dtlm,
2994
+ void* workspace)
2995
+ {
2996
+ const BYTE* dictPtr = (const BYTE*)dict;
2997
+ const BYTE* const dictEnd = dictPtr + dictSize;
2998
+ short offcodeNCount[MaxOff+1];
2999
+ unsigned offcodeMaxValue = MaxOff;
3000
+ size_t dictID;
3001
+ size_t eSize;
3002
+
3003
+ ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
3004
+ assert(dictSize >= 8);
3005
+ assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
3006
+
3007
+ dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ );
3008
+ eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize);
3009
+ FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed");
3010
+ dictPtr += eSize;
3011
+
3222
3012
  { size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
3223
3013
  U32 offcodeMax = MaxOff;
3224
3014
  if (dictContentSize <= ((U32)-1) - 128 KB) {
@@ -3226,19 +3016,19 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
3226
3016
  offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
3227
3017
  }
3228
3018
  /* All offset values <= dictContentSize + 128 KB must be representable */
3229
- FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
3019
+ FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), "");
3230
3020
  /* All repCodes must be <= dictContentSize and != 0*/
3231
3021
  { U32 u;
3232
3022
  for (u=0; u<3; u++) {
3233
- RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted);
3234
- RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted);
3023
+ RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
3024
+ RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
3235
3025
  } }
3236
3026
 
3237
- bs->entropy.huf.repeatMode = HUF_repeat_valid;
3238
3027
  bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
3239
3028
  bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
3240
3029
  bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
3241
- FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
3030
+ FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
3031
+ ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
3242
3032
  return dictID;
3243
3033
  }
3244
3034
  }
@@ -3248,6 +3038,8 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
3248
3038
  static size_t
3249
3039
  ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
3250
3040
  ZSTD_matchState_t* ms,
3041
+ ldmState_t* ls,
3042
+ ZSTD_cwksp* ws,
3251
3043
  const ZSTD_CCtx_params* params,
3252
3044
  const void* dict, size_t dictSize,
3253
3045
  ZSTD_dictContentType_e dictContentType,
@@ -3255,27 +3047,35 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
3255
3047
  void* workspace)
3256
3048
  {
3257
3049
  DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
3258
- if ((dict==NULL) || (dictSize<=8)) return 0;
3050
+ if ((dict==NULL) || (dictSize<8)) {
3051
+ RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
3052
+ return 0;
3053
+ }
3259
3054
 
3260
3055
  ZSTD_reset_compressedBlockState(bs);
3261
3056
 
3262
3057
  /* dict restricted modes */
3263
3058
  if (dictContentType == ZSTD_dct_rawContent)
3264
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
3059
+ return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm);
3265
3060
 
3266
3061
  if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
3267
3062
  if (dictContentType == ZSTD_dct_auto) {
3268
3063
  DEBUGLOG(4, "raw content dictionary detected");
3269
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
3064
+ return ZSTD_loadDictionaryContent(
3065
+ ms, ls, ws, params, dict, dictSize, dtlm);
3270
3066
  }
3271
- RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong);
3067
+ RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
3272
3068
  assert(0); /* impossible */
3273
3069
  }
3274
3070
 
3275
3071
  /* dict as full zstd dictionary */
3276
- return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, dtlm, workspace);
3072
+ return ZSTD_loadZstdDictionary(
3073
+ bs, ms, ws, params, dict, dictSize, dtlm, workspace);
3277
3074
  }
3278
3075
 
3076
+ #define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
3077
+ #define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6)
3078
+
3279
3079
  /*! ZSTD_compressBegin_internal() :
3280
3080
  * @return : 0, or an error code */
3281
3081
  static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
@@ -3283,26 +3083,37 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
3283
3083
  ZSTD_dictContentType_e dictContentType,
3284
3084
  ZSTD_dictTableLoadMethod_e dtlm,
3285
3085
  const ZSTD_CDict* cdict,
3286
- ZSTD_CCtx_params params, U64 pledgedSrcSize,
3086
+ const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
3287
3087
  ZSTD_buffered_policy_e zbuff)
3288
3088
  {
3289
- DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params.cParams.windowLog);
3089
+ DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
3290
3090
  /* params are supposed to be fully validated at this point */
3291
- assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3091
+ assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
3292
3092
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3293
-
3294
- if (cdict && cdict->dictContentSize>0) {
3093
+ if ( (cdict)
3094
+ && (cdict->dictContentSize > 0)
3095
+ && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
3096
+ || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
3097
+ || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
3098
+ || cdict->compressionLevel == 0)
3099
+ && (params->attachDictPref != ZSTD_dictForceLoad) ) {
3295
3100
  return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
3296
3101
  }
3297
3102
 
3298
- FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
3299
- ZSTDcrp_continue, zbuff) );
3300
- {
3301
- size_t const dictID = ZSTD_compress_insertDictionary(
3302
- cctx->blockState.prevCBlock, &cctx->blockState.matchState,
3303
- &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
3304
- FORWARD_IF_ERROR(dictID);
3305
- assert(dictID <= (size_t)(U32)-1);
3103
+ FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize,
3104
+ ZSTDcrp_makeClean, zbuff) , "");
3105
+ { size_t const dictID = cdict ?
3106
+ ZSTD_compress_insertDictionary(
3107
+ cctx->blockState.prevCBlock, &cctx->blockState.matchState,
3108
+ &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,
3109
+ cdict->dictContentSize, dictContentType, dtlm,
3110
+ cctx->entropyWorkspace)
3111
+ : ZSTD_compress_insertDictionary(
3112
+ cctx->blockState.prevCBlock, &cctx->blockState.matchState,
3113
+ &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize,
3114
+ dictContentType, dtlm, cctx->entropyWorkspace);
3115
+ FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
3116
+ assert(dictID <= UINT_MAX);
3306
3117
  cctx->dictID = (U32)dictID;
3307
3118
  }
3308
3119
  return 0;
@@ -3313,12 +3124,12 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
3313
3124
  ZSTD_dictContentType_e dictContentType,
3314
3125
  ZSTD_dictTableLoadMethod_e dtlm,
3315
3126
  const ZSTD_CDict* cdict,
3316
- ZSTD_CCtx_params params,
3127
+ const ZSTD_CCtx_params* params,
3317
3128
  unsigned long long pledgedSrcSize)
3318
3129
  {
3319
- DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
3130
+ DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog);
3320
3131
  /* compression parameters verification and optimization */
3321
- FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
3132
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , "");
3322
3133
  return ZSTD_compressBegin_internal(cctx,
3323
3134
  dict, dictSize, dictContentType, dtlm,
3324
3135
  cdict,
@@ -3333,21 +3144,21 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
3333
3144
  ZSTD_parameters params, unsigned long long pledgedSrcSize)
3334
3145
  {
3335
3146
  ZSTD_CCtx_params const cctxParams =
3336
- ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3147
+ ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
3337
3148
  return ZSTD_compressBegin_advanced_internal(cctx,
3338
3149
  dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
3339
3150
  NULL /*cdict*/,
3340
- cctxParams, pledgedSrcSize);
3151
+ &cctxParams, pledgedSrcSize);
3341
3152
  }
3342
3153
 
3343
3154
  size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
3344
3155
  {
3345
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3156
+ ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3346
3157
  ZSTD_CCtx_params const cctxParams =
3347
- ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3158
+ ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
3348
3159
  DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
3349
3160
  return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3350
- cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
3161
+ &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
3351
3162
  }
3352
3163
 
3353
3164
  size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
@@ -3370,8 +3181,8 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
3370
3181
 
3371
3182
  /* special case : empty frame */
3372
3183
  if (cctx->stage == ZSTDcs_init) {
3373
- fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
3374
- FORWARD_IF_ERROR(fhSize);
3184
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
3185
+ FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
3375
3186
  dstCapacity -= fhSize;
3376
3187
  op += fhSize;
3377
3188
  cctx->stage = ZSTDcs_ongoing;
@@ -3380,7 +3191,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
3380
3191
  if (cctx->stage != ZSTDcs_ending) {
3381
3192
  /* write one last empty block, make it the "last" block */
3382
3193
  U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
3383
- RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
3194
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue");
3384
3195
  MEM_writeLE32(op, cBlockHeader24);
3385
3196
  op += ZSTD_blockHeaderSize;
3386
3197
  dstCapacity -= ZSTD_blockHeaderSize;
@@ -3388,7 +3199,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
3388
3199
 
3389
3200
  if (cctx->appliedParams.fParams.checksumFlag) {
3390
3201
  U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
3391
- RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
3202
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
3392
3203
  DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
3393
3204
  MEM_writeLE32(op, checksum);
3394
3205
  op += 4;
@@ -3406,9 +3217,9 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
3406
3217
  size_t const cSize = ZSTD_compressContinue_internal(cctx,
3407
3218
  dst, dstCapacity, src, srcSize,
3408
3219
  1 /* frame mode */, 1 /* last chunk */);
3409
- FORWARD_IF_ERROR(cSize);
3220
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed");
3410
3221
  endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
3411
- FORWARD_IF_ERROR(endResult);
3222
+ FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed");
3412
3223
  assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
3413
3224
  if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
3414
3225
  ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
@@ -3428,16 +3239,16 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
3428
3239
  void* dst, size_t dstCapacity,
3429
3240
  const void* src, size_t srcSize,
3430
3241
  const void* dict,size_t dictSize,
3431
- ZSTD_parameters params)
3242
+ const ZSTD_parameters* params)
3432
3243
  {
3433
3244
  ZSTD_CCtx_params const cctxParams =
3434
- ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3245
+ ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params);
3435
3246
  DEBUGLOG(4, "ZSTD_compress_internal");
3436
3247
  return ZSTD_compress_advanced_internal(cctx,
3437
3248
  dst, dstCapacity,
3438
3249
  src, srcSize,
3439
3250
  dict, dictSize,
3440
- cctxParams);
3251
+ &cctxParams);
3441
3252
  }
3442
3253
 
3443
3254
  size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
@@ -3447,12 +3258,12 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
3447
3258
  ZSTD_parameters params)
3448
3259
  {
3449
3260
  DEBUGLOG(4, "ZSTD_compress_advanced");
3450
- FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams));
3261
+ FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
3451
3262
  return ZSTD_compress_internal(cctx,
3452
3263
  dst, dstCapacity,
3453
3264
  src, srcSize,
3454
3265
  dict, dictSize,
3455
- params);
3266
+ &params);
3456
3267
  }
3457
3268
 
3458
3269
  /* Internal */
@@ -3461,12 +3272,12 @@ size_t ZSTD_compress_advanced_internal(
3461
3272
  void* dst, size_t dstCapacity,
3462
3273
  const void* src, size_t srcSize,
3463
3274
  const void* dict,size_t dictSize,
3464
- ZSTD_CCtx_params params)
3275
+ const ZSTD_CCtx_params* params)
3465
3276
  {
3466
3277
  DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
3467
3278
  FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
3468
3279
  dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3469
- params, srcSize, ZSTDb_not_buffered) );
3280
+ params, srcSize, ZSTDb_not_buffered) , "");
3470
3281
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3471
3282
  }
3472
3283
 
@@ -3476,10 +3287,11 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
3476
3287
  const void* dict, size_t dictSize,
3477
3288
  int compressionLevel)
3478
3289
  {
3479
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize + (!srcSize), dict ? dictSize : 0);
3480
- ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3290
+ ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0);
3291
+ ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
3292
+ DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize);
3481
3293
  assert(params.fParams.contentSizeFlag == 1);
3482
- return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams);
3294
+ return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams);
3483
3295
  }
3484
3296
 
3485
3297
  size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
@@ -3514,13 +3326,16 @@ size_t ZSTD_estimateCDictSize_advanced(
3514
3326
  ZSTD_dictLoadMethod_e dictLoadMethod)
3515
3327
  {
3516
3328
  DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
3517
- return sizeof(ZSTD_CDict) + HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
3518
- + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
3329
+ return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
3330
+ + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
3331
+ + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
3332
+ + (dictLoadMethod == ZSTD_dlm_byRef ? 0
3333
+ : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));
3519
3334
  }
3520
3335
 
3521
3336
  size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
3522
3337
  {
3523
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3338
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3524
3339
  return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
3525
3340
  }
3526
3341
 
@@ -3528,7 +3343,9 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
3528
3343
  {
3529
3344
  if (cdict==NULL) return 0; /* support sizeof on NULL */
3530
3345
  DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict));
3531
- return cdict->workspaceSize + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
3346
+ /* cdict may be in the workspace */
3347
+ return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict))
3348
+ + ZSTD_cwksp_sizeof(&cdict->workspace);
3532
3349
  }
3533
3350
 
3534
3351
  static size_t ZSTD_initCDict_internal(
@@ -3542,28 +3359,29 @@ static size_t ZSTD_initCDict_internal(
3542
3359
  assert(!ZSTD_checkCParams(cParams));
3543
3360
  cdict->matchState.cParams = cParams;
3544
3361
  if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
3545
- cdict->dictBuffer = NULL;
3546
3362
  cdict->dictContent = dictBuffer;
3547
3363
  } else {
3548
- void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
3549
- cdict->dictBuffer = internalBuffer;
3364
+ void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));
3365
+ RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!");
3550
3366
  cdict->dictContent = internalBuffer;
3551
- RETURN_ERROR_IF(!internalBuffer, memory_allocation);
3552
3367
  memcpy(internalBuffer, dictBuffer, dictSize);
3553
3368
  }
3554
3369
  cdict->dictContentSize = dictSize;
3555
3370
 
3371
+ cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
3372
+
3373
+
3556
3374
  /* Reset the state to no dictionary */
3557
3375
  ZSTD_reset_compressedBlockState(&cdict->cBlockState);
3558
- { void* const end = ZSTD_reset_matchState(
3559
- &cdict->matchState,
3560
- (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32,
3561
- &cParams, ZSTDcrp_continue, /* forCCtx */ 0);
3562
- assert(end == (char*)cdict->workspace + cdict->workspaceSize);
3563
- (void)end;
3564
- }
3376
+ FORWARD_IF_ERROR(ZSTD_reset_matchState(
3377
+ &cdict->matchState,
3378
+ &cdict->workspace,
3379
+ &cParams,
3380
+ ZSTDcrp_makeClean,
3381
+ ZSTDirp_reset,
3382
+ ZSTD_resetTarget_CDict), "");
3565
3383
  /* (Maybe) load the dictionary
3566
- * Skips loading the dictionary if it is <= 8 bytes.
3384
+ * Skips loading the dictionary if it is < 8 bytes.
3567
3385
  */
3568
3386
  { ZSTD_CCtx_params params;
3569
3387
  memset(&params, 0, sizeof(params));
@@ -3571,10 +3389,10 @@ static size_t ZSTD_initCDict_internal(
3571
3389
  params.fParams.contentSizeFlag = 1;
3572
3390
  params.cParams = cParams;
3573
3391
  { size_t const dictID = ZSTD_compress_insertDictionary(
3574
- &cdict->cBlockState, &cdict->matchState, &params,
3575
- cdict->dictContent, cdict->dictContentSize,
3576
- dictContentType, ZSTD_dtlm_full, cdict->workspace);
3577
- FORWARD_IF_ERROR(dictID);
3392
+ &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,
3393
+ &params, cdict->dictContent, cdict->dictContentSize,
3394
+ dictContentType, ZSTD_dtlm_full, cdict->entropyWorkspace);
3395
+ FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
3578
3396
  assert(dictID <= (size_t)(U32)-1);
3579
3397
  cdict->dictID = (U32)dictID;
3580
3398
  }
@@ -3591,18 +3409,29 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3591
3409
  DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType);
3592
3410
  if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
3593
3411
 
3594
- { ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
3595
- size_t const workspaceSize = HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
3412
+ { size_t const workspaceSize =
3413
+ ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +
3414
+ ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) +
3415
+ ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) +
3416
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0
3417
+ : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));
3596
3418
  void* const workspace = ZSTD_malloc(workspaceSize, customMem);
3419
+ ZSTD_cwksp ws;
3420
+ ZSTD_CDict* cdict;
3597
3421
 
3598
- if (!cdict || !workspace) {
3599
- ZSTD_free(cdict, customMem);
3422
+ if (!workspace) {
3600
3423
  ZSTD_free(workspace, customMem);
3601
3424
  return NULL;
3602
3425
  }
3426
+
3427
+ ZSTD_cwksp_init(&ws, workspace, workspaceSize);
3428
+
3429
+ cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
3430
+ assert(cdict != NULL);
3431
+ ZSTD_cwksp_move(&cdict->workspace, &ws);
3603
3432
  cdict->customMem = customMem;
3604
- cdict->workspace = workspace;
3605
- cdict->workspaceSize = workspaceSize;
3433
+ cdict->compressionLevel = 0; /* signals advanced API usage */
3434
+
3606
3435
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3607
3436
  dictBuffer, dictSize,
3608
3437
  dictLoadMethod, dictContentType,
@@ -3617,15 +3446,18 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3617
3446
 
3618
3447
  ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
3619
3448
  {
3620
- ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3621
- return ZSTD_createCDict_advanced(dict, dictSize,
3622
- ZSTD_dlm_byCopy, ZSTD_dct_auto,
3623
- cParams, ZSTD_defaultCMem);
3449
+ ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3450
+ ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize,
3451
+ ZSTD_dlm_byCopy, ZSTD_dct_auto,
3452
+ cParams, ZSTD_defaultCMem);
3453
+ if (cdict)
3454
+ cdict->compressionLevel = compressionLevel == 0 ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
3455
+ return cdict;
3624
3456
  }
3625
3457
 
3626
3458
  ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
3627
3459
  {
3628
- ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3460
+ ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3629
3461
  return ZSTD_createCDict_advanced(dict, dictSize,
3630
3462
  ZSTD_dlm_byRef, ZSTD_dct_auto,
3631
3463
  cParams, ZSTD_defaultCMem);
@@ -3635,9 +3467,11 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
3635
3467
  {
3636
3468
  if (cdict==NULL) return 0; /* support free on NULL */
3637
3469
  { ZSTD_customMem const cMem = cdict->customMem;
3638
- ZSTD_free(cdict->workspace, cMem);
3639
- ZSTD_free(cdict->dictBuffer, cMem);
3640
- ZSTD_free(cdict, cMem);
3470
+ int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);
3471
+ ZSTD_cwksp_free(&cdict->workspace, cMem);
3472
+ if (!cdictInWorkspace) {
3473
+ ZSTD_free(cdict, cMem);
3474
+ }
3641
3475
  return 0;
3642
3476
  }
3643
3477
  }
@@ -3663,28 +3497,30 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
3663
3497
  ZSTD_compressionParameters cParams)
3664
3498
  {
3665
3499
  size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
3666
- size_t const neededSize = sizeof(ZSTD_CDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize)
3667
- + HUF_WORKSPACE_SIZE + matchStateSize;
3668
- ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
3669
- void* ptr;
3500
+ size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
3501
+ + (dictLoadMethod == ZSTD_dlm_byRef ? 0
3502
+ : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))))
3503
+ + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
3504
+ + matchStateSize;
3505
+ ZSTD_CDict* cdict;
3506
+
3670
3507
  if ((size_t)workspace & 7) return NULL; /* 8-aligned */
3508
+
3509
+ {
3510
+ ZSTD_cwksp ws;
3511
+ ZSTD_cwksp_init(&ws, workspace, workspaceSize);
3512
+ cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
3513
+ if (cdict == NULL) return NULL;
3514
+ ZSTD_cwksp_move(&cdict->workspace, &ws);
3515
+ }
3516
+
3671
3517
  DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
3672
3518
  (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
3673
3519
  if (workspaceSize < neededSize) return NULL;
3674
3520
 
3675
- if (dictLoadMethod == ZSTD_dlm_byCopy) {
3676
- memcpy(cdict+1, dict, dictSize);
3677
- dict = cdict+1;
3678
- ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
3679
- } else {
3680
- ptr = cdict+1;
3681
- }
3682
- cdict->workspace = ptr;
3683
- cdict->workspaceSize = HUF_WORKSPACE_SIZE + matchStateSize;
3684
-
3685
3521
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3686
3522
  dict, dictSize,
3687
- ZSTD_dlm_byRef, dictContentType,
3523
+ dictLoadMethod, dictContentType,
3688
3524
  cParams) ))
3689
3525
  return NULL;
3690
3526
 
@@ -3704,9 +3540,17 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
3704
3540
  ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
3705
3541
  {
3706
3542
  DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
3707
- RETURN_ERROR_IF(cdict==NULL, dictionary_wrong);
3543
+ RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
3708
3544
  { ZSTD_CCtx_params params = cctx->requestedParams;
3709
- params.cParams = ZSTD_getCParamsFromCDict(cdict);
3545
+ params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
3546
+ || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
3547
+ || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
3548
+ || cdict->compressionLevel == 0 )
3549
+ && (params.attachDictPref != ZSTD_dictForceLoad) ?
3550
+ ZSTD_getCParamsFromCDict(cdict)
3551
+ : ZSTD_getCParams(cdict->compressionLevel,
3552
+ pledgedSrcSize,
3553
+ cdict->dictContentSize);
3710
3554
  /* Increase window log to fit the entire dictionary and source if the
3711
3555
  * source size is known. Limit the increase to 19, which is the
3712
3556
  * window log for compression level 1 with the largest source size.
@@ -3720,7 +3564,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
3720
3564
  return ZSTD_compressBegin_internal(cctx,
3721
3565
  NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
3722
3566
  cdict,
3723
- params, pledgedSrcSize,
3567
+ &params, pledgedSrcSize,
3724
3568
  ZSTDb_not_buffered);
3725
3569
  }
3726
3570
  }
@@ -3740,7 +3584,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
3740
3584
  const void* src, size_t srcSize,
3741
3585
  const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
3742
3586
  {
3743
- FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
3587
+ FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */
3744
3588
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3745
3589
  }
3746
3590
 
@@ -3811,8 +3655,8 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
3811
3655
  FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
3812
3656
  dict, dictSize, dictContentType, ZSTD_dtlm_fast,
3813
3657
  cdict,
3814
- params, pledgedSrcSize,
3815
- ZSTDb_buffered) );
3658
+ &params, pledgedSrcSize,
3659
+ ZSTDb_buffered) , "");
3816
3660
 
3817
3661
  cctx->inToCompress = 0;
3818
3662
  cctx->inBuffPos = 0;
@@ -3834,8 +3678,8 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
3834
3678
  */
3835
3679
  U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3836
3680
  DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
3837
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3838
- FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3681
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3682
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3839
3683
  return 0;
3840
3684
  }
3841
3685
 
@@ -3845,19 +3689,20 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
3845
3689
  * Assumption 2 : either dict, or cdict, is defined, not both */
3846
3690
  size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3847
3691
  const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3848
- ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
3692
+ const ZSTD_CCtx_params* params,
3693
+ unsigned long long pledgedSrcSize)
3849
3694
  {
3850
3695
  DEBUGLOG(4, "ZSTD_initCStream_internal");
3851
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3852
- FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3853
- assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3854
- zcs->requestedParams = params;
3696
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3697
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3698
+ assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
3699
+ zcs->requestedParams = *params;
3855
3700
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3856
3701
  if (dict) {
3857
- FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
3702
+ FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
3858
3703
  } else {
3859
3704
  /* Dictionary is cleared if !cdict */
3860
- FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
3705
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
3861
3706
  }
3862
3707
  return 0;
3863
3708
  }
@@ -3870,10 +3715,10 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
3870
3715
  unsigned long long pledgedSrcSize)
3871
3716
  {
3872
3717
  DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
3873
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3874
- FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3718
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3719
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3875
3720
  zcs->requestedParams.fParams = fParams;
3876
- FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
3721
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
3877
3722
  return 0;
3878
3723
  }
3879
3724
 
@@ -3881,8 +3726,8 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
3881
3726
  size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
3882
3727
  {
3883
3728
  DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
3884
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3885
- FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
3729
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3730
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
3886
3731
  return 0;
3887
3732
  }
3888
3733
 
@@ -3890,7 +3735,7 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
3890
3735
  /* ZSTD_initCStream_advanced() :
3891
3736
  * pledgedSrcSize must be exact.
3892
3737
  * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
3893
- * dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
3738
+ * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */
3894
3739
  size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
3895
3740
  const void* dict, size_t dictSize,
3896
3741
  ZSTD_parameters params, unsigned long long pss)
@@ -3901,20 +3746,20 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
3901
3746
  */
3902
3747
  U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3903
3748
  DEBUGLOG(4, "ZSTD_initCStream_advanced");
3904
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3905
- FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3906
- FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
3907
- zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3908
- FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
3749
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3750
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3751
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
3752
+ zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, &params);
3753
+ FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
3909
3754
  return 0;
3910
3755
  }
3911
3756
 
3912
3757
  size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3913
3758
  {
3914
3759
  DEBUGLOG(4, "ZSTD_initCStream_usingDict");
3915
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3916
- FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
3917
- FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
3760
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3761
+ FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
3762
+ FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
3918
3763
  return 0;
3919
3764
  }
3920
3765
 
@@ -3926,19 +3771,19 @@ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigne
3926
3771
  */
3927
3772
  U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3928
3773
  DEBUGLOG(4, "ZSTD_initCStream_srcSize");
3929
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3930
- FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
3931
- FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
3932
- FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
3774
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3775
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
3776
+ FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
3777
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3933
3778
  return 0;
3934
3779
  }
3935
3780
 
3936
3781
  size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
3937
3782
  {
3938
3783
  DEBUGLOG(4, "ZSTD_initCStream");
3939
- FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
3940
- FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
3941
- FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
3784
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3785
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
3786
+ FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
3942
3787
  return 0;
3943
3788
  }
3944
3789
 
@@ -3951,14 +3796,6 @@ static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
3951
3796
  return hintInSize;
3952
3797
  }
3953
3798
 
3954
- static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
3955
- const void* src, size_t srcSize)
3956
- {
3957
- size_t const length = MIN(dstCapacity, srcSize);
3958
- if (length) memcpy(dst, src, length);
3959
- return length;
3960
- }
3961
-
3962
3799
  /** ZSTD_compressStream_generic():
3963
3800
  * internal function for all *compressStream*() variants
3964
3801
  * non-static, because can be called from zstdmt_compress.c
@@ -3969,11 +3806,11 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3969
3806
  ZSTD_EndDirective const flushMode)
3970
3807
  {
3971
3808
  const char* const istart = (const char*)input->src;
3972
- const char* const iend = istart + input->size;
3973
- const char* ip = istart + input->pos;
3809
+ const char* const iend = input->size != 0 ? istart + input->size : istart;
3810
+ const char* ip = input->pos != 0 ? istart + input->pos : istart;
3974
3811
  char* const ostart = (char*)output->dst;
3975
- char* const oend = ostart + output->size;
3976
- char* op = ostart + output->pos;
3812
+ char* const oend = output->size != 0 ? ostart + output->size : ostart;
3813
+ char* op = output->pos != 0 ? ostart + output->pos : ostart;
3977
3814
  U32 someMoreWork = 1;
3978
3815
 
3979
3816
  /* check expectations */
@@ -3999,7 +3836,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3999
3836
  size_t const cSize = ZSTD_compressEnd(zcs,
4000
3837
  op, oend-op, ip, iend-ip);
4001
3838
  DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
4002
- FORWARD_IF_ERROR(cSize);
3839
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed");
4003
3840
  ip = iend;
4004
3841
  op += cSize;
4005
3842
  zcs->frameEnded = 1;
@@ -4012,7 +3849,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
4012
3849
  zcs->inBuff + zcs->inBuffPos, toLoad,
4013
3850
  ip, iend-ip);
4014
3851
  zcs->inBuffPos += loaded;
4015
- ip += loaded;
3852
+ if (loaded != 0)
3853
+ ip += loaded;
4016
3854
  if ( (flushMode == ZSTD_e_continue)
4017
3855
  && (zcs->inBuffPos < zcs->inBuffTarget) ) {
4018
3856
  /* not enough input to fill full block : stop here */
@@ -4040,7 +3878,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
4040
3878
  zcs->inBuff + zcs->inToCompress, iSize) :
4041
3879
  ZSTD_compressContinue(zcs, cDst, oSize,
4042
3880
  zcs->inBuff + zcs->inToCompress, iSize);
4043
- FORWARD_IF_ERROR(cSize);
3881
+ FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
4044
3882
  zcs->frameEnded = lastBlock;
4045
3883
  /* prepare next block */
4046
3884
  zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
@@ -4068,11 +3906,12 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
4068
3906
  case zcss_flush:
4069
3907
  DEBUGLOG(5, "flush stage");
4070
3908
  { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
4071
- size_t const flushed = ZSTD_limitCopy(op, oend-op,
3909
+ size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
4072
3910
  zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
4073
3911
  DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
4074
3912
  (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
4075
- op += flushed;
3913
+ if (flushed)
3914
+ op += flushed;
4076
3915
  zcs->outBuffFlushedSize += flushed;
4077
3916
  if (toFlush!=flushed) {
4078
3917
  /* flush not fully completed, presumably because dst is too small */
@@ -4116,7 +3955,7 @@ static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
4116
3955
 
4117
3956
  size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
4118
3957
  {
4119
- FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
3958
+ FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , "");
4120
3959
  return ZSTD_nextInputSizeHint_MTorST(zcs);
4121
3960
  }
4122
3961
 
@@ -4128,15 +3967,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4128
3967
  {
4129
3968
  DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
4130
3969
  /* check conditions */
4131
- RETURN_ERROR_IF(output->pos > output->size, GENERIC);
4132
- RETURN_ERROR_IF(input->pos > input->size, GENERIC);
3970
+ RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer");
3971
+ RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer");
4133
3972
  assert(cctx!=NULL);
4134
3973
 
4135
3974
  /* transparent initialization stage */
4136
3975
  if (cctx->streamStage == zcss_init) {
4137
3976
  ZSTD_CCtx_params params = cctx->requestedParams;
4138
3977
  ZSTD_prefixDict const prefixDict = cctx->prefixDict;
4139
- FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) ); /* Init the local dict if present. */
3978
+ FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
4140
3979
  memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
4141
3980
  assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
4142
3981
  DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
@@ -4154,15 +3993,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4154
3993
  if (cctx->mtctx == NULL) {
4155
3994
  DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
4156
3995
  params.nbWorkers);
4157
- cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
4158
- RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation);
3996
+ cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem);
3997
+ RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
4159
3998
  }
4160
3999
  /* mt compression */
4161
4000
  DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
4162
4001
  FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
4163
4002
  cctx->mtctx,
4164
- prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
4165
- cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
4003
+ prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
4004
+ cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
4166
4005
  cctx->streamStage = zcss_load;
4167
4006
  cctx->appliedParams.nbWorkers = params.nbWorkers;
4168
4007
  } else
@@ -4170,7 +4009,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4170
4009
  { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
4171
4010
  prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
4172
4011
  cctx->cdict,
4173
- params, cctx->pledgedSrcSizePlusOne-1) );
4012
+ params, cctx->pledgedSrcSizePlusOne-1) , "");
4174
4013
  assert(cctx->streamStage == zcss_load);
4175
4014
  assert(cctx->appliedParams.nbWorkers == 0);
4176
4015
  } }
@@ -4192,7 +4031,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4192
4031
  || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
4193
4032
  ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
4194
4033
  }
4195
- FORWARD_IF_ERROR(flushMin);
4034
+ FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
4196
4035
  } while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
4197
4036
  DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
4198
4037
  /* Either we don't require maximum forward progress, we've finished the
@@ -4202,7 +4041,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4202
4041
  return flushMin;
4203
4042
  }
4204
4043
  #endif
4205
- FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) );
4044
+ FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
4206
4045
  DEBUGLOG(5, "completed ZSTD_compressStream2");
4207
4046
  return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
4208
4047
  }
@@ -4226,6 +4065,7 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
4226
4065
  void* dst, size_t dstCapacity,
4227
4066
  const void* src, size_t srcSize)
4228
4067
  {
4068
+ DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
4229
4069
  ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
4230
4070
  { size_t oPos = 0;
4231
4071
  size_t iPos = 0;
@@ -4233,10 +4073,10 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
4233
4073
  dst, dstCapacity, &oPos,
4234
4074
  src, srcSize, &iPos,
4235
4075
  ZSTD_e_end);
4236
- FORWARD_IF_ERROR(result);
4076
+ FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
4237
4077
  if (result != 0) { /* compression not completed, due to lack of output space */
4238
4078
  assert(oPos == dstCapacity);
4239
- RETURN_ERROR(dstSize_tooSmall);
4079
+ RETURN_ERROR(dstSize_tooSmall, "");
4240
4080
  }
4241
4081
  assert(iPos == srcSize); /* all input is expected consumed */
4242
4082
  return oPos;
@@ -4258,11 +4098,11 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
4258
4098
  {
4259
4099
  ZSTD_inBuffer input = { NULL, 0, 0 };
4260
4100
  size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
4261
- FORWARD_IF_ERROR( remainingToFlush );
4101
+ FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed");
4262
4102
  if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
4263
4103
  /* single thread mode : attempt to calculate remaining to flush more precisely */
4264
4104
  { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
4265
- size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4;
4105
+ size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);
4266
4106
  size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
4267
4107
  DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
4268
4108
  return toFlush;
@@ -4282,8 +4122,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4282
4122
  { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
4283
4123
  { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
4284
4124
  { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
4285
- { 21, 16, 17, 1, 5, 1, ZSTD_dfast }, /* level 3 */
4286
- { 21, 18, 18, 1, 5, 1, ZSTD_dfast }, /* level 4 */
4125
+ { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */
4126
+ { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */
4287
4127
  { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */
4288
4128
  { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */
4289
4129
  { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */
@@ -4307,8 +4147,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4307
4147
  /* W, C, H, S, L, T, strat */
4308
4148
  { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
4309
4149
  { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
4310
- { 18, 14, 14, 1, 5, 1, ZSTD_dfast }, /* level 2 */
4311
- { 18, 16, 16, 1, 4, 1, ZSTD_dfast }, /* level 3 */
4150
+ { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */
4151
+ { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */
4312
4152
  { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
4313
4153
  { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
4314
4154
  { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
@@ -4334,8 +4174,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4334
4174
  { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
4335
4175
  { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
4336
4176
  { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
4337
- { 17, 15, 16, 2, 5, 1, ZSTD_dfast }, /* level 3 */
4338
- { 17, 17, 17, 2, 4, 1, ZSTD_dfast }, /* level 4 */
4177
+ { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */
4178
+ { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */
4339
4179
  { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
4340
4180
  { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
4341
4181
  { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
@@ -4360,7 +4200,7 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4360
4200
  { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
4361
4201
  { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
4362
4202
  { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
4363
- { 14, 14, 15, 2, 4, 1, ZSTD_dfast }, /* level 3 */
4203
+ { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
4364
4204
  { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
4365
4205
  { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
4366
4206
  { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
@@ -4383,35 +4223,56 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4383
4223
  },
4384
4224
  };
4385
4225
 
4386
- /*! ZSTD_getCParams() :
4226
+ /*! ZSTD_getCParams_internal() :
4387
4227
  * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
4388
- * Size values are optional, provide 0 if not known or unused */
4389
- ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
4228
+ * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.
4229
+ * Use dictSize == 0 for unknown or unused. */
4230
+ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
4390
4231
  {
4391
- size_t const addedSize = srcSizeHint ? 0 : 500;
4392
- U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : ZSTD_CONTENTSIZE_UNKNOWN; /* intentional overflow for srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN */
4232
+ int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;
4233
+ size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
4234
+ U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
4393
4235
  U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
4394
4236
  int row = compressionLevel;
4395
- DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
4237
+ DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
4396
4238
  if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
4397
4239
  if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
4398
4240
  if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
4399
4241
  { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
4400
4242
  if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
4401
- return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); /* refine parameters based on srcSize & dictSize */
4243
+ /* refine parameters based on srcSize & dictSize */
4244
+ return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize);
4402
4245
  }
4403
4246
  }
4404
4247
 
4248
+ /*! ZSTD_getCParams() :
4249
+ * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
4250
+ * Size values are optional, provide 0 if not known or unused */
4251
+ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
4252
+ {
4253
+ if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
4254
+ return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
4255
+ }
4256
+
4405
4257
  /*! ZSTD_getParams() :
4406
4258
  * same idea as ZSTD_getCParams()
4407
4259
  * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
4408
4260
  * Fields of `ZSTD_frameParameters` are set to default values */
4409
- ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
4261
+ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
4410
4262
  ZSTD_parameters params;
4411
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
4263
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
4412
4264
  DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
4413
4265
  memset(&params, 0, sizeof(params));
4414
4266
  params.cParams = cParams;
4415
4267
  params.fParams.contentSizeFlag = 1;
4416
4268
  return params;
4417
4269
  }
4270
+
4271
+ /*! ZSTD_getParams() :
4272
+ * same idea as ZSTD_getCParams()
4273
+ * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
4274
+ * Fields of `ZSTD_frameParameters` are set to default values */
4275
+ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
4276
+ if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
4277
+ return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize);
4278
+ }