zstd-ruby 1.3.8.0 → 1.4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -5
  3. data/README.md +1 -1
  4. data/ext/zstdruby/libzstd/Makefile +133 -61
  5. data/ext/zstdruby/libzstd/README.md +51 -18
  6. data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
  7. data/ext/zstdruby/libzstd/common/compiler.h +41 -6
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  9. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  10. data/ext/zstdruby/libzstd/common/debug.h +11 -31
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
  12. data/ext/zstdruby/libzstd/common/error_private.c +2 -1
  13. data/ext/zstdruby/libzstd/common/error_private.h +6 -2
  14. data/ext/zstdruby/libzstd/common/fse.h +13 -33
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
  16. data/ext/zstdruby/libzstd/common/huf.h +15 -33
  17. data/ext/zstdruby/libzstd/common/mem.h +75 -2
  18. data/ext/zstdruby/libzstd/common/pool.c +8 -4
  19. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  20. data/ext/zstdruby/libzstd/common/threading.c +52 -6
  21. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  22. data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
  23. data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
  24. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  25. data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
  26. data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
  27. data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
  28. data/ext/zstdruby/libzstd/compress/hist.c +15 -35
  29. data/ext/zstdruby/libzstd/compress/hist.h +12 -32
  30. data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
  31. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
  32. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
  33. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +419 -0
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
  41. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  42. data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
  43. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  44. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
  45. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
  46. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
  47. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
  49. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  50. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
  51. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
  52. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
  53. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
  54. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  55. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
  56. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
  57. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
  58. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
  59. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  60. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  61. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  62. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  63. data/ext/zstdruby/libzstd/dictBuilder/cover.c +220 -65
  64. data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
  65. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
  66. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
  67. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
  68. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  69. data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
  70. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
  71. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
  72. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
  73. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
  74. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
  75. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
  76. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
  77. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
  78. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
  79. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
  80. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
  81. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
  82. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
  83. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
  84. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
  85. data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
  86. data/ext/zstdruby/libzstd/zstd.h +921 -597
  87. data/lib/zstd-ruby/version.rb +1 -1
  88. data/zstd-ruby.gemspec +2 -2
  89. metadata +19 -14
  90. data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
@@ -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,46 +90,72 @@ 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
  }
105
116
 
117
+ /**
118
+ * Clears and frees all of the dictionaries in the CCtx.
119
+ */
120
+ static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
121
+ {
122
+ ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
123
+ ZSTD_freeCDict(cctx->localDict.cdict);
124
+ memset(&cctx->localDict, 0, sizeof(cctx->localDict));
125
+ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
126
+ cctx->cdict = NULL;
127
+ }
128
+
129
+ static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
130
+ {
131
+ size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
132
+ size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
133
+ return bufferSize + cdictSize;
134
+ }
135
+
106
136
  static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
107
137
  {
108
138
  assert(cctx != NULL);
109
139
  assert(cctx->staticSize == 0);
110
- ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
111
- ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
140
+ ZSTD_clearAllDicts(cctx);
112
141
  #ifdef ZSTD_MULTITHREAD
113
142
  ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
114
143
  #endif
144
+ ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);
115
145
  }
116
146
 
117
147
  size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
118
148
  {
119
149
  if (cctx==NULL) return 0; /* support free on NULL */
120
- if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
121
- ZSTD_freeCCtxContent(cctx);
122
- ZSTD_free(cctx, cctx->customMem);
150
+ RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
151
+ "not compatible with static CCtx");
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
+ }
123
159
  return 0;
124
160
  }
125
161
 
@@ -138,8 +174,10 @@ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
138
174
  size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
139
175
  {
140
176
  if (cctx==NULL) return 0; /* support sizeof on NULL */
141
- return sizeof(*cctx) + cctx->workSpaceSize
142
- + ZSTD_sizeof_CDict(cctx->cdictLocal)
177
+ /* cctx may be in the workspace */
178
+ return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))
179
+ + ZSTD_cwksp_sizeof(&cctx->workspace)
180
+ + ZSTD_sizeof_localDict(cctx->localDict)
143
181
  + ZSTD_sizeof_mtctx(cctx);
144
182
  }
145
183
 
@@ -195,7 +233,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
195
233
  }
196
234
 
197
235
  size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
198
- if (!cctxParams) { return ERROR(GENERIC); }
236
+ RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
199
237
  memset(cctxParams, 0, sizeof(*cctxParams));
200
238
  cctxParams->compressionLevel = compressionLevel;
201
239
  cctxParams->fParams.contentSizeFlag = 1;
@@ -204,26 +242,26 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
204
242
 
205
243
  size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
206
244
  {
207
- if (!cctxParams) { return ERROR(GENERIC); }
208
- CHECK_F( ZSTD_checkCParams(params.cParams) );
245
+ RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
246
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
209
247
  memset(cctxParams, 0, sizeof(*cctxParams));
248
+ assert(!ZSTD_checkCParams(params.cParams));
210
249
  cctxParams->cParams = params.cParams;
211
250
  cctxParams->fParams = params.fParams;
212
251
  cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
213
- assert(!ZSTD_checkCParams(params.cParams));
214
252
  return 0;
215
253
  }
216
254
 
217
255
  /* ZSTD_assignParamsToCCtxParams() :
218
256
  * params is presumed valid at this stage */
219
257
  static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
220
- ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
258
+ const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
221
259
  {
222
- ZSTD_CCtx_params ret = cctxParams;
223
- ret.cParams = params.cParams;
224
- 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;
225
264
  ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
226
- assert(!ZSTD_checkCParams(params.cParams));
227
265
  return ret;
228
266
  }
229
267
 
@@ -307,8 +345,13 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
307
345
  return bounds;
308
346
 
309
347
  case ZSTD_c_overlapLog:
348
+ #ifdef ZSTD_MULTITHREAD
310
349
  bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;
311
350
  bounds.upperBound = ZSTD_OVERLAPLOG_MAX;
351
+ #else
352
+ bounds.lowerBound = 0;
353
+ bounds.upperBound = 0;
354
+ #endif
312
355
  return bounds;
313
356
 
314
357
  case ZSTD_c_enableLongDistanceMatching:
@@ -356,32 +399,47 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
356
399
  case ZSTD_c_forceAttachDict:
357
400
  ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy);
358
401
  bounds.lowerBound = ZSTD_dictDefaultAttach;
359
- 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 ? */
403
+ return bounds;
404
+
405
+ case ZSTD_c_literalCompressionMode:
406
+ ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
407
+ bounds.lowerBound = ZSTD_lcm_auto;
408
+ bounds.upperBound = ZSTD_lcm_uncompressed;
409
+ return bounds;
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;
360
419
  return bounds;
361
420
 
362
421
  default:
363
- { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 };
364
- return boundError;
365
- }
422
+ bounds.error = ERROR(parameter_unsupported);
423
+ return bounds;
366
424
  }
367
425
  }
368
426
 
369
- /* ZSTD_cParam_withinBounds:
370
- * @return 1 if value is within cParam bounds,
371
- * 0 otherwise */
372
- static int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
427
+ /* ZSTD_cParam_clampBounds:
428
+ * Clamps the value into the bounded range.
429
+ */
430
+ static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
373
431
  {
374
432
  ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
375
- if (ZSTD_isError(bounds.error)) return 0;
376
- if (value < bounds.lowerBound) return 0;
377
- if (value > bounds.upperBound) return 0;
378
- return 1;
433
+ if (ZSTD_isError(bounds.error)) return bounds.error;
434
+ if (*value < bounds.lowerBound) *value = bounds.lowerBound;
435
+ if (*value > bounds.upperBound) *value = bounds.upperBound;
436
+ return 0;
379
437
  }
380
438
 
381
- #define BOUNDCHECK(cParam, val) { \
382
- if (!ZSTD_cParam_withinBounds(cParam,val)) { \
383
- return ERROR(parameter_outOfBound); \
384
- } }
439
+ #define BOUNDCHECK(cParam, val) { \
440
+ RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
441
+ parameter_outOfBound, "Param out of bounds"); \
442
+ }
385
443
 
386
444
 
387
445
  static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
@@ -413,6 +471,9 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
413
471
  case ZSTD_c_ldmBucketSizeLog:
414
472
  case ZSTD_c_ldmHashRateLog:
415
473
  case ZSTD_c_forceAttachDict:
474
+ case ZSTD_c_literalCompressionMode:
475
+ case ZSTD_c_targetCBlockSize:
476
+ case ZSTD_c_srcSizeHint:
416
477
  default:
417
478
  return 0;
418
479
  }
@@ -425,18 +486,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
425
486
  if (ZSTD_isUpdateAuthorized(param)) {
426
487
  cctx->cParamsChanged = 1;
427
488
  } else {
428
- return ERROR(stage_wrong);
489
+ RETURN_ERROR(stage_wrong, "can only set params in ctx init stage");
429
490
  } }
430
491
 
431
492
  switch(param)
432
493
  {
433
- case ZSTD_c_format :
434
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
494
+ case ZSTD_c_nbWorkers:
495
+ RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
496
+ "MT not compatible with static alloc");
497
+ break;
435
498
 
436
499
  case ZSTD_c_compressionLevel:
437
- if (cctx->cdict) return ERROR(stage_wrong);
438
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
439
-
440
500
  case ZSTD_c_windowLog:
441
501
  case ZSTD_c_hashLog:
442
502
  case ZSTD_c_chainLog:
@@ -444,49 +504,34 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
444
504
  case ZSTD_c_minMatch:
445
505
  case ZSTD_c_targetLength:
446
506
  case ZSTD_c_strategy:
447
- if (cctx->cdict) return ERROR(stage_wrong);
448
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
449
-
507
+ case ZSTD_c_ldmHashRateLog:
508
+ case ZSTD_c_format:
450
509
  case ZSTD_c_contentSizeFlag:
451
510
  case ZSTD_c_checksumFlag:
452
511
  case ZSTD_c_dictIDFlag:
453
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
454
-
455
- case ZSTD_c_forceMaxWindow : /* Force back-references to remain < windowSize,
456
- * even when referencing into Dictionary content.
457
- * default : 0 when using a CDict, 1 when using a Prefix */
458
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
459
-
512
+ case ZSTD_c_forceMaxWindow:
460
513
  case ZSTD_c_forceAttachDict:
461
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
462
-
463
- case ZSTD_c_nbWorkers:
464
- if ((value!=0) && cctx->staticSize) {
465
- return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
466
- }
467
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
468
-
514
+ case ZSTD_c_literalCompressionMode:
469
515
  case ZSTD_c_jobSize:
470
516
  case ZSTD_c_overlapLog:
471
517
  case ZSTD_c_rsyncable:
472
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
473
-
474
518
  case ZSTD_c_enableLongDistanceMatching:
475
519
  case ZSTD_c_ldmHashLog:
476
520
  case ZSTD_c_ldmMinMatch:
477
521
  case ZSTD_c_ldmBucketSizeLog:
478
- case ZSTD_c_ldmHashRateLog:
479
- if (cctx->cdict) return ERROR(stage_wrong);
480
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
522
+ case ZSTD_c_targetCBlockSize:
523
+ case ZSTD_c_srcSizeHint:
524
+ break;
481
525
 
482
- default: return ERROR(parameter_unsupported);
526
+ default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
483
527
  }
528
+ return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
484
529
  }
485
530
 
486
- size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
487
- ZSTD_cParameter param, int value)
531
+ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
532
+ ZSTD_cParameter param, int value)
488
533
  {
489
- DEBUGLOG(4, "ZSTD_CCtxParam_setParameter (%i, %i)", (int)param, value);
534
+ DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
490
535
  switch(param)
491
536
  {
492
537
  case ZSTD_c_format :
@@ -495,39 +540,37 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
495
540
  return (size_t)CCtxParams->format;
496
541
 
497
542
  case ZSTD_c_compressionLevel : {
498
- int cLevel = value;
499
- if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
500
- if (cLevel < ZSTD_minCLevel()) cLevel = ZSTD_minCLevel();
501
- if (cLevel) { /* 0 : does not change current level */
502
- CCtxParams->compressionLevel = cLevel;
543
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
544
+ if (value) { /* 0 : does not change current level */
545
+ CCtxParams->compressionLevel = value;
503
546
  }
504
- if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
547
+ if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
505
548
  return 0; /* return type (size_t) cannot represent negative values */
506
549
  }
507
550
 
508
551
  case ZSTD_c_windowLog :
509
552
  if (value!=0) /* 0 => use default */
510
553
  BOUNDCHECK(ZSTD_c_windowLog, value);
511
- CCtxParams->cParams.windowLog = value;
554
+ CCtxParams->cParams.windowLog = (U32)value;
512
555
  return CCtxParams->cParams.windowLog;
513
556
 
514
557
  case ZSTD_c_hashLog :
515
558
  if (value!=0) /* 0 => use default */
516
559
  BOUNDCHECK(ZSTD_c_hashLog, value);
517
- CCtxParams->cParams.hashLog = value;
560
+ CCtxParams->cParams.hashLog = (U32)value;
518
561
  return CCtxParams->cParams.hashLog;
519
562
 
520
563
  case ZSTD_c_chainLog :
521
564
  if (value!=0) /* 0 => use default */
522
565
  BOUNDCHECK(ZSTD_c_chainLog, value);
523
- CCtxParams->cParams.chainLog = value;
566
+ CCtxParams->cParams.chainLog = (U32)value;
524
567
  return CCtxParams->cParams.chainLog;
525
568
 
526
569
  case ZSTD_c_searchLog :
527
570
  if (value!=0) /* 0 => use default */
528
571
  BOUNDCHECK(ZSTD_c_searchLog, value);
529
- CCtxParams->cParams.searchLog = value;
530
- return value;
572
+ CCtxParams->cParams.searchLog = (U32)value;
573
+ return (size_t)value;
531
574
 
532
575
  case ZSTD_c_minMatch :
533
576
  if (value!=0) /* 0 => use default */
@@ -573,33 +616,55 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
573
616
  return CCtxParams->attachDictPref;
574
617
  }
575
618
 
619
+ case ZSTD_c_literalCompressionMode : {
620
+ const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
621
+ BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
622
+ CCtxParams->literalCompressionMode = lcm;
623
+ return CCtxParams->literalCompressionMode;
624
+ }
625
+
576
626
  case ZSTD_c_nbWorkers :
577
627
  #ifndef ZSTD_MULTITHREAD
578
- if (value!=0) return ERROR(parameter_unsupported);
628
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
579
629
  return 0;
580
630
  #else
581
- return ZSTDMT_CCtxParam_setNbWorkers(CCtxParams, value);
631
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
632
+ CCtxParams->nbWorkers = value;
633
+ return CCtxParams->nbWorkers;
582
634
  #endif
583
635
 
584
636
  case ZSTD_c_jobSize :
585
637
  #ifndef ZSTD_MULTITHREAD
586
- return ERROR(parameter_unsupported);
638
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
639
+ return 0;
587
640
  #else
588
- return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value);
641
+ /* Adjust to the minimum non-default value. */
642
+ if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
643
+ value = ZSTDMT_JOBSIZE_MIN;
644
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
645
+ assert(value >= 0);
646
+ CCtxParams->jobSize = value;
647
+ return CCtxParams->jobSize;
589
648
  #endif
590
649
 
591
650
  case ZSTD_c_overlapLog :
592
651
  #ifndef ZSTD_MULTITHREAD
593
- return ERROR(parameter_unsupported);
652
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
653
+ return 0;
594
654
  #else
595
- return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapLog, value);
655
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
656
+ CCtxParams->overlapLog = value;
657
+ return CCtxParams->overlapLog;
596
658
  #endif
597
659
 
598
660
  case ZSTD_c_rsyncable :
599
661
  #ifndef ZSTD_MULTITHREAD
600
- return ERROR(parameter_unsupported);
662
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
663
+ return 0;
601
664
  #else
602
- return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_rsyncable, value);
665
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
666
+ CCtxParams->rsyncable = value;
667
+ return CCtxParams->rsyncable;
603
668
  #endif
604
669
 
605
670
  case ZSTD_c_enableLongDistanceMatching :
@@ -625,21 +690,33 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
625
690
  return CCtxParams->ldmParams.bucketSizeLog;
626
691
 
627
692
  case ZSTD_c_ldmHashRateLog :
628
- if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
629
- return ERROR(parameter_outOfBound);
693
+ RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
694
+ parameter_outOfBound, "Param out of bounds!");
630
695
  CCtxParams->ldmParams.hashRateLog = value;
631
696
  return CCtxParams->ldmParams.hashRateLog;
632
697
 
633
- default: return ERROR(parameter_unsupported);
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
+
710
+ default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
634
711
  }
635
712
  }
636
713
 
637
714
  size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
638
715
  {
639
- return ZSTD_CCtxParam_getParameter(&cctx->requestedParams, param, value);
716
+ return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
640
717
  }
641
718
 
642
- size_t ZSTD_CCtxParam_getParameter(
719
+ size_t ZSTD_CCtxParams_getParameter(
643
720
  ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
644
721
  {
645
722
  switch(param)
@@ -651,13 +728,13 @@ size_t ZSTD_CCtxParam_getParameter(
651
728
  *value = CCtxParams->compressionLevel;
652
729
  break;
653
730
  case ZSTD_c_windowLog :
654
- *value = CCtxParams->cParams.windowLog;
731
+ *value = (int)CCtxParams->cParams.windowLog;
655
732
  break;
656
733
  case ZSTD_c_hashLog :
657
- *value = CCtxParams->cParams.hashLog;
734
+ *value = (int)CCtxParams->cParams.hashLog;
658
735
  break;
659
736
  case ZSTD_c_chainLog :
660
- *value = CCtxParams->cParams.chainLog;
737
+ *value = (int)CCtxParams->cParams.chainLog;
661
738
  break;
662
739
  case ZSTD_c_searchLog :
663
740
  *value = CCtxParams->cParams.searchLog;
@@ -686,6 +763,9 @@ size_t ZSTD_CCtxParam_getParameter(
686
763
  case ZSTD_c_forceAttachDict :
687
764
  *value = CCtxParams->attachDictPref;
688
765
  break;
766
+ case ZSTD_c_literalCompressionMode :
767
+ *value = CCtxParams->literalCompressionMode;
768
+ break;
689
769
  case ZSTD_c_nbWorkers :
690
770
  #ifndef ZSTD_MULTITHREAD
691
771
  assert(CCtxParams->nbWorkers == 0);
@@ -694,7 +774,7 @@ size_t ZSTD_CCtxParam_getParameter(
694
774
  break;
695
775
  case ZSTD_c_jobSize :
696
776
  #ifndef ZSTD_MULTITHREAD
697
- return ERROR(parameter_unsupported);
777
+ RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
698
778
  #else
699
779
  assert(CCtxParams->jobSize <= INT_MAX);
700
780
  *value = (int)CCtxParams->jobSize;
@@ -702,14 +782,14 @@ size_t ZSTD_CCtxParam_getParameter(
702
782
  #endif
703
783
  case ZSTD_c_overlapLog :
704
784
  #ifndef ZSTD_MULTITHREAD
705
- return ERROR(parameter_unsupported);
785
+ RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
706
786
  #else
707
787
  *value = CCtxParams->overlapLog;
708
788
  break;
709
789
  #endif
710
790
  case ZSTD_c_rsyncable :
711
791
  #ifndef ZSTD_MULTITHREAD
712
- return ERROR(parameter_unsupported);
792
+ RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
713
793
  #else
714
794
  *value = CCtxParams->rsyncable;
715
795
  break;
@@ -729,7 +809,13 @@ size_t ZSTD_CCtxParam_getParameter(
729
809
  case ZSTD_c_ldmHashRateLog :
730
810
  *value = CCtxParams->ldmParams.hashRateLog;
731
811
  break;
732
- default: return ERROR(parameter_unsupported);
812
+ case ZSTD_c_targetCBlockSize :
813
+ *value = (int)CCtxParams->targetCBlockSize;
814
+ break;
815
+ case ZSTD_c_srcSizeHint :
816
+ *value = (int)CCtxParams->srcSizeHint;
817
+ break;
818
+ default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
733
819
  }
734
820
  return 0;
735
821
  }
@@ -745,8 +831,11 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
745
831
  ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
746
832
  {
747
833
  DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
748
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
749
- if (cctx->cdict) return ERROR(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).");
750
839
 
751
840
  cctx->requestedParams = *params;
752
841
  return 0;
@@ -755,33 +844,73 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
755
844
  ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
756
845
  {
757
846
  DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
758
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
847
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
848
+ "Can't set pledgedSrcSize when not in init stage.");
759
849
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
760
850
  return 0;
761
851
  }
762
852
 
853
+ /**
854
+ * Initializes the local dict using the requested parameters.
855
+ * NOTE: This does not use the pledged src size, because it may be used for more
856
+ * than one compression.
857
+ */
858
+ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
859
+ {
860
+ ZSTD_localDict* const dl = &cctx->localDict;
861
+ ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
862
+ &cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize);
863
+ if (dl->dict == NULL) {
864
+ /* No local dictionary. */
865
+ assert(dl->dictBuffer == NULL);
866
+ assert(dl->cdict == NULL);
867
+ assert(dl->dictSize == 0);
868
+ return 0;
869
+ }
870
+ if (dl->cdict != NULL) {
871
+ assert(cctx->cdict == dl->cdict);
872
+ /* Local dictionary already initialized. */
873
+ return 0;
874
+ }
875
+ assert(dl->dictSize > 0);
876
+ assert(cctx->cdict == NULL);
877
+ assert(cctx->prefixDict.dict == NULL);
878
+
879
+ dl->cdict = ZSTD_createCDict_advanced(
880
+ dl->dict,
881
+ dl->dictSize,
882
+ ZSTD_dlm_byRef,
883
+ dl->dictContentType,
884
+ cParams,
885
+ cctx->customMem);
886
+ RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
887
+ cctx->cdict = dl->cdict;
888
+ return 0;
889
+ }
890
+
763
891
  size_t ZSTD_CCtx_loadDictionary_advanced(
764
892
  ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
765
893
  ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
766
894
  {
767
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
768
- if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
895
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
896
+ "Can't load a dictionary when ctx is not in init stage.");
897
+ RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
898
+ "no malloc for static CCtx");
769
899
  DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
770
- ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
771
- if (dict==NULL || dictSize==0) { /* no dictionary mode */
772
- cctx->cdictLocal = NULL;
773
- cctx->cdict = NULL;
900
+ ZSTD_clearAllDicts(cctx); /* in case one already exists */
901
+ if (dict == NULL || dictSize == 0) /* no dictionary mode */
902
+ return 0;
903
+ if (dictLoadMethod == ZSTD_dlm_byRef) {
904
+ cctx->localDict.dict = dict;
774
905
  } else {
775
- ZSTD_compressionParameters const cParams =
776
- ZSTD_getCParamsFromCCtxParams(&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
777
- cctx->cdictLocal = ZSTD_createCDict_advanced(
778
- dict, dictSize,
779
- dictLoadMethod, dictContentType,
780
- cParams, cctx->customMem);
781
- cctx->cdict = cctx->cdictLocal;
782
- if (cctx->cdictLocal == NULL)
783
- return ERROR(memory_allocation);
906
+ void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
907
+ RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
908
+ memcpy(dictBuffer, dict, dictSize);
909
+ cctx->localDict.dictBuffer = dictBuffer;
910
+ cctx->localDict.dict = dictBuffer;
784
911
  }
912
+ cctx->localDict.dictSize = dictSize;
913
+ cctx->localDict.dictContentType = dictContentType;
785
914
  return 0;
786
915
  }
787
916
 
@@ -801,9 +930,11 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
801
930
 
802
931
  size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
803
932
  {
804
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
933
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
934
+ "Can't ref a dict when ctx not in init stage.");
935
+ /* Free the existing local cdict (if any) to save memory. */
936
+ ZSTD_clearAllDicts(cctx);
805
937
  cctx->cdict = cdict;
806
- memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
807
938
  return 0;
808
939
  }
809
940
 
@@ -815,11 +946,14 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz
815
946
  size_t ZSTD_CCtx_refPrefix_advanced(
816
947
  ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
817
948
  {
818
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
819
- cctx->cdict = NULL; /* prefix discards any prior cdict */
820
- cctx->prefixDict.dict = prefix;
821
- cctx->prefixDict.dictSize = prefixSize;
822
- cctx->prefixDict.dictContentType = dictContentType;
949
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
950
+ "Can't ref a prefix when ctx not in init stage.");
951
+ ZSTD_clearAllDicts(cctx);
952
+ if (prefix != NULL && prefixSize > 0) {
953
+ cctx->prefixDict.dict = prefix;
954
+ cctx->prefixDict.dictSize = prefixSize;
955
+ cctx->prefixDict.dictContentType = dictContentType;
956
+ }
823
957
  return 0;
824
958
  }
825
959
 
@@ -834,8 +968,9 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
834
968
  }
835
969
  if ( (reset == ZSTD_reset_parameters)
836
970
  || (reset == ZSTD_reset_session_and_parameters) ) {
837
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
838
- cctx->cdict = NULL;
971
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
972
+ "Can't reset parameters only when not in init stage.");
973
+ ZSTD_clearAllDicts(cctx);
839
974
  return ZSTD_CCtxParams_reset(&cctx->requestedParams);
840
975
  }
841
976
  return 0;
@@ -847,12 +982,12 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
847
982
  @return : 0, or an error code if one value is beyond authorized range */
848
983
  size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
849
984
  {
850
- BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog);
851
- BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog);
852
- BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog);
853
- BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog);
854
- BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch);
855
- 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);
856
991
  BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
857
992
  return 0;
858
993
  }
@@ -868,7 +1003,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
868
1003
  if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
869
1004
  else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
870
1005
  }
871
- # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, int)
1006
+ # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
872
1007
  CLAMP(ZSTD_c_windowLog, cParams.windowLog);
873
1008
  CLAMP(ZSTD_c_chainLog, cParams.chainLog);
874
1009
  CLAMP(ZSTD_c_hashLog, cParams.hashLog);
@@ -881,17 +1016,18 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
881
1016
 
882
1017
  /** ZSTD_cycleLog() :
883
1018
  * condition for correct operation : hashLog > 1 */
884
- static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
1019
+ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
885
1020
  {
886
1021
  U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
887
1022
  return hashLog - btScale;
888
1023
  }
889
1024
 
890
1025
  /** ZSTD_adjustCParams_internal() :
891
- optimize `cPar` for a given input (`srcSize` and `dictSize`).
892
- mostly downsizing to reduce memory consumption and initialization latency.
893
- Both `srcSize` and `dictSize` are optional (use 0 if unknown).
894
- Note : cPar is assumed validated. Use ZSTD_checkCParams() to ensure this condition. */
1026
+ * optimize `cPar` for a specified input (`srcSize` and `dictSize`).
1027
+ * mostly downsize to reduce memory consumption and initialization latency.
1028
+ * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
1029
+ * note : `srcSize==0` means 0!
1030
+ * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
895
1031
  static ZSTD_compressionParameters
896
1032
  ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
897
1033
  unsigned long long srcSize,
@@ -901,10 +1037,8 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
901
1037
  static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
902
1038
  assert(ZSTD_checkCParams(cPar)==0);
903
1039
 
904
- if (dictSize && (srcSize+1<2) /* srcSize unknown */ )
905
- srcSize = minSrcSize; /* presumed small when there is a dictionary */
906
- else if (srcSize == 0)
907
- srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
1040
+ if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
1041
+ srcSize = minSrcSize;
908
1042
 
909
1043
  /* resize windowLog if input is small enough, to use less memory */
910
1044
  if ( (srcSize < maxWindowResize)
@@ -922,7 +1056,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
922
1056
  }
923
1057
 
924
1058
  if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
925
- cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
1059
+ cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */
926
1060
 
927
1061
  return cPar;
928
1062
  }
@@ -932,14 +1066,22 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
932
1066
  unsigned long long srcSize,
933
1067
  size_t dictSize)
934
1068
  {
935
- cPar = ZSTD_clampCParams(cPar);
1069
+ cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
1070
+ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
936
1071
  return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
937
1072
  }
938
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
+
939
1077
  ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
940
1078
  const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
941
1079
  {
942
- 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);
943
1085
  if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
944
1086
  if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
945
1087
  if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
@@ -949,6 +1091,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
949
1091
  if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
950
1092
  if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
951
1093
  assert(!ZSTD_checkCParams(cParams));
1094
+ /* srcSizeHint == 0 means 0 */
952
1095
  return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
953
1096
  }
954
1097
 
@@ -959,10 +1102,19 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
959
1102
  size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
960
1103
  size_t const hSize = ((size_t)1) << cParams->hashLog;
961
1104
  U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
962
- size_t const h3Size = ((size_t)1) << hashLog3;
963
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
964
- size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
965
- + (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));
966
1118
  size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
967
1119
  ? optPotentialSpace
968
1120
  : 0;
@@ -973,27 +1125,42 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
973
1125
 
974
1126
  size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
975
1127
  {
976
- /* Estimate CCtx size is supported for single-threaded compression only. */
977
- if (params->nbWorkers > 0) { return ERROR(GENERIC); }
1128
+ RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
978
1129
  { ZSTD_compressionParameters const cParams =
979
- ZSTD_getCParamsFromCCtxParams(params, 0, 0);
1130
+ ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
980
1131
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
981
1132
  U32 const divider = (cParams.minMatch==3) ? 3 : 4;
982
1133
  size_t const maxNbSeq = blockSize / divider;
983
- size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
984
- size_t const entropySpace = HUF_WORKSPACE_SIZE;
985
- 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));
986
1139
  size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
987
1140
 
988
1141
  size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
989
- size_t const ldmSeqSpace = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq);
990
-
991
- size_t const neededSpace = entropySpace + blockStateSpace + tokenSpace +
992
- matchStateSize + ldmSpace + ldmSeqSpace;
993
-
994
- DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
995
- DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
996
- 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;
997
1164
  }
998
1165
  }
999
1166
 
@@ -1005,7 +1172,7 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
1005
1172
 
1006
1173
  static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
1007
1174
  {
1008
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
1175
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1009
1176
  return ZSTD_estimateCCtxSize_usingCParams(cParams);
1010
1177
  }
1011
1178
 
@@ -1022,12 +1189,15 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel)
1022
1189
 
1023
1190
  size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1024
1191
  {
1025
- if (params->nbWorkers > 0) { return ERROR(GENERIC); }
1026
- { size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
1027
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
1028
- size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
1192
+ RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
1193
+ { ZSTD_compressionParameters const cParams =
1194
+ ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1195
+ size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
1196
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
1197
+ size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
1029
1198
  size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
1030
- size_t const streamingSize = inBuffSize + outBuffSize;
1199
+ size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize)
1200
+ + ZSTD_cwksp_alloc_size(outBuffSize);
1031
1201
 
1032
1202
  return CCtxSize + streamingSize;
1033
1203
  }
@@ -1041,7 +1211,7 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
1041
1211
 
1042
1212
  static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
1043
1213
  {
1044
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
1214
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1045
1215
  return ZSTD_estimateCStreamSize_usingCParams(cParams);
1046
1216
  }
1047
1217
 
@@ -1095,17 +1265,6 @@ size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
1095
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 */
1096
1266
  }
1097
1267
 
1098
-
1099
-
1100
- static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
1101
- ZSTD_compressionParameters cParams2)
1102
- {
1103
- return (cParams1.hashLog == cParams2.hashLog)
1104
- & (cParams1.chainLog == cParams2.chainLog)
1105
- & (cParams1.strategy == cParams2.strategy) /* opt parser space */
1106
- & ((cParams1.minMatch==3) == (cParams2.minMatch==3)); /* hashlog3 space */
1107
- }
1108
-
1109
1268
  static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
1110
1269
  ZSTD_compressionParameters cParams2)
1111
1270
  {
@@ -1120,72 +1279,7 @@ static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
1120
1279
  assert(cParams1.strategy == cParams2.strategy);
1121
1280
  }
1122
1281
 
1123
- /** The parameters are equivalent if ldm is not enabled in both sets or
1124
- * all the parameters are equivalent. */
1125
- static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
1126
- ldmParams_t ldmParams2)
1127
- {
1128
- return (!ldmParams1.enableLdm && !ldmParams2.enableLdm) ||
1129
- (ldmParams1.enableLdm == ldmParams2.enableLdm &&
1130
- ldmParams1.hashLog == ldmParams2.hashLog &&
1131
- ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
1132
- ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
1133
- ldmParams1.hashRateLog == ldmParams2.hashRateLog);
1134
- }
1135
-
1136
- typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
1137
-
1138
- /* ZSTD_sufficientBuff() :
1139
- * check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
1140
- * Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
1141
- static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t maxNbSeq1,
1142
- size_t maxNbLit1,
1143
- ZSTD_buffered_policy_e buffPol2,
1144
- ZSTD_compressionParameters cParams2,
1145
- U64 pledgedSrcSize)
1146
- {
1147
- size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
1148
- size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
1149
- size_t const maxNbSeq2 = blockSize2 / ((cParams2.minMatch == 3) ? 3 : 4);
1150
- size_t const maxNbLit2 = blockSize2;
1151
- size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
1152
- DEBUGLOG(4, "ZSTD_sufficientBuff: is neededBufferSize2=%u <= bufferSize1=%u",
1153
- (U32)neededBufferSize2, (U32)bufferSize1);
1154
- DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbSeq2=%u <= maxNbSeq1=%u",
1155
- (U32)maxNbSeq2, (U32)maxNbSeq1);
1156
- DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbLit2=%u <= maxNbLit1=%u",
1157
- (U32)maxNbLit2, (U32)maxNbLit1);
1158
- return (maxNbLit2 <= maxNbLit1)
1159
- & (maxNbSeq2 <= maxNbSeq1)
1160
- & (neededBufferSize2 <= bufferSize1);
1161
- }
1162
-
1163
- /** Equivalence for resetCCtx purposes */
1164
- static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
1165
- ZSTD_CCtx_params params2,
1166
- size_t buffSize1,
1167
- size_t maxNbSeq1, size_t maxNbLit1,
1168
- ZSTD_buffered_policy_e buffPol2,
1169
- U64 pledgedSrcSize)
1170
- {
1171
- DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
1172
- if (!ZSTD_equivalentCParams(params1.cParams, params2.cParams)) {
1173
- DEBUGLOG(4, "ZSTD_equivalentCParams() == 0");
1174
- return 0;
1175
- }
1176
- if (!ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams)) {
1177
- DEBUGLOG(4, "ZSTD_equivalentLdmParams() == 0");
1178
- return 0;
1179
- }
1180
- if (!ZSTD_sufficientBuff(buffSize1, maxNbSeq1, maxNbLit1, buffPol2,
1181
- params2.cParams, pledgedSrcSize)) {
1182
- DEBUGLOG(4, "ZSTD_sufficientBuff() == 0");
1183
- return 0;
1184
- }
1185
- return 1;
1186
- }
1187
-
1188
- static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
1282
+ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
1189
1283
  {
1190
1284
  int i;
1191
1285
  for (i = 0; i < ZSTD_REP_NUM; ++i)
@@ -1197,132 +1291,143 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
1197
1291
  }
1198
1292
 
1199
1293
  /*! ZSTD_invalidateMatchState()
1200
- * Invalidate all the matches in the match finder tables.
1201
- * 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).
1202
1296
  */
1203
1297
  static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
1204
1298
  {
1205
1299
  ZSTD_window_clear(&ms->window);
1206
1300
 
1207
1301
  ms->nextToUpdate = ms->window.dictLimit;
1208
- ms->nextToUpdate3 = ms->window.dictLimit;
1209
1302
  ms->loadedDictEnd = 0;
1210
1303
  ms->opt.litLengthSum = 0; /* force reset of btopt stats */
1211
1304
  ms->dictMatchState = NULL;
1212
1305
  }
1213
1306
 
1214
- /*! ZSTD_continueCCtx() :
1215
- * reuse CCtx without reset (note : requires no dictionary) */
1216
- static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
1217
- {
1218
- size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
1219
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
1220
- 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;
1221
1316
 
1222
- cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
1223
- cctx->appliedParams = params;
1224
- cctx->blockState.matchState.cParams = params.cParams;
1225
- cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
1226
- cctx->consumedSrcSize = 0;
1227
- cctx->producedCSize = 0;
1228
- if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
1229
- cctx->appliedParams.fParams.contentSizeFlag = 0;
1230
- DEBUGLOG(4, "pledged content size : %u ; flag : %u",
1231
- (U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
1232
- cctx->stage = ZSTDcs_init;
1233
- cctx->dictID = 0;
1234
- if (params.ldmParams.enableLdm)
1235
- ZSTD_window_clear(&cctx->ldmState.window);
1236
- ZSTD_referenceExternalSequences(cctx, NULL, 0);
1237
- ZSTD_invalidateMatchState(&cctx->blockState.matchState);
1238
- ZSTD_reset_compressedBlockState(cctx->blockState.prevCBlock);
1239
- XXH64_reset(&cctx->xxhState, 0);
1240
- return 0;
1241
- }
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;
1328
+
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;
1242
1338
 
1243
- typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
1339
+ typedef enum {
1340
+ ZSTD_resetTarget_CDict,
1341
+ ZSTD_resetTarget_CCtx
1342
+ } ZSTD_resetTarget_e;
1244
1343
 
1245
- static void*
1344
+ static size_t
1246
1345
  ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1247
- void* ptr,
1346
+ ZSTD_cwksp* ws,
1248
1347
  const ZSTD_compressionParameters* cParams,
1249
- 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)
1250
1351
  {
1251
1352
  size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
1252
1353
  size_t const hSize = ((size_t)1) << cParams->hashLog;
1253
- U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
1254
- size_t const h3Size = ((size_t)1) << hashLog3;
1255
- 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;
1256
1356
 
1257
- 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
+ }
1258
1362
 
1259
1363
  ms->hashLog3 = hashLog3;
1260
- memset(&ms->window, 0, sizeof(ms->window));
1261
- ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */
1262
- ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
1263
- ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
1364
+
1264
1365
  ZSTD_invalidateMatchState(ms);
1265
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
+
1266
1385
  /* opt parser space */
1267
- if (forCCtx && (cParams->strategy >= ZSTD_btopt)) {
1386
+ if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
1268
1387
  DEBUGLOG(4, "reserving optimal parser space");
1269
- ms->opt.litFreq = (unsigned*)ptr;
1270
- ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits);
1271
- ms->opt.matchLengthFreq = ms->opt.litLengthFreq + (MaxLL+1);
1272
- ms->opt.offCodeFreq = ms->opt.matchLengthFreq + (MaxML+1);
1273
- ptr = ms->opt.offCodeFreq + (MaxOff+1);
1274
- ms->opt.matchTable = (ZSTD_match_t*)ptr;
1275
- ptr = ms->opt.matchTable + ZSTD_OPT_NUM+1;
1276
- ms->opt.priceTable = (ZSTD_optimal_t*)ptr;
1277
- 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));
1278
1394
  }
1279
1395
 
1280
- /* table Space */
1281
- DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
1282
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1283
- if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
1284
- ms->hashTable = (U32*)(ptr);
1285
- ms->chainTable = ms->hashTable + hSize;
1286
- ms->hashTable3 = ms->chainTable + chainSize;
1287
- ptr = ms->hashTable3 + h3Size;
1288
-
1289
1396
  ms->cParams = *cParams;
1290
1397
 
1291
- assert(((size_t)ptr & 3) == 0);
1292
- 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;
1293
1402
  }
1294
1403
 
1295
- #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */
1296
- #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large
1297
- * during at least this number of times,
1298
- * context's memory usage is considered wasteful,
1299
- * because it's sized to handle a worst case scenario which rarely happens.
1300
- * 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
+ }
1301
1416
 
1302
1417
  /*! ZSTD_resetCCtx_internal() :
1303
1418
  note : `params` are assumed fully validated at this stage */
1304
1419
  static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1305
1420
  ZSTD_CCtx_params params,
1306
- U64 pledgedSrcSize,
1421
+ U64 const pledgedSrcSize,
1307
1422
  ZSTD_compResetPolicy_e const crp,
1308
1423
  ZSTD_buffered_policy_e const zbuff)
1309
1424
  {
1425
+ ZSTD_cwksp* const ws = &zc->workspace;
1310
1426
  DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
1311
1427
  (U32)pledgedSrcSize, params.cParams.windowLog);
1312
1428
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
1313
1429
 
1314
- if (crp == ZSTDcrp_continue) {
1315
- if (ZSTD_equivalentParams(zc->appliedParams, params,
1316
- zc->inBuffSize,
1317
- zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
1318
- zbuff, pledgedSrcSize)) {
1319
- DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
1320
- zc->appliedParams.cParams.windowLog, zc->blockSize);
1321
- zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
1322
- if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
1323
- return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
1324
- } }
1325
- DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
1430
+ zc->isFirstBlock = 1;
1326
1431
 
1327
1432
  if (params.ldmParams.enableLdm) {
1328
1433
  /* Adjust long distance matching parameters */
@@ -1336,58 +1441,74 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1336
1441
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
1337
1442
  U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
1338
1443
  size_t const maxNbSeq = blockSize / divider;
1339
- 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));
1340
1447
  size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
1341
1448
  size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
1342
1449
  size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
1343
1450
  size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
1344
- void* ptr; /* used to partition workSpace */
1345
1451
 
1346
- /* Check if workSpace is large enough, alloc a new one if needed */
1347
- { size_t const entropySpace = HUF_WORKSPACE_SIZE;
1348
- size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
1349
- 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);
1350
1465
  size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
1351
- size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq);
1466
+ size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq));
1352
1467
 
1353
- size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
1354
- ldmSeqSpace + matchStateSize + tokenSpace +
1355
- bufferSpace;
1468
+ size_t const neededSpace =
1469
+ cctxSpace +
1470
+ entropySpace +
1471
+ blockStateSpace +
1472
+ ldmSpace +
1473
+ ldmSeqSpace +
1474
+ matchStateSize +
1475
+ tokenSpace +
1476
+ bufferSpace;
1356
1477
 
1357
- int const workSpaceTooSmall = zc->workSpaceSize < neededSpace;
1358
- int const workSpaceTooLarge = zc->workSpaceSize > ZSTD_WORKSPACETOOLARGE_FACTOR * neededSpace;
1359
- int const workSpaceWasteful = workSpaceTooLarge && (zc->workSpaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION);
1360
- 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);
1361
1480
 
1362
1481
  DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
1363
1482
  neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
1364
1483
  DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
1365
1484
 
1366
- if (workSpaceTooSmall || workSpaceWasteful) {
1367
- DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB",
1368
- zc->workSpaceSize >> 10,
1485
+ if (workspaceTooSmall || workspaceWasteful) {
1486
+ DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
1487
+ ZSTD_cwksp_sizeof(ws) >> 10,
1369
1488
  neededSpace >> 10);
1370
- /* static cctx : no resize, error out */
1371
- if (zc->staticSize) return ERROR(memory_allocation);
1372
1489
 
1373
- zc->workSpaceSize = 0;
1374
- ZSTD_free(zc->workSpace, zc->customMem);
1375
- zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
1376
- if (zc->workSpace == NULL) return ERROR(memory_allocation);
1377
- zc->workSpaceSize = neededSpace;
1378
- zc->workSpaceOversizedDuration = 0;
1490
+ RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
1379
1491
 
1492
+ needsIndexReset = ZSTDirp_reset;
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");
1380
1498
  /* Statically sized space.
1381
1499
  * entropyWorkspace never moves,
1382
1500
  * though prev/next block swap places */
1383
- assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */
1384
- assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t));
1385
- zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace;
1386
- zc->blockState.nextCBlock = zc->blockState.prevCBlock + 1;
1387
- ptr = zc->blockState.nextCBlock + 1;
1388
- 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");
1389
1508
  } }
1390
1509
 
1510
+ ZSTD_cwksp_clear(ws);
1511
+
1391
1512
  /* init params */
1392
1513
  zc->appliedParams = params;
1393
1514
  zc->blockState.matchState.cParams = params.cParams;
@@ -1406,57 +1527,60 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1406
1527
 
1407
1528
  ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
1408
1529
 
1409
- ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32;
1410
-
1411
- /* ldm hash table */
1412
- /* initialize bucketOffsets table later for pointer alignment */
1413
- if (params.ldmParams.enableLdm) {
1414
- size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
1415
- memset(ptr, 0, ldmHSize * sizeof(ldmEntry_t));
1416
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1417
- zc->ldmState.hashTable = (ldmEntry_t*)ptr;
1418
- ptr = zc->ldmState.hashTable + ldmHSize;
1419
- zc->ldmSequences = (rawSeq*)ptr;
1420
- ptr = zc->ldmSequences + maxNbLdmSeq;
1421
- zc->maxNbLdmSequences = maxNbLdmSeq;
1422
-
1423
- memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window));
1424
- }
1425
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
1426
-
1427
- ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
1428
-
1429
- /* sequences storage */
1430
- zc->seqStore.maxNbSeq = maxNbSeq;
1431
- zc->seqStore.sequencesStart = (seqDef*)ptr;
1432
- ptr = zc->seqStore.sequencesStart + maxNbSeq;
1433
- zc->seqStore.llCode = (BYTE*) ptr;
1434
- zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
1435
- zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
1436
- zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
1437
1530
  /* ZSTD_wildcopy() is used to copy into the literals buffer,
1438
1531
  * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
1439
1532
  */
1533
+ zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);
1440
1534
  zc->seqStore.maxNbLit = blockSize;
1441
- 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);
1442
1541
 
1443
1542
  /* ldm bucketOffsets table */
1444
1543
  if (params.ldmParams.enableLdm) {
1544
+ /* TODO: avoid memset? */
1445
1545
  size_t const ldmBucketSize =
1446
1546
  ((size_t)1) << (params.ldmParams.hashLog -
1447
1547
  params.ldmParams.bucketSizeLog);
1448
- memset(ptr, 0, ldmBucketSize);
1449
- zc->ldmState.bucketOffsets = (BYTE*)ptr;
1450
- ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
1451
- ZSTD_window_clear(&zc->ldmState.window);
1548
+ zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize);
1549
+ memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize);
1452
1550
  }
1551
+
1552
+ /* sequences storage */
1453
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), "");
1454
1567
 
1455
- /* buffers */
1456
- zc->inBuffSize = buffInSize;
1457
- zc->inBuff = (char*)ptr;
1458
- zc->outBuffSize = buffOutSize;
1459
- 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;
1460
1584
 
1461
1585
  return 0;
1462
1586
  }
@@ -1490,40 +1614,39 @@ static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {
1490
1614
  };
1491
1615
 
1492
1616
  static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
1493
- ZSTD_CCtx_params params,
1617
+ const ZSTD_CCtx_params* params,
1494
1618
  U64 pledgedSrcSize)
1495
1619
  {
1496
1620
  size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
1497
1621
  return ( pledgedSrcSize <= cutoff
1498
1622
  || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
1499
- || params.attachDictPref == ZSTD_dictForceAttach )
1500
- && params.attachDictPref != ZSTD_dictForceCopy
1501
- && !params.forceWindow; /* dictMatchState isn't correctly
1623
+ || params->attachDictPref == ZSTD_dictForceAttach )
1624
+ && params->attachDictPref != ZSTD_dictForceCopy
1625
+ && !params->forceWindow; /* dictMatchState isn't correctly
1502
1626
  * handled in _enforceMaxDist */
1503
1627
  }
1504
1628
 
1505
- static size_t ZSTD_resetCCtx_byAttachingCDict(
1506
- ZSTD_CCtx* cctx,
1507
- const ZSTD_CDict* cdict,
1508
- ZSTD_CCtx_params params,
1509
- U64 pledgedSrcSize,
1510
- 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)
1511
1635
  {
1512
- {
1513
- const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1636
+ { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams;
1514
1637
  unsigned const windowLog = params.cParams.windowLog;
1515
1638
  assert(windowLog != 0);
1516
1639
  /* Resize working context table params for input only, since the dict
1517
1640
  * has its own tables. */
1641
+ /* pledgeSrcSize == 0 means 0! */
1518
1642
  params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
1519
1643
  params.cParams.windowLog = windowLog;
1520
- ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1521
- ZSTDcrp_continue, zbuff);
1644
+ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1645
+ ZSTDcrp_makeClean, zbuff), "");
1522
1646
  assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1523
1647
  }
1524
1648
 
1525
- {
1526
- const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1649
+ { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1527
1650
  - cdict->matchState.window.base);
1528
1651
  const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
1529
1652
  if (cdictLen == 0) {
@@ -1540,9 +1663,9 @@ static size_t ZSTD_resetCCtx_byAttachingCDict(
1540
1663
  cctx->blockState.matchState.window.base + cdictEnd;
1541
1664
  ZSTD_window_clear(&cctx->blockState.matchState.window);
1542
1665
  }
1666
+ /* loadedDictEnd is expressed within the referential of the active context */
1543
1667
  cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
1544
- }
1545
- }
1668
+ } }
1546
1669
 
1547
1670
  cctx->dictID = cdict->dictID;
1548
1671
 
@@ -1567,36 +1690,41 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
1567
1690
  /* Copy only compression parameters related to tables. */
1568
1691
  params.cParams = *cdict_cParams;
1569
1692
  params.cParams.windowLog = windowLog;
1570
- ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1571
- ZSTDcrp_noMemset, zbuff);
1693
+ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1694
+ ZSTDcrp_leaveDirty, zbuff), "");
1572
1695
  assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1573
1696
  assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
1574
1697
  assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
1575
1698
  }
1576
1699
 
1700
+ ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
1701
+
1577
1702
  /* copy tables */
1578
1703
  { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
1579
1704
  size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
1580
- size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
1581
- assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1582
- assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
1583
- assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
1584
- assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
1585
- 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));
1586
1712
  }
1587
1713
 
1588
1714
  /* Zero the hashTable3, since the cdict never fills it */
1589
- { 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;
1590
1717
  assert(cdict->matchState.hashLog3 == 0);
1591
1718
  memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1592
1719
  }
1593
1720
 
1721
+ ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
1722
+
1594
1723
  /* copy dictionary offsets */
1595
1724
  { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1596
1725
  ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1597
1726
  dstMatchState->window = srcMatchState->window;
1598
1727
  dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1599
- dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1600
1728
  dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1601
1729
  }
1602
1730
 
@@ -1613,7 +1741,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
1613
1741
  * in-place. We decide here which strategy to use. */
1614
1742
  static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1615
1743
  const ZSTD_CDict* cdict,
1616
- ZSTD_CCtx_params params,
1744
+ const ZSTD_CCtx_params* params,
1617
1745
  U64 pledgedSrcSize,
1618
1746
  ZSTD_buffered_policy_e zbuff)
1619
1747
  {
@@ -1623,10 +1751,10 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1623
1751
 
1624
1752
  if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
1625
1753
  return ZSTD_resetCCtx_byAttachingCDict(
1626
- cctx, cdict, params, pledgedSrcSize, zbuff);
1754
+ cctx, cdict, *params, pledgedSrcSize, zbuff);
1627
1755
  } else {
1628
1756
  return ZSTD_resetCCtx_byCopyingCDict(
1629
- cctx, cdict, params, pledgedSrcSize, zbuff);
1757
+ cctx, cdict, *params, pledgedSrcSize, zbuff);
1630
1758
  }
1631
1759
  }
1632
1760
 
@@ -1644,7 +1772,8 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1644
1772
  ZSTD_buffered_policy_e zbuff)
1645
1773
  {
1646
1774
  DEBUGLOG(5, "ZSTD_copyCCtx_internal");
1647
- if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
1775
+ RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
1776
+ "Can't copy a ctx that's not in init stage.");
1648
1777
 
1649
1778
  memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
1650
1779
  { ZSTD_CCtx_params params = dstCCtx->requestedParams;
@@ -1652,7 +1781,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1652
1781
  params.cParams = srcCCtx->appliedParams.cParams;
1653
1782
  params.fParams = fParams;
1654
1783
  ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
1655
- ZSTDcrp_noMemset, zbuff);
1784
+ ZSTDcrp_leaveDirty, zbuff);
1656
1785
  assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
1657
1786
  assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
1658
1787
  assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
@@ -1660,23 +1789,33 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
1660
1789
  assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
1661
1790
  }
1662
1791
 
1792
+ ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);
1793
+
1663
1794
  /* copy tables */
1664
1795
  { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
1665
1796
  size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
1666
- size_t const h3Size = (size_t)1 << srcCCtx->blockState.matchState.hashLog3;
1667
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
1668
- assert((U32*)dstCCtx->blockState.matchState.chainTable == (U32*)dstCCtx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1669
- assert((U32*)dstCCtx->blockState.matchState.hashTable3 == (U32*)dstCCtx->blockState.matchState.chainTable + chainSize);
1670
- 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));
1671
1809
  }
1672
1810
 
1811
+ ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);
1812
+
1673
1813
  /* copy dictionary offsets */
1674
1814
  {
1675
1815
  const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
1676
1816
  ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
1677
1817
  dstMatchState->window = srcMatchState->window;
1678
1818
  dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1679
- dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1680
1819
  dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1681
1820
  }
1682
1821
  dstCCtx->dictID = srcCCtx->dictID;
@@ -1721,6 +1860,20 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
1721
1860
  int rowNb;
1722
1861
  assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
1723
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
+
1724
1877
  for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
1725
1878
  int column;
1726
1879
  for (column=0; column<ZSTD_ROWSIZE; column++) {
@@ -1746,16 +1899,15 @@ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const
1746
1899
 
1747
1900
  /*! ZSTD_reduceIndex() :
1748
1901
  * rescale all indexes to avoid future overflow (indexes are U32) */
1749
- 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)
1750
1903
  {
1751
- ZSTD_matchState_t* const ms = &zc->blockState.matchState;
1752
- { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
1904
+ { U32 const hSize = (U32)1 << params->cParams.hashLog;
1753
1905
  ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
1754
1906
  }
1755
1907
 
1756
- if (zc->appliedParams.cParams.strategy != ZSTD_fast) {
1757
- U32 const chainSize = (U32)1 << zc->appliedParams.cParams.chainLog;
1758
- 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)
1759
1911
  ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
1760
1912
  else
1761
1913
  ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
@@ -1774,164 +1926,6 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
1774
1926
 
1775
1927
  /* See doc/zstd_compression_format.md for detailed format description */
1776
1928
 
1777
- static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
1778
- {
1779
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
1780
- if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
1781
- MEM_writeLE24(dst, cBlockHeader24);
1782
- memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
1783
- return ZSTD_blockHeaderSize + srcSize;
1784
- }
1785
-
1786
- static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1787
- {
1788
- BYTE* const ostart = (BYTE* const)dst;
1789
- U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
1790
-
1791
- if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
1792
-
1793
- switch(flSize)
1794
- {
1795
- case 1: /* 2 - 1 - 5 */
1796
- ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3));
1797
- break;
1798
- case 2: /* 2 - 2 - 12 */
1799
- MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));
1800
- break;
1801
- case 3: /* 2 - 2 - 20 */
1802
- MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));
1803
- break;
1804
- default: /* not necessary : flSize is {1,2,3} */
1805
- assert(0);
1806
- }
1807
-
1808
- memcpy(ostart + flSize, src, srcSize);
1809
- return srcSize + flSize;
1810
- }
1811
-
1812
- static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1813
- {
1814
- BYTE* const ostart = (BYTE* const)dst;
1815
- U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
1816
-
1817
- (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
1818
-
1819
- switch(flSize)
1820
- {
1821
- case 1: /* 2 - 1 - 5 */
1822
- ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3));
1823
- break;
1824
- case 2: /* 2 - 2 - 12 */
1825
- MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));
1826
- break;
1827
- case 3: /* 2 - 2 - 20 */
1828
- MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));
1829
- break;
1830
- default: /* not necessary : flSize is {1,2,3} */
1831
- assert(0);
1832
- }
1833
-
1834
- ostart[flSize] = *(const BYTE*)src;
1835
- return flSize+1;
1836
- }
1837
-
1838
-
1839
- /* ZSTD_minGain() :
1840
- * minimum compression required
1841
- * to generate a compress block or a compressed literals section.
1842
- * note : use same formula for both situations */
1843
- static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
1844
- {
1845
- U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
1846
- ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
1847
- assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
1848
- return (srcSize >> minlog) + 2;
1849
- }
1850
-
1851
- static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
1852
- ZSTD_hufCTables_t* nextHuf,
1853
- ZSTD_strategy strategy, int disableLiteralCompression,
1854
- void* dst, size_t dstCapacity,
1855
- const void* src, size_t srcSize,
1856
- void* workspace, size_t wkspSize,
1857
- const int bmi2)
1858
- {
1859
- size_t const minGain = ZSTD_minGain(srcSize, strategy);
1860
- size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
1861
- BYTE* const ostart = (BYTE*)dst;
1862
- U32 singleStream = srcSize < 256;
1863
- symbolEncodingType_e hType = set_compressed;
1864
- size_t cLitSize;
1865
-
1866
- DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
1867
- disableLiteralCompression);
1868
-
1869
- /* Prepare nextEntropy assuming reusing the existing table */
1870
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1871
-
1872
- if (disableLiteralCompression)
1873
- return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1874
-
1875
- /* small ? don't even attempt compression (speed opt) */
1876
- # define COMPRESS_LITERALS_SIZE_MIN 63
1877
- { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
1878
- if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1879
- }
1880
-
1881
- if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
1882
- { HUF_repeat repeat = prevHuf->repeatMode;
1883
- int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
1884
- if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
1885
- cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1886
- workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
1887
- : HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
1888
- workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
1889
- if (repeat != HUF_repeat_none) {
1890
- /* reused the existing table */
1891
- hType = set_repeat;
1892
- }
1893
- }
1894
-
1895
- if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
1896
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1897
- return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
1898
- }
1899
- if (cLitSize==1) {
1900
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
1901
- return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
1902
- }
1903
-
1904
- if (hType == set_compressed) {
1905
- /* using a newly constructed table */
1906
- nextHuf->repeatMode = HUF_repeat_check;
1907
- }
1908
-
1909
- /* Build header */
1910
- switch(lhSize)
1911
- {
1912
- case 3: /* 2 - 2 - 10 - 10 */
1913
- { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
1914
- MEM_writeLE24(ostart, lhc);
1915
- break;
1916
- }
1917
- case 4: /* 2 - 2 - 14 - 14 */
1918
- { U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);
1919
- MEM_writeLE32(ostart, lhc);
1920
- break;
1921
- }
1922
- case 5: /* 2 - 2 - 18 - 18 */
1923
- { U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
1924
- MEM_writeLE32(ostart, lhc);
1925
- ostart[4] = (BYTE)(cLitSize >> 10);
1926
- break;
1927
- }
1928
- default: /* not possible : lhSize is {3,4,5} */
1929
- assert(0);
1930
- }
1931
- return lhSize+cLitSize;
1932
- }
1933
-
1934
-
1935
1929
  void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1936
1930
  {
1937
1931
  const seqDef* const sequences = seqStorePtr->sequencesStart;
@@ -1944,428 +1938,24 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1944
1938
  for (u=0; u<nbSeq; u++) {
1945
1939
  U32 const llv = sequences[u].litLength;
1946
1940
  U32 const mlv = sequences[u].matchLength;
1947
- llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
1948
- ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
1949
- mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
1950
- }
1951
- if (seqStorePtr->longLengthID==1)
1952
- llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
1953
- if (seqStorePtr->longLengthID==2)
1954
- mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
1955
- }
1956
-
1957
-
1958
- /**
1959
- * -log2(x / 256) lookup table for x in [0, 256).
1960
- * If x == 0: Return 0
1961
- * Else: Return floor(-log2(x / 256) * 256)
1962
- */
1963
- static unsigned const kInverseProbabiltyLog256[256] = {
1964
- 0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
1965
- 1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
1966
- 874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
1967
- 724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
1968
- 618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
1969
- 535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
1970
- 468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
1971
- 411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
1972
- 362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
1973
- 318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
1974
- 279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
1975
- 244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
1976
- 212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
1977
- 182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
1978
- 155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
1979
- 130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
1980
- 106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
1981
- 83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
1982
- 62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
1983
- 42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
1984
- 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
1985
- 5, 4, 2, 1,
1986
- };
1987
-
1988
-
1989
- /**
1990
- * Returns the cost in bits of encoding the distribution described by count
1991
- * using the entropy bound.
1992
- */
1993
- static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
1994
- {
1995
- unsigned cost = 0;
1996
- unsigned s;
1997
- for (s = 0; s <= max; ++s) {
1998
- unsigned norm = (unsigned)((256 * count[s]) / total);
1999
- if (count[s] != 0 && norm == 0)
2000
- norm = 1;
2001
- assert(count[s] < total);
2002
- cost += count[s] * kInverseProbabiltyLog256[norm];
2003
- }
2004
- return cost >> 8;
2005
- }
2006
-
2007
-
2008
- /**
2009
- * Returns the cost in bits of encoding the distribution in count using the
2010
- * table described by norm. The max symbol support by norm is assumed >= max.
2011
- * norm must be valid for every symbol with non-zero probability in count.
2012
- */
2013
- static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
2014
- unsigned const* count, unsigned const max)
2015
- {
2016
- unsigned const shift = 8 - accuracyLog;
2017
- size_t cost = 0;
2018
- unsigned s;
2019
- assert(accuracyLog <= 8);
2020
- for (s = 0; s <= max; ++s) {
2021
- unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
2022
- unsigned const norm256 = normAcc << shift;
2023
- assert(norm256 > 0);
2024
- assert(norm256 < 256);
2025
- cost += count[s] * kInverseProbabiltyLog256[norm256];
2026
- }
2027
- return cost >> 8;
2028
- }
2029
-
2030
-
2031
- static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
2032
- void const* ptr = ctable;
2033
- U16 const* u16ptr = (U16 const*)ptr;
2034
- U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
2035
- return maxSymbolValue;
2036
- }
2037
-
2038
-
2039
- /**
2040
- * Returns the cost in bits of encoding the distribution in count using ctable.
2041
- * Returns an error if ctable cannot represent all the symbols in count.
2042
- */
2043
- static size_t ZSTD_fseBitCost(
2044
- FSE_CTable const* ctable,
2045
- unsigned const* count,
2046
- unsigned const max)
2047
- {
2048
- unsigned const kAccuracyLog = 8;
2049
- size_t cost = 0;
2050
- unsigned s;
2051
- FSE_CState_t cstate;
2052
- FSE_initCState(&cstate, ctable);
2053
- if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {
2054
- DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u",
2055
- ZSTD_getFSEMaxSymbolValue(ctable), max);
2056
- return ERROR(GENERIC);
2057
- }
2058
- for (s = 0; s <= max; ++s) {
2059
- unsigned const tableLog = cstate.stateLog;
2060
- unsigned const badCost = (tableLog + 1) << kAccuracyLog;
2061
- unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
2062
- if (count[s] == 0)
2063
- continue;
2064
- if (bitCost >= badCost) {
2065
- DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s);
2066
- return ERROR(GENERIC);
2067
- }
2068
- cost += count[s] * bitCost;
2069
- }
2070
- return cost >> kAccuracyLog;
2071
- }
2072
-
2073
- /**
2074
- * Returns the cost in bytes of encoding the normalized count header.
2075
- * Returns an error if any of the helper functions return an error.
2076
- */
2077
- static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
2078
- size_t const nbSeq, unsigned const FSELog)
2079
- {
2080
- BYTE wksp[FSE_NCOUNTBOUND];
2081
- S16 norm[MaxSeq + 1];
2082
- const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
2083
- CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
2084
- return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
2085
- }
2086
-
2087
-
2088
- typedef enum {
2089
- ZSTD_defaultDisallowed = 0,
2090
- ZSTD_defaultAllowed = 1
2091
- } ZSTD_defaultPolicy_e;
2092
-
2093
- MEM_STATIC symbolEncodingType_e
2094
- ZSTD_selectEncodingType(
2095
- FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
2096
- size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
2097
- FSE_CTable const* prevCTable,
2098
- short const* defaultNorm, U32 defaultNormLog,
2099
- ZSTD_defaultPolicy_e const isDefaultAllowed,
2100
- ZSTD_strategy const strategy)
2101
- {
2102
- ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
2103
- if (mostFrequent == nbSeq) {
2104
- *repeatMode = FSE_repeat_none;
2105
- if (isDefaultAllowed && nbSeq <= 2) {
2106
- /* Prefer set_basic over set_rle when there are 2 or less symbols,
2107
- * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
2108
- * If basic encoding isn't possible, always choose RLE.
2109
- */
2110
- DEBUGLOG(5, "Selected set_basic");
2111
- return set_basic;
2112
- }
2113
- DEBUGLOG(5, "Selected set_rle");
2114
- return set_rle;
2115
- }
2116
- if (strategy < ZSTD_lazy) {
2117
- if (isDefaultAllowed) {
2118
- size_t const staticFse_nbSeq_max = 1000;
2119
- size_t const mult = 10 - strategy;
2120
- size_t const baseLog = 3;
2121
- size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
2122
- assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
2123
- assert(mult <= 9 && mult >= 7);
2124
- if ( (*repeatMode == FSE_repeat_valid)
2125
- && (nbSeq < staticFse_nbSeq_max) ) {
2126
- DEBUGLOG(5, "Selected set_repeat");
2127
- return set_repeat;
2128
- }
2129
- if ( (nbSeq < dynamicFse_nbSeq_min)
2130
- || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
2131
- DEBUGLOG(5, "Selected set_basic");
2132
- /* The format allows default tables to be repeated, but it isn't useful.
2133
- * When using simple heuristics to select encoding type, we don't want
2134
- * to confuse these tables with dictionaries. When running more careful
2135
- * analysis, we don't need to waste time checking both repeating tables
2136
- * and default tables.
2137
- */
2138
- *repeatMode = FSE_repeat_none;
2139
- return set_basic;
2140
- }
2141
- }
2142
- } else {
2143
- size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
2144
- size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
2145
- size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
2146
- size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
2147
-
2148
- if (isDefaultAllowed) {
2149
- assert(!ZSTD_isError(basicCost));
2150
- assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
2151
- }
2152
- assert(!ZSTD_isError(NCountCost));
2153
- assert(compressedCost < ERROR(maxCode));
2154
- DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
2155
- (unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);
2156
- if (basicCost <= repeatCost && basicCost <= compressedCost) {
2157
- DEBUGLOG(5, "Selected set_basic");
2158
- assert(isDefaultAllowed);
2159
- *repeatMode = FSE_repeat_none;
2160
- return set_basic;
2161
- }
2162
- if (repeatCost <= compressedCost) {
2163
- DEBUGLOG(5, "Selected set_repeat");
2164
- assert(!ZSTD_isError(repeatCost));
2165
- return set_repeat;
2166
- }
2167
- assert(compressedCost < basicCost && compressedCost < repeatCost);
2168
- }
2169
- DEBUGLOG(5, "Selected set_compressed");
2170
- *repeatMode = FSE_repeat_check;
2171
- return set_compressed;
2172
- }
2173
-
2174
- MEM_STATIC size_t
2175
- ZSTD_buildCTable(void* dst, size_t dstCapacity,
2176
- FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
2177
- unsigned* count, U32 max,
2178
- const BYTE* codeTable, size_t nbSeq,
2179
- const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
2180
- const FSE_CTable* prevCTable, size_t prevCTableSize,
2181
- void* workspace, size_t workspaceSize)
2182
- {
2183
- BYTE* op = (BYTE*)dst;
2184
- const BYTE* const oend = op + dstCapacity;
2185
- DEBUGLOG(6, "ZSTD_buildCTable (dstCapacity=%u)", (unsigned)dstCapacity);
2186
-
2187
- switch (type) {
2188
- case set_rle:
2189
- CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
2190
- if (dstCapacity==0) return ERROR(dstSize_tooSmall);
2191
- *op = codeTable[0];
2192
- return 1;
2193
- case set_repeat:
2194
- memcpy(nextCTable, prevCTable, prevCTableSize);
2195
- return 0;
2196
- case set_basic:
2197
- CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
2198
- return 0;
2199
- case set_compressed: {
2200
- S16 norm[MaxSeq + 1];
2201
- size_t nbSeq_1 = nbSeq;
2202
- const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
2203
- if (count[codeTable[nbSeq-1]] > 1) {
2204
- count[codeTable[nbSeq-1]]--;
2205
- nbSeq_1--;
2206
- }
2207
- assert(nbSeq_1 > 1);
2208
- CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
2209
- { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
2210
- if (FSE_isError(NCountSize)) return NCountSize;
2211
- CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
2212
- return NCountSize;
2213
- }
2214
- }
2215
- default: return assert(0), ERROR(GENERIC);
2216
- }
2217
- }
2218
-
2219
- FORCE_INLINE_TEMPLATE size_t
2220
- ZSTD_encodeSequences_body(
2221
- void* dst, size_t dstCapacity,
2222
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2223
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2224
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2225
- seqDef const* sequences, size_t nbSeq, int longOffsets)
2226
- {
2227
- BIT_CStream_t blockStream;
2228
- FSE_CState_t stateMatchLength;
2229
- FSE_CState_t stateOffsetBits;
2230
- FSE_CState_t stateLitLength;
2231
-
2232
- CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
2233
- DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
2234
- (int)(blockStream.endPtr - blockStream.startPtr),
2235
- (unsigned)dstCapacity);
2236
-
2237
- /* first symbols */
2238
- FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
2239
- FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
2240
- FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
2241
- BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
2242
- if (MEM_32bits()) BIT_flushBits(&blockStream);
2243
- BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
2244
- if (MEM_32bits()) BIT_flushBits(&blockStream);
2245
- if (longOffsets) {
2246
- U32 const ofBits = ofCodeTable[nbSeq-1];
2247
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
2248
- if (extraBits) {
2249
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
2250
- BIT_flushBits(&blockStream);
2251
- }
2252
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
2253
- ofBits - extraBits);
2254
- } else {
2255
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
2256
- }
2257
- BIT_flushBits(&blockStream);
2258
-
2259
- { size_t n;
2260
- for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
2261
- BYTE const llCode = llCodeTable[n];
2262
- BYTE const ofCode = ofCodeTable[n];
2263
- BYTE const mlCode = mlCodeTable[n];
2264
- U32 const llBits = LL_bits[llCode];
2265
- U32 const ofBits = ofCode;
2266
- U32 const mlBits = ML_bits[mlCode];
2267
- DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
2268
- (unsigned)sequences[n].litLength,
2269
- (unsigned)sequences[n].matchLength + MINMATCH,
2270
- (unsigned)sequences[n].offset);
2271
- /* 32b*/ /* 64b*/
2272
- /* (7)*/ /* (7)*/
2273
- FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
2274
- FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
2275
- if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
2276
- FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
2277
- if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
2278
- BIT_flushBits(&blockStream); /* (7)*/
2279
- BIT_addBits(&blockStream, sequences[n].litLength, llBits);
2280
- if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
2281
- BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
2282
- if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
2283
- if (longOffsets) {
2284
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
2285
- if (extraBits) {
2286
- BIT_addBits(&blockStream, sequences[n].offset, extraBits);
2287
- BIT_flushBits(&blockStream); /* (7)*/
2288
- }
2289
- BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
2290
- ofBits - extraBits); /* 31 */
2291
- } else {
2292
- BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
2293
- }
2294
- BIT_flushBits(&blockStream); /* (7)*/
2295
- DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
2296
- } }
2297
-
2298
- DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
2299
- FSE_flushCState(&blockStream, &stateMatchLength);
2300
- DEBUGLOG(6, "ZSTD_encodeSequences: flushing Off state with %u bits", stateOffsetBits.stateLog);
2301
- FSE_flushCState(&blockStream, &stateOffsetBits);
2302
- DEBUGLOG(6, "ZSTD_encodeSequences: flushing LL state with %u bits", stateLitLength.stateLog);
2303
- FSE_flushCState(&blockStream, &stateLitLength);
2304
-
2305
- { size_t const streamSize = BIT_closeCStream(&blockStream);
2306
- if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
2307
- return streamSize;
1941
+ llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
1942
+ ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
1943
+ mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
2308
1944
  }
1945
+ if (seqStorePtr->longLengthID==1)
1946
+ llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
1947
+ if (seqStorePtr->longLengthID==2)
1948
+ mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
2309
1949
  }
2310
1950
 
2311
- static size_t
2312
- ZSTD_encodeSequences_default(
2313
- void* dst, size_t dstCapacity,
2314
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2315
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2316
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2317
- seqDef const* sequences, size_t nbSeq, int longOffsets)
2318
- {
2319
- return ZSTD_encodeSequences_body(dst, dstCapacity,
2320
- CTable_MatchLength, mlCodeTable,
2321
- CTable_OffsetBits, ofCodeTable,
2322
- CTable_LitLength, llCodeTable,
2323
- sequences, nbSeq, longOffsets);
2324
- }
2325
-
2326
-
2327
- #if DYNAMIC_BMI2
2328
-
2329
- static TARGET_ATTRIBUTE("bmi2") size_t
2330
- ZSTD_encodeSequences_bmi2(
2331
- void* dst, size_t dstCapacity,
2332
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2333
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2334
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2335
- 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)
2336
1956
  {
2337
- return ZSTD_encodeSequences_body(dst, dstCapacity,
2338
- CTable_MatchLength, mlCodeTable,
2339
- CTable_OffsetBits, ofCodeTable,
2340
- CTable_LitLength, llCodeTable,
2341
- sequences, nbSeq, longOffsets);
2342
- }
2343
-
2344
- #endif
2345
-
2346
- static size_t ZSTD_encodeSequences(
2347
- void* dst, size_t dstCapacity,
2348
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2349
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
2350
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
2351
- seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
2352
- {
2353
- DEBUGLOG(5, "ZSTD_encodeSequences: dstCapacity = %u", (unsigned)dstCapacity);
2354
- #if DYNAMIC_BMI2
2355
- if (bmi2) {
2356
- return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
2357
- CTable_MatchLength, mlCodeTable,
2358
- CTable_OffsetBits, ofCodeTable,
2359
- CTable_LitLength, llCodeTable,
2360
- sequences, nbSeq, longOffsets);
2361
- }
2362
- #endif
2363
- (void)bmi2;
2364
- return ZSTD_encodeSequences_default(dst, dstCapacity,
2365
- CTable_MatchLength, mlCodeTable,
2366
- CTable_OffsetBits, ofCodeTable,
2367
- CTable_LitLength, llCodeTable,
2368
- sequences, nbSeq, longOffsets);
1957
+ DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize);
1958
+ return (cctxParams->targetCBlockSize != 0);
2369
1959
  }
2370
1960
 
2371
1961
  /* ZSTD_compressSequences_internal():
@@ -2376,7 +1966,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2376
1966
  ZSTD_entropyCTables_t* nextEntropy,
2377
1967
  const ZSTD_CCtx_params* cctxParams,
2378
1968
  void* dst, size_t dstCapacity,
2379
- void* workspace, size_t wkspSize,
1969
+ void* entropyWorkspace, size_t entropyWkspSize,
2380
1970
  const int bmi2)
2381
1971
  {
2382
1972
  const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
@@ -2393,52 +1983,59 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2393
1983
  BYTE* const ostart = (BYTE*)dst;
2394
1984
  BYTE* const oend = ostart + dstCapacity;
2395
1985
  BYTE* op = ostart;
2396
- size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
1986
+ size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
2397
1987
  BYTE* seqHead;
2398
1988
  BYTE* lastNCount = NULL;
2399
1989
 
1990
+ DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq);
2400
1991
  ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
2401
- DEBUGLOG(5, "ZSTD_compressSequences_internal");
2402
1992
 
2403
1993
  /* Compress literals */
2404
1994
  { const BYTE* const literals = seqStorePtr->litStart;
2405
- size_t const litSize = seqStorePtr->lit - literals;
2406
- int const disableLiteralCompression = (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
1995
+ size_t const litSize = (size_t)(seqStorePtr->lit - literals);
2407
1996
  size_t const cSize = ZSTD_compressLiterals(
2408
1997
  &prevEntropy->huf, &nextEntropy->huf,
2409
- cctxParams->cParams.strategy, disableLiteralCompression,
1998
+ cctxParams->cParams.strategy,
1999
+ ZSTD_disableLiteralsCompression(cctxParams),
2410
2000
  op, dstCapacity,
2411
2001
  literals, litSize,
2412
- workspace, wkspSize,
2002
+ entropyWorkspace, entropyWkspSize,
2413
2003
  bmi2);
2414
- if (ZSTD_isError(cSize))
2415
- return cSize;
2004
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
2416
2005
  assert(cSize <= dstCapacity);
2417
2006
  op += cSize;
2418
2007
  }
2419
2008
 
2420
2009
  /* Sequences Header */
2421
- if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/) return ERROR(dstSize_tooSmall);
2422
- if (nbSeq < 0x7F)
2010
+ RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
2011
+ dstSize_tooSmall, "Can't fit seq hdr in output buf!");
2012
+ if (nbSeq < 128) {
2423
2013
  *op++ = (BYTE)nbSeq;
2424
- else if (nbSeq < LONGNBSEQ)
2425
- op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
2426
- else
2427
- 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);
2428
2024
  if (nbSeq==0) {
2429
2025
  /* Copy the old tables over as if we repeated them */
2430
2026
  memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
2431
- return op - ostart;
2027
+ return (size_t)(op - ostart);
2432
2028
  }
2433
2029
 
2434
2030
  /* seqHead : flags for FSE encoding type */
2435
2031
  seqHead = op++;
2032
+ assert(op <= oend);
2436
2033
 
2437
2034
  /* convert length/distances into codes */
2438
2035
  ZSTD_seqToCodes(seqStorePtr);
2439
2036
  /* build CTable for Literal Lengths */
2440
2037
  { unsigned max = MaxLL;
2441
- 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 */
2442
2039
  DEBUGLOG(5, "Building LL table");
2443
2040
  nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
2444
2041
  LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
@@ -2448,18 +2045,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2448
2045
  ZSTD_defaultAllowed, strategy);
2449
2046
  assert(set_basic < set_compressed && set_rle < set_compressed);
2450
2047
  assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2451
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
2452
- count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
2453
- prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
2454
- workspace, wkspSize);
2455
- if (ZSTD_isError(countSize)) return 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");
2456
2057
  if (LLtype == set_compressed)
2457
2058
  lastNCount = op;
2458
2059
  op += countSize;
2060
+ assert(op <= oend);
2459
2061
  } }
2460
2062
  /* build CTable for Offsets */
2461
2063
  { unsigned max = MaxOff;
2462
- 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 */
2463
2066
  /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
2464
2067
  ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
2465
2068
  DEBUGLOG(5, "Building OF table");
@@ -2470,18 +2073,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2470
2073
  OF_defaultNorm, OF_defaultNormLog,
2471
2074
  defaultPolicy, strategy);
2472
2075
  assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2473
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
2474
- count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
2475
- prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
2476
- workspace, wkspSize);
2477
- if (ZSTD_isError(countSize)) return 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");
2478
2085
  if (Offtype == set_compressed)
2479
2086
  lastNCount = op;
2480
2087
  op += countSize;
2088
+ assert(op <= oend);
2481
2089
  } }
2482
2090
  /* build CTable for MatchLengths */
2483
2091
  { unsigned max = MaxML;
2484
- 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 */
2485
2094
  DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
2486
2095
  nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
2487
2096
  MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
@@ -2490,29 +2099,35 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2490
2099
  ML_defaultNorm, ML_defaultNormLog,
2491
2100
  ZSTD_defaultAllowed, strategy);
2492
2101
  assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
2493
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
2494
- count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
2495
- prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
2496
- workspace, wkspSize);
2497
- if (ZSTD_isError(countSize)) return 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");
2498
2111
  if (MLtype == set_compressed)
2499
2112
  lastNCount = op;
2500
2113
  op += countSize;
2114
+ assert(op <= oend);
2501
2115
  } }
2502
2116
 
2503
2117
  *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
2504
2118
 
2505
2119
  { size_t const bitstreamSize = ZSTD_encodeSequences(
2506
- op, oend - op,
2120
+ op, (size_t)(oend - op),
2507
2121
  CTable_MatchLength, mlCodeTable,
2508
2122
  CTable_OffsetBits, ofCodeTable,
2509
2123
  CTable_LitLength, llCodeTable,
2510
2124
  sequences, nbSeq,
2511
2125
  longOffsets, bmi2);
2512
- if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
2126
+ FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
2513
2127
  op += bitstreamSize;
2128
+ assert(op <= oend);
2514
2129
  /* zstd versions <= 1.3.4 mistakenly report corruption when
2515
- * FSE_readNCount() recieves a buffer < 4 bytes.
2130
+ * FSE_readNCount() receives a buffer < 4 bytes.
2516
2131
  * Fixed by https://github.com/facebook/zstd/pull/1146.
2517
2132
  * This can happen when the last set_compressed table present is 2
2518
2133
  * bytes and the bitstream is only one byte.
@@ -2529,7 +2144,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
2529
2144
  }
2530
2145
 
2531
2146
  DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
2532
- return op - ostart;
2147
+ return (size_t)(op - ostart);
2533
2148
  }
2534
2149
 
2535
2150
  MEM_STATIC size_t
@@ -2539,20 +2154,20 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
2539
2154
  const ZSTD_CCtx_params* cctxParams,
2540
2155
  void* dst, size_t dstCapacity,
2541
2156
  size_t srcSize,
2542
- void* workspace, size_t wkspSize,
2157
+ void* entropyWorkspace, size_t entropyWkspSize,
2543
2158
  int bmi2)
2544
2159
  {
2545
2160
  size_t const cSize = ZSTD_compressSequences_internal(
2546
2161
  seqStorePtr, prevEntropy, nextEntropy, cctxParams,
2547
2162
  dst, dstCapacity,
2548
- workspace, wkspSize, bmi2);
2163
+ entropyWorkspace, entropyWkspSize, bmi2);
2549
2164
  if (cSize == 0) return 0;
2550
2165
  /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
2551
2166
  * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
2552
2167
  */
2553
2168
  if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
2554
2169
  return 0; /* block not compressed */
2555
- if (ZSTD_isError(cSize)) return cSize;
2170
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed");
2556
2171
 
2557
2172
  /* Check compressibility */
2558
2173
  { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
@@ -2622,27 +2237,24 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
2622
2237
  ssPtr->longLengthID = 0;
2623
2238
  }
2624
2239
 
2625
- static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2626
- void* dst, size_t dstCapacity,
2627
- 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)
2628
2243
  {
2629
2244
  ZSTD_matchState_t* const ms = &zc->blockState.matchState;
2630
- size_t cSize;
2631
- DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
2632
- (unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate);
2245
+ DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
2633
2246
  assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
2634
-
2635
2247
  /* Assert that we have correctly flushed the ctx params into the ms's copy */
2636
2248
  ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
2637
-
2638
2249
  if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
2639
2250
  ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
2640
- cSize = 0;
2641
- goto out; /* don't even attempt compression below a certain srcSize */
2251
+ return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
2642
2252
  }
2643
2253
  ZSTD_resetSeqStore(&(zc->seqStore));
2644
- ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* required for optimal parser to read stats from dictionary */
2645
-
2254
+ /* required for optimal parser to read stats from dictionary */
2255
+ ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
2256
+ /* tell the optimal parser how we expect to compress literals */
2257
+ ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
2646
2258
  /* a gap between an attached dict and the current window is not safe,
2647
2259
  * they must remain adjacent,
2648
2260
  * and when that stops being the case, the dict must be unset */
@@ -2679,9 +2291,9 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2679
2291
  ldmSeqStore.seq = zc->ldmSequences;
2680
2292
  ldmSeqStore.capacity = zc->maxNbLdmSequences;
2681
2293
  /* Updates ldmSeqStore.size */
2682
- CHECK_F(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
2294
+ FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
2683
2295
  &zc->appliedParams.ldmParams,
2684
- src, srcSize));
2296
+ src, srcSize), "");
2685
2297
  /* Updates ldmSeqStore.pos */
2686
2298
  lastLLSize =
2687
2299
  ZSTD_ldm_blockCompress(&ldmSeqStore,
@@ -2696,6 +2308,134 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2696
2308
  { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
2697
2309
  ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
2698
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
+ }
2699
2439
 
2700
2440
  /* encode sequences and literals */
2701
2441
  cSize = ZSTD_compressSequences(&zc->seqStore,
@@ -2706,12 +2446,22 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2706
2446
  zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
2707
2447
  zc->bmi2);
2708
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
+
2709
2462
  out:
2710
- if (!ZSTD_isError(cSize) && cSize != 0) {
2711
- /* confirm repcodes and entropy tables when emitting a compressed block */
2712
- ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
2713
- zc->blockState.prevCBlock = zc->blockState.nextCBlock;
2714
- zc->blockState.nextCBlock = tmp;
2463
+ if (!ZSTD_isError(cSize) && cSize > 1) {
2464
+ ZSTD_confirmRepcodesAndEntropyTables(zc);
2715
2465
  }
2716
2466
  /* We check that dictionaries have offset codes available for the first
2717
2467
  * block. After the first block, the offcode table might not have large
@@ -2723,6 +2473,104 @@ out:
2723
2473
  return cSize;
2724
2474
  }
2725
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
+ }
2726
2574
 
2727
2575
  /*! ZSTD_compress_frameChunk() :
2728
2576
  * Compress a chunk of data into one or multiple blocks.
@@ -2742,7 +2590,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2742
2590
  BYTE* const ostart = (BYTE*)dst;
2743
2591
  BYTE* op = ostart;
2744
2592
  U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
2745
- assert(cctx->appliedParams.cParams.windowLog <= 31);
2593
+
2594
+ assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
2746
2595
 
2747
2596
  DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
2748
2597
  if (cctx->appliedParams.fParams.checksumFlag && srcSize)
@@ -2752,78 +2601,84 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2752
2601
  ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
2753
2602
  U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
2754
2603
 
2755
- if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE)
2756
- return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
2604
+ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
2605
+ dstSize_tooSmall,
2606
+ "not enough space to store compressed block");
2757
2607
  if (remaining < blockSize) blockSize = remaining;
2758
2608
 
2759
- if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) {
2760
- U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2761
- U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
2762
- ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2763
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2764
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2765
- ZSTD_reduceIndex(cctx, correction);
2766
- if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2767
- else ms->nextToUpdate -= correction;
2768
- ms->loadedDictEnd = 0;
2769
- ms->dictMatchState = NULL;
2770
- }
2771
- ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
2772
- 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);
2773
2612
 
2774
- { size_t cSize = ZSTD_compressBlock_internal(cctx,
2775
- op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
2776
- ip, blockSize);
2777
- if (ZSTD_isError(cSize)) return cSize;
2613
+ /* Ensure hash/chain table insertion resumes no sooner than lowlimit */
2614
+ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
2778
2615
 
2779
- if (cSize == 0) { /* block is not compressible */
2780
- cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
2781
- if (ZSTD_isError(cSize)) return 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);
2782
2622
  } else {
2783
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
2784
- MEM_writeLE24(op, cBlockHeader24);
2785
- 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
+ }
2786
2638
  }
2787
2639
 
2640
+
2788
2641
  ip += blockSize;
2789
2642
  assert(remaining >= blockSize);
2790
2643
  remaining -= blockSize;
2791
2644
  op += cSize;
2792
2645
  assert(dstCapacity >= cSize);
2793
2646
  dstCapacity -= cSize;
2647
+ cctx->isFirstBlock = 0;
2794
2648
  DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
2795
2649
  (unsigned)cSize);
2796
2650
  } }
2797
2651
 
2798
2652
  if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
2799
- return op-ostart;
2653
+ return (size_t)(op-ostart);
2800
2654
  }
2801
2655
 
2802
2656
 
2803
2657
  static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2804
- ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
2658
+ const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID)
2805
2659
  { BYTE* const op = (BYTE*)dst;
2806
2660
  U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
2807
- U32 const dictIDSizeCode = params.fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
2808
- U32 const checksumFlag = params.fParams.checksumFlag>0;
2809
- U32 const windowSize = (U32)1 << params.cParams.windowLog;
2810
- U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
2811
- BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2812
- 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 ?
2813
2667
  (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
2814
- BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2668
+ BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2815
2669
  size_t pos=0;
2816
2670
 
2817
- assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
2818
- if (dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX) return ERROR(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.");
2819
2674
  DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2820
- !params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
2675
+ !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
2821
2676
 
2822
- if (params.format == ZSTD_f_zstd1) {
2677
+ if (params->format == ZSTD_f_zstd1) {
2823
2678
  MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2824
2679
  pos = 4;
2825
2680
  }
2826
- op[pos++] = frameHeaderDecriptionByte;
2681
+ op[pos++] = frameHeaderDescriptionByte;
2827
2682
  if (!singleSegment) op[pos++] = windowLogByte;
2828
2683
  switch(dictIDSizeCode)
2829
2684
  {
@@ -2847,11 +2702,12 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2847
2702
  /* ZSTD_writeLastEmptyBlock() :
2848
2703
  * output an empty Block with end-of-frame mark to complete a frame
2849
2704
  * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
2850
- * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
2705
+ * or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
2851
2706
  */
2852
2707
  size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
2853
2708
  {
2854
- if (dstCapacity < ZSTD_blockHeaderSize) return ERROR(dstSize_tooSmall);
2709
+ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,
2710
+ "dst buf is too small to write frame trailer empty block.");
2855
2711
  { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
2856
2712
  MEM_writeLE24(dst, cBlockHeader24);
2857
2713
  return ZSTD_blockHeaderSize;
@@ -2860,10 +2716,11 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
2860
2716
 
2861
2717
  size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
2862
2718
  {
2863
- if (cctx->stage != ZSTDcs_init)
2864
- return ERROR(stage_wrong);
2865
- if (cctx->appliedParams.ldmParams.enableLdm)
2866
- return ERROR(parameter_unsupported);
2719
+ RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
2720
+ "wrong cctx stage");
2721
+ RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
2722
+ parameter_unsupported,
2723
+ "incompatible with ldm");
2867
2724
  cctx->externSeqStore.seq = seq;
2868
2725
  cctx->externSeqStore.size = nbSeq;
2869
2726
  cctx->externSeqStore.capacity = nbSeq;
@@ -2882,12 +2739,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2882
2739
 
2883
2740
  DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
2884
2741
  cctx->stage, (unsigned)srcSize);
2885
- if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
2742
+ RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
2743
+ "missing init (ZSTD_compressBegin)");
2886
2744
 
2887
2745
  if (frame && (cctx->stage==ZSTDcs_init)) {
2888
- fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
2746
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,
2889
2747
  cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
2890
- if (ZSTD_isError(fhSize)) return fhSize;
2748
+ FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
2749
+ assert(fhSize <= dstCapacity);
2891
2750
  dstCapacity -= fhSize;
2892
2751
  dst = (char*)dst + fhSize;
2893
2752
  cctx->stage = ZSTDcs_ongoing;
@@ -2904,35 +2763,27 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2904
2763
 
2905
2764
  if (!frame) {
2906
2765
  /* overflow check and correction for block mode */
2907
- if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) {
2908
- U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2909
- U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src);
2910
- ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2911
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2912
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2913
- ZSTD_reduceIndex(cctx, correction);
2914
- if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2915
- else ms->nextToUpdate -= correction;
2916
- ms->loadedDictEnd = 0;
2917
- ms->dictMatchState = NULL;
2918
- }
2766
+ ZSTD_overflowCorrectIfNeeded(
2767
+ ms, &cctx->workspace, &cctx->appliedParams,
2768
+ src, (BYTE const*)src + srcSize);
2919
2769
  }
2920
2770
 
2921
2771
  DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
2922
2772
  { size_t const cSize = frame ?
2923
2773
  ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
2924
- ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
2925
- if (ZSTD_isError(cSize)) return 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");
2926
2776
  cctx->consumedSrcSize += srcSize;
2927
2777
  cctx->producedCSize += (cSize + fhSize);
2928
2778
  assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
2929
2779
  if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
2930
2780
  ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
2931
- if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) {
2932
- DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u",
2933
- (unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize);
2934
- return ERROR(srcSize_wrong);
2935
- }
2781
+ RETURN_ERROR_IF(
2782
+ cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
2783
+ srcSize_wrong,
2784
+ "error : pledgedSrcSize = %u, while realSrcSize >= %u",
2785
+ (unsigned)cctx->pledgedSrcSizePlusOne-1,
2786
+ (unsigned)cctx->consumedSrcSize);
2936
2787
  }
2937
2788
  return cSize + fhSize;
2938
2789
  }
@@ -2956,8 +2807,9 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
2956
2807
 
2957
2808
  size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2958
2809
  {
2959
- size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
2960
- if (srcSize > blockSizeMax) return ERROR(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"); }
2961
2813
 
2962
2814
  return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
2963
2815
  }
@@ -2966,47 +2818,67 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
2966
2818
  * @return : 0, or an error code
2967
2819
  */
2968
2820
  static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
2821
+ ldmState_t* ls,
2822
+ ZSTD_cwksp* ws,
2969
2823
  ZSTD_CCtx_params const* params,
2970
2824
  const void* src, size_t srcSize,
2971
2825
  ZSTD_dictTableLoadMethod_e dtlm)
2972
2826
  {
2973
- const BYTE* const ip = (const BYTE*) src;
2827
+ const BYTE* ip = (const BYTE*) src;
2974
2828
  const BYTE* const iend = ip + srcSize;
2975
2829
 
2976
2830
  ZSTD_window_update(&ms->window, src, srcSize);
2977
2831
  ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
2978
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
+
2979
2838
  /* Assert that we the ms params match the params we're being given */
2980
2839
  ZSTD_assertEqualCParams(params->cParams, ms->cParams);
2981
2840
 
2982
2841
  if (srcSize <= HASH_READ_SIZE) return 0;
2983
2842
 
2984
- switch(params->cParams.strategy)
2985
- {
2986
- case ZSTD_fast:
2987
- ZSTD_fillHashTable(ms, iend, dtlm);
2988
- break;
2989
- case ZSTD_dfast:
2990
- ZSTD_fillDoubleHashTable(ms, iend, dtlm);
2991
- 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;
2992
2847
 
2993
- case ZSTD_greedy:
2994
- case ZSTD_lazy:
2995
- case ZSTD_lazy2:
2996
- if (srcSize >= HASH_READ_SIZE)
2997
- ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
2998
- break;
2848
+ ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk);
2999
2849
 
3000
- case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
3001
- case ZSTD_btopt:
3002
- case ZSTD_btultra:
3003
- case ZSTD_btultra2:
3004
- if (srcSize >= HASH_READ_SIZE)
3005
- ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
3006
- break;
2850
+ if (params->ldmParams.enableLdm && ls != NULL)
2851
+ ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, &params->ldmParams);
3007
2852
 
3008
- default:
3009
- 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;
3010
2882
  }
3011
2883
 
3012
2884
  ms->nextToUpdate = (U32)(iend - ms->window.base);
@@ -3020,98 +2892,123 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
3020
2892
  NOTE: This behavior is not standard and could be improved in the future. */
3021
2893
  static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
3022
2894
  U32 s;
3023
- if (dictMaxSymbolValue < maxSymbolValue) return ERROR(dictionary_corrupted);
2895
+ RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols");
3024
2896
  for (s = 0; s <= maxSymbolValue; ++s) {
3025
- if (normalizedCounter[s] == 0) return ERROR(dictionary_corrupted);
2897
+ RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols");
3026
2898
  }
3027
2899
  return 0;
3028
2900
  }
3029
2901
 
3030
-
3031
- /* Dictionary format :
3032
- * See :
3033
- * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
3034
- */
3035
- /*! ZSTD_loadZstdDictionary() :
3036
- * @return : dictID, or an error code
3037
- * assumptions : magic number supposed already checked
3038
- * dictSize supposed > 8
3039
- */
3040
- static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
3041
- ZSTD_matchState_t* ms,
3042
- ZSTD_CCtx_params const* params,
3043
- const void* dict, size_t dictSize,
3044
- ZSTD_dictTableLoadMethod_e dtlm,
3045
- 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)
3046
2905
  {
3047
- const BYTE* dictPtr = (const BYTE*)dict;
2906
+ const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */
3048
2907
  const BYTE* const dictEnd = dictPtr + dictSize;
3049
- short offcodeNCount[MaxOff+1];
3050
- unsigned offcodeMaxValue = MaxOff;
3051
- size_t dictID;
2908
+ dictPtr += 8;
2909
+ bs->entropy.huf.repeatMode = HUF_repeat_check;
3052
2910
 
3053
- ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
3054
- assert(dictSize > 8);
3055
- 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);
3056
2915
 
3057
- dictPtr += 4; /* skip magic number */
3058
- dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
3059
- 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;
3060
2920
 
3061
- { unsigned maxSymbolValue = 255;
3062
- size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
3063
- if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
3064
- if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
2921
+ RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, "");
2922
+ RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, "");
3065
2923
  dictPtr += hufHeaderSize;
3066
2924
  }
3067
2925
 
3068
2926
  { unsigned offcodeLog;
3069
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
3070
- if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
3071
- if (offcodeLog > OffFSELog) return ERROR(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, "");
3072
2930
  /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
3073
2931
  /* fill all offset symbols to avoid garbage at end of table */
3074
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.offcodeCTable,
3075
- offcodeNCount, MaxOff, offcodeLog,
3076
- workspace, HUF_WORKSPACE_SIZE),
3077
- dictionary_corrupted);
2932
+ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
2933
+ bs->entropy.fse.offcodeCTable,
2934
+ offcodeNCount, MaxOff, offcodeLog,
2935
+ workspace, HUF_WORKSPACE_SIZE)),
2936
+ dictionary_corrupted, "");
3078
2937
  dictPtr += offcodeHeaderSize;
3079
2938
  }
3080
2939
 
3081
2940
  { short matchlengthNCount[MaxML+1];
3082
2941
  unsigned matchlengthMaxValue = MaxML, matchlengthLog;
3083
2942
  size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
3084
- if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
3085
- if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
2943
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
2944
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
3086
2945
  /* Every match length code must have non-zero probability */
3087
- CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
3088
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.matchlengthCTable,
3089
- matchlengthNCount, matchlengthMaxValue, matchlengthLog,
3090
- workspace, HUF_WORKSPACE_SIZE),
3091
- dictionary_corrupted);
2946
+ FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), "");
2947
+ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
2948
+ bs->entropy.fse.matchlengthCTable,
2949
+ matchlengthNCount, matchlengthMaxValue, matchlengthLog,
2950
+ workspace, HUF_WORKSPACE_SIZE)),
2951
+ dictionary_corrupted, "");
3092
2952
  dictPtr += matchlengthHeaderSize;
3093
2953
  }
3094
2954
 
3095
2955
  { short litlengthNCount[MaxLL+1];
3096
2956
  unsigned litlengthMaxValue = MaxLL, litlengthLog;
3097
2957
  size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
3098
- if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
3099
- if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
2958
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
2959
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
3100
2960
  /* Every literal length code must have non-zero probability */
3101
- CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
3102
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.fse.litlengthCTable,
3103
- litlengthNCount, litlengthMaxValue, litlengthLog,
3104
- workspace, HUF_WORKSPACE_SIZE),
3105
- dictionary_corrupted);
2961
+ FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), "");
2962
+ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
2963
+ bs->entropy.fse.litlengthCTable,
2964
+ litlengthNCount, litlengthMaxValue, litlengthLog,
2965
+ workspace, HUF_WORKSPACE_SIZE)),
2966
+ dictionary_corrupted, "");
3106
2967
  dictPtr += litlengthHeaderSize;
3107
2968
  }
3108
2969
 
3109
- if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
2970
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
3110
2971
  bs->rep[0] = MEM_readLE32(dictPtr+0);
3111
2972
  bs->rep[1] = MEM_readLE32(dictPtr+4);
3112
2973
  bs->rep[2] = MEM_readLE32(dictPtr+8);
3113
2974
  dictPtr += 12;
3114
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
+
3115
3012
  { size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
3116
3013
  U32 offcodeMax = MaxOff;
3117
3014
  if (dictContentSize <= ((U32)-1) - 128 KB) {
@@ -3119,19 +3016,19 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
3119
3016
  offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
3120
3017
  }
3121
3018
  /* All offset values <= dictContentSize + 128 KB must be representable */
3122
- CHECK_F (ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
3019
+ FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), "");
3123
3020
  /* All repCodes must be <= dictContentSize and != 0*/
3124
3021
  { U32 u;
3125
3022
  for (u=0; u<3; u++) {
3126
- if (bs->rep[u] == 0) return ERROR(dictionary_corrupted);
3127
- if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
3023
+ RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
3024
+ RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
3128
3025
  } }
3129
3026
 
3130
- bs->entropy.huf.repeatMode = HUF_repeat_valid;
3131
3027
  bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
3132
3028
  bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
3133
3029
  bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
3134
- CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
3030
+ FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
3031
+ ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
3135
3032
  return dictID;
3136
3033
  }
3137
3034
  }
@@ -3141,6 +3038,8 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
3141
3038
  static size_t
3142
3039
  ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
3143
3040
  ZSTD_matchState_t* ms,
3041
+ ldmState_t* ls,
3042
+ ZSTD_cwksp* ws,
3144
3043
  const ZSTD_CCtx_params* params,
3145
3044
  const void* dict, size_t dictSize,
3146
3045
  ZSTD_dictContentType_e dictContentType,
@@ -3148,28 +3047,35 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
3148
3047
  void* workspace)
3149
3048
  {
3150
3049
  DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
3151
- 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
+ }
3152
3054
 
3153
3055
  ZSTD_reset_compressedBlockState(bs);
3154
3056
 
3155
3057
  /* dict restricted modes */
3156
3058
  if (dictContentType == ZSTD_dct_rawContent)
3157
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
3059
+ return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm);
3158
3060
 
3159
3061
  if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
3160
3062
  if (dictContentType == ZSTD_dct_auto) {
3161
3063
  DEBUGLOG(4, "raw content dictionary detected");
3162
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
3064
+ return ZSTD_loadDictionaryContent(
3065
+ ms, ls, ws, params, dict, dictSize, dtlm);
3163
3066
  }
3164
- if (dictContentType == ZSTD_dct_fullDict)
3165
- return ERROR(dictionary_wrong);
3067
+ RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
3166
3068
  assert(0); /* impossible */
3167
3069
  }
3168
3070
 
3169
3071
  /* dict as full zstd dictionary */
3170
- return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, dtlm, workspace);
3072
+ return ZSTD_loadZstdDictionary(
3073
+ bs, ms, ws, params, dict, dictSize, dtlm, workspace);
3171
3074
  }
3172
3075
 
3076
+ #define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
3077
+ #define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6)
3078
+
3173
3079
  /*! ZSTD_compressBegin_internal() :
3174
3080
  * @return : 0, or an error code */
3175
3081
  static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
@@ -3177,26 +3083,37 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
3177
3083
  ZSTD_dictContentType_e dictContentType,
3178
3084
  ZSTD_dictTableLoadMethod_e dtlm,
3179
3085
  const ZSTD_CDict* cdict,
3180
- ZSTD_CCtx_params params, U64 pledgedSrcSize,
3086
+ const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
3181
3087
  ZSTD_buffered_policy_e zbuff)
3182
3088
  {
3183
- DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params.cParams.windowLog);
3089
+ DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
3184
3090
  /* params are supposed to be fully validated at this point */
3185
- assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3091
+ assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
3186
3092
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3187
-
3188
- 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) ) {
3189
3100
  return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
3190
3101
  }
3191
3102
 
3192
- CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
3193
- ZSTDcrp_continue, zbuff) );
3194
- {
3195
- size_t const dictID = ZSTD_compress_insertDictionary(
3196
- cctx->blockState.prevCBlock, &cctx->blockState.matchState,
3197
- &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
3198
- if (ZSTD_isError(dictID)) return dictID;
3199
- 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);
3200
3117
  cctx->dictID = (U32)dictID;
3201
3118
  }
3202
3119
  return 0;
@@ -3207,12 +3124,12 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
3207
3124
  ZSTD_dictContentType_e dictContentType,
3208
3125
  ZSTD_dictTableLoadMethod_e dtlm,
3209
3126
  const ZSTD_CDict* cdict,
3210
- ZSTD_CCtx_params params,
3127
+ const ZSTD_CCtx_params* params,
3211
3128
  unsigned long long pledgedSrcSize)
3212
3129
  {
3213
- DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
3130
+ DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog);
3214
3131
  /* compression parameters verification and optimization */
3215
- CHECK_F( ZSTD_checkCParams(params.cParams) );
3132
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , "");
3216
3133
  return ZSTD_compressBegin_internal(cctx,
3217
3134
  dict, dictSize, dictContentType, dtlm,
3218
3135
  cdict,
@@ -3227,21 +3144,21 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
3227
3144
  ZSTD_parameters params, unsigned long long pledgedSrcSize)
3228
3145
  {
3229
3146
  ZSTD_CCtx_params const cctxParams =
3230
- ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3147
+ ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
3231
3148
  return ZSTD_compressBegin_advanced_internal(cctx,
3232
3149
  dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
3233
3150
  NULL /*cdict*/,
3234
- cctxParams, pledgedSrcSize);
3151
+ &cctxParams, pledgedSrcSize);
3235
3152
  }
3236
3153
 
3237
3154
  size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
3238
3155
  {
3239
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3156
+ ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3240
3157
  ZSTD_CCtx_params const cctxParams =
3241
- ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3158
+ ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
3242
3159
  DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
3243
3160
  return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3244
- cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
3161
+ &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
3245
3162
  }
3246
3163
 
3247
3164
  size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
@@ -3260,12 +3177,12 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
3260
3177
  size_t fhSize = 0;
3261
3178
 
3262
3179
  DEBUGLOG(4, "ZSTD_writeEpilogue");
3263
- if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
3180
+ RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
3264
3181
 
3265
3182
  /* special case : empty frame */
3266
3183
  if (cctx->stage == ZSTDcs_init) {
3267
- fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
3268
- if (ZSTD_isError(fhSize)) return fhSize;
3184
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
3185
+ FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
3269
3186
  dstCapacity -= fhSize;
3270
3187
  op += fhSize;
3271
3188
  cctx->stage = ZSTDcs_ongoing;
@@ -3274,7 +3191,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
3274
3191
  if (cctx->stage != ZSTDcs_ending) {
3275
3192
  /* write one last empty block, make it the "last" block */
3276
3193
  U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
3277
- if (dstCapacity<4) return ERROR(dstSize_tooSmall);
3194
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue");
3278
3195
  MEM_writeLE32(op, cBlockHeader24);
3279
3196
  op += ZSTD_blockHeaderSize;
3280
3197
  dstCapacity -= ZSTD_blockHeaderSize;
@@ -3282,7 +3199,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
3282
3199
 
3283
3200
  if (cctx->appliedParams.fParams.checksumFlag) {
3284
3201
  U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
3285
- if (dstCapacity<4) return ERROR(dstSize_tooSmall);
3202
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
3286
3203
  DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
3287
3204
  MEM_writeLE32(op, checksum);
3288
3205
  op += 4;
@@ -3300,18 +3217,20 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
3300
3217
  size_t const cSize = ZSTD_compressContinue_internal(cctx,
3301
3218
  dst, dstCapacity, src, srcSize,
3302
3219
  1 /* frame mode */, 1 /* last chunk */);
3303
- if (ZSTD_isError(cSize)) return cSize;
3220
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed");
3304
3221
  endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
3305
- if (ZSTD_isError(endResult)) return endResult;
3222
+ FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed");
3306
3223
  assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
3307
3224
  if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
3308
3225
  ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
3309
3226
  DEBUGLOG(4, "end of frame : controlling src size");
3310
- if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
3311
- DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
3312
- (unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize);
3313
- return ERROR(srcSize_wrong);
3314
- } }
3227
+ RETURN_ERROR_IF(
3228
+ cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
3229
+ srcSize_wrong,
3230
+ "error : pledgedSrcSize = %u, while realSrcSize = %u",
3231
+ (unsigned)cctx->pledgedSrcSizePlusOne-1,
3232
+ (unsigned)cctx->consumedSrcSize);
3233
+ }
3315
3234
  return cSize + endResult;
3316
3235
  }
3317
3236
 
@@ -3320,16 +3239,16 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
3320
3239
  void* dst, size_t dstCapacity,
3321
3240
  const void* src, size_t srcSize,
3322
3241
  const void* dict,size_t dictSize,
3323
- ZSTD_parameters params)
3242
+ const ZSTD_parameters* params)
3324
3243
  {
3325
3244
  ZSTD_CCtx_params const cctxParams =
3326
- ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3245
+ ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params);
3327
3246
  DEBUGLOG(4, "ZSTD_compress_internal");
3328
3247
  return ZSTD_compress_advanced_internal(cctx,
3329
3248
  dst, dstCapacity,
3330
3249
  src, srcSize,
3331
3250
  dict, dictSize,
3332
- cctxParams);
3251
+ &cctxParams);
3333
3252
  }
3334
3253
 
3335
3254
  size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
@@ -3339,12 +3258,12 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
3339
3258
  ZSTD_parameters params)
3340
3259
  {
3341
3260
  DEBUGLOG(4, "ZSTD_compress_advanced");
3342
- CHECK_F(ZSTD_checkCParams(params.cParams));
3261
+ FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
3343
3262
  return ZSTD_compress_internal(cctx,
3344
3263
  dst, dstCapacity,
3345
3264
  src, srcSize,
3346
3265
  dict, dictSize,
3347
- params);
3266
+ &params);
3348
3267
  }
3349
3268
 
3350
3269
  /* Internal */
@@ -3353,12 +3272,12 @@ size_t ZSTD_compress_advanced_internal(
3353
3272
  void* dst, size_t dstCapacity,
3354
3273
  const void* src, size_t srcSize,
3355
3274
  const void* dict,size_t dictSize,
3356
- ZSTD_CCtx_params params)
3275
+ const ZSTD_CCtx_params* params)
3357
3276
  {
3358
3277
  DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
3359
- CHECK_F( ZSTD_compressBegin_internal(cctx,
3278
+ FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
3360
3279
  dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
3361
- params, srcSize, ZSTDb_not_buffered) );
3280
+ params, srcSize, ZSTDb_not_buffered) , "");
3362
3281
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3363
3282
  }
3364
3283
 
@@ -3368,10 +3287,11 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
3368
3287
  const void* dict, size_t dictSize,
3369
3288
  int compressionLevel)
3370
3289
  {
3371
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize + (!srcSize), dict ? dictSize : 0);
3372
- 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);
3373
3293
  assert(params.fParams.contentSizeFlag == 1);
3374
- 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);
3375
3295
  }
3376
3296
 
3377
3297
  size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
@@ -3406,13 +3326,16 @@ size_t ZSTD_estimateCDictSize_advanced(
3406
3326
  ZSTD_dictLoadMethod_e dictLoadMethod)
3407
3327
  {
3408
3328
  DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
3409
- return sizeof(ZSTD_CDict) + HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
3410
- + (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 *))));
3411
3334
  }
3412
3335
 
3413
3336
  size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
3414
3337
  {
3415
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3338
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3416
3339
  return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
3417
3340
  }
3418
3341
 
@@ -3420,7 +3343,9 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
3420
3343
  {
3421
3344
  if (cdict==NULL) return 0; /* support sizeof on NULL */
3422
3345
  DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict));
3423
- 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);
3424
3349
  }
3425
3350
 
3426
3351
  static size_t ZSTD_initCDict_internal(
@@ -3434,28 +3359,29 @@ static size_t ZSTD_initCDict_internal(
3434
3359
  assert(!ZSTD_checkCParams(cParams));
3435
3360
  cdict->matchState.cParams = cParams;
3436
3361
  if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
3437
- cdict->dictBuffer = NULL;
3438
3362
  cdict->dictContent = dictBuffer;
3439
3363
  } else {
3440
- void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
3441
- 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!");
3442
3366
  cdict->dictContent = internalBuffer;
3443
- if (!internalBuffer) return ERROR(memory_allocation);
3444
3367
  memcpy(internalBuffer, dictBuffer, dictSize);
3445
3368
  }
3446
3369
  cdict->dictContentSize = dictSize;
3447
3370
 
3371
+ cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
3372
+
3373
+
3448
3374
  /* Reset the state to no dictionary */
3449
3375
  ZSTD_reset_compressedBlockState(&cdict->cBlockState);
3450
- { void* const end = ZSTD_reset_matchState(
3451
- &cdict->matchState,
3452
- (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32,
3453
- &cParams, ZSTDcrp_continue, /* forCCtx */ 0);
3454
- assert(end == (char*)cdict->workspace + cdict->workspaceSize);
3455
- (void)end;
3456
- }
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), "");
3457
3383
  /* (Maybe) load the dictionary
3458
- * Skips loading the dictionary if it is <= 8 bytes.
3384
+ * Skips loading the dictionary if it is < 8 bytes.
3459
3385
  */
3460
3386
  { ZSTD_CCtx_params params;
3461
3387
  memset(&params, 0, sizeof(params));
@@ -3463,10 +3389,10 @@ static size_t ZSTD_initCDict_internal(
3463
3389
  params.fParams.contentSizeFlag = 1;
3464
3390
  params.cParams = cParams;
3465
3391
  { size_t const dictID = ZSTD_compress_insertDictionary(
3466
- &cdict->cBlockState, &cdict->matchState, &params,
3467
- cdict->dictContent, cdict->dictContentSize,
3468
- dictContentType, ZSTD_dtlm_full, cdict->workspace);
3469
- if (ZSTD_isError(dictID)) return 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");
3470
3396
  assert(dictID <= (size_t)(U32)-1);
3471
3397
  cdict->dictID = (U32)dictID;
3472
3398
  }
@@ -3483,18 +3409,29 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3483
3409
  DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType);
3484
3410
  if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
3485
3411
 
3486
- { ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
3487
- 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*))));
3488
3418
  void* const workspace = ZSTD_malloc(workspaceSize, customMem);
3419
+ ZSTD_cwksp ws;
3420
+ ZSTD_CDict* cdict;
3489
3421
 
3490
- if (!cdict || !workspace) {
3491
- ZSTD_free(cdict, customMem);
3422
+ if (!workspace) {
3492
3423
  ZSTD_free(workspace, customMem);
3493
3424
  return NULL;
3494
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);
3495
3432
  cdict->customMem = customMem;
3496
- cdict->workspace = workspace;
3497
- cdict->workspaceSize = workspaceSize;
3433
+ cdict->compressionLevel = 0; /* signals advanced API usage */
3434
+
3498
3435
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3499
3436
  dictBuffer, dictSize,
3500
3437
  dictLoadMethod, dictContentType,
@@ -3509,15 +3446,18 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3509
3446
 
3510
3447
  ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
3511
3448
  {
3512
- ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3513
- return ZSTD_createCDict_advanced(dict, dictSize,
3514
- ZSTD_dlm_byCopy, ZSTD_dct_auto,
3515
- 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;
3516
3456
  }
3517
3457
 
3518
3458
  ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
3519
3459
  {
3520
- ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3460
+ ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
3521
3461
  return ZSTD_createCDict_advanced(dict, dictSize,
3522
3462
  ZSTD_dlm_byRef, ZSTD_dct_auto,
3523
3463
  cParams, ZSTD_defaultCMem);
@@ -3527,9 +3467,11 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
3527
3467
  {
3528
3468
  if (cdict==NULL) return 0; /* support free on NULL */
3529
3469
  { ZSTD_customMem const cMem = cdict->customMem;
3530
- ZSTD_free(cdict->workspace, cMem);
3531
- ZSTD_free(cdict->dictBuffer, cMem);
3532
- 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
+ }
3533
3475
  return 0;
3534
3476
  }
3535
3477
  }
@@ -3555,28 +3497,30 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
3555
3497
  ZSTD_compressionParameters cParams)
3556
3498
  {
3557
3499
  size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
3558
- size_t const neededSize = sizeof(ZSTD_CDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize)
3559
- + HUF_WORKSPACE_SIZE + matchStateSize;
3560
- ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
3561
- 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
+
3562
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
+
3563
3517
  DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
3564
3518
  (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
3565
3519
  if (workspaceSize < neededSize) return NULL;
3566
3520
 
3567
- if (dictLoadMethod == ZSTD_dlm_byCopy) {
3568
- memcpy(cdict+1, dict, dictSize);
3569
- dict = cdict+1;
3570
- ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
3571
- } else {
3572
- ptr = cdict+1;
3573
- }
3574
- cdict->workspace = ptr;
3575
- cdict->workspaceSize = HUF_WORKSPACE_SIZE + matchStateSize;
3576
-
3577
3521
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3578
3522
  dict, dictSize,
3579
- ZSTD_dlm_byRef, dictContentType,
3523
+ dictLoadMethod, dictContentType,
3580
3524
  cParams) ))
3581
3525
  return NULL;
3582
3526
 
@@ -3596,9 +3540,17 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
3596
3540
  ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
3597
3541
  {
3598
3542
  DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
3599
- if (cdict==NULL) return ERROR(dictionary_wrong);
3543
+ RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
3600
3544
  { ZSTD_CCtx_params params = cctx->requestedParams;
3601
- 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);
3602
3554
  /* Increase window log to fit the entire dictionary and source if the
3603
3555
  * source size is known. Limit the increase to 19, which is the
3604
3556
  * window log for compression level 1 with the largest source size.
@@ -3612,7 +3564,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
3612
3564
  return ZSTD_compressBegin_internal(cctx,
3613
3565
  NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
3614
3566
  cdict,
3615
- params, pledgedSrcSize,
3567
+ &params, pledgedSrcSize,
3616
3568
  ZSTDb_not_buffered);
3617
3569
  }
3618
3570
  }
@@ -3632,7 +3584,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
3632
3584
  const void* src, size_t srcSize,
3633
3585
  const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
3634
3586
  {
3635
- CHECK_F (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 */
3636
3588
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
3637
3589
  }
3638
3590
 
@@ -3700,11 +3652,11 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
3700
3652
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3701
3653
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3702
3654
 
3703
- CHECK_F( ZSTD_compressBegin_internal(cctx,
3655
+ FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
3704
3656
  dict, dictSize, dictContentType, ZSTD_dtlm_fast,
3705
3657
  cdict,
3706
- params, pledgedSrcSize,
3707
- ZSTDb_buffered) );
3658
+ &params, pledgedSrcSize,
3659
+ ZSTDb_buffered) , "");
3708
3660
 
3709
3661
  cctx->inToCompress = 0;
3710
3662
  cctx->inBuffPos = 0;
@@ -3718,13 +3670,17 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
3718
3670
 
3719
3671
  /* ZSTD_resetCStream():
3720
3672
  * pledgedSrcSize == 0 means "unknown" */
3721
- size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
3673
+ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
3722
3674
  {
3723
- ZSTD_CCtx_params params = zcs->requestedParams;
3675
+ /* temporary : 0 interpreted as "unknown" during transition period.
3676
+ * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
3677
+ * 0 will be interpreted as "empty" in the future.
3678
+ */
3679
+ U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3724
3680
  DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
3725
- if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
3726
- params.fParams.contentSizeFlag = 1;
3727
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
3681
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3682
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3683
+ return 0;
3728
3684
  }
3729
3685
 
3730
3686
  /*! ZSTD_initCStream_internal() :
@@ -3733,35 +3689,22 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
3733
3689
  * Assumption 2 : either dict, or cdict, is defined, not both */
3734
3690
  size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3735
3691
  const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3736
- ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
3692
+ const ZSTD_CCtx_params* params,
3693
+ unsigned long long pledgedSrcSize)
3737
3694
  {
3738
3695
  DEBUGLOG(4, "ZSTD_initCStream_internal");
3739
- params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
3740
- assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
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;
3741
3700
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3742
-
3743
- if (dict && dictSize >= 8) {
3744
- DEBUGLOG(4, "loading dictionary of size %u", (unsigned)dictSize);
3745
- if (zcs->staticSize) { /* static CCtx : never uses malloc */
3746
- /* incompatible with internal cdict creation */
3747
- return ERROR(memory_allocation);
3748
- }
3749
- ZSTD_freeCDict(zcs->cdictLocal);
3750
- zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
3751
- ZSTD_dlm_byCopy, ZSTD_dct_auto,
3752
- params.cParams, zcs->customMem);
3753
- zcs->cdict = zcs->cdictLocal;
3754
- if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
3701
+ if (dict) {
3702
+ FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
3755
3703
  } else {
3756
- if (cdict) {
3757
- params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict; it includes windowLog */
3758
- }
3759
- ZSTD_freeCDict(zcs->cdictLocal);
3760
- zcs->cdictLocal = NULL;
3761
- zcs->cdict = cdict;
3704
+ /* Dictionary is cleared if !cdict */
3705
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
3762
3706
  }
3763
-
3764
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
3707
+ return 0;
3765
3708
  }
3766
3709
 
3767
3710
  /* ZSTD_initCStream_usingCDict_advanced() :
@@ -3772,58 +3715,76 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
3772
3715
  unsigned long long pledgedSrcSize)
3773
3716
  {
3774
3717
  DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
3775
- if (!cdict) return ERROR(dictionary_wrong); /* cannot handle NULL cdict (does not know what to do) */
3776
- { ZSTD_CCtx_params params = zcs->requestedParams;
3777
- params.cParams = ZSTD_getCParamsFromCDict(cdict);
3778
- params.fParams = fParams;
3779
- return ZSTD_initCStream_internal(zcs,
3780
- NULL, 0, cdict,
3781
- params, pledgedSrcSize);
3782
- }
3718
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3719
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3720
+ zcs->requestedParams.fParams = fParams;
3721
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
3722
+ return 0;
3783
3723
  }
3784
3724
 
3785
3725
  /* note : cdict must outlive compression session */
3786
3726
  size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
3787
3727
  {
3788
- ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksum */, 0 /* hideDictID */ };
3789
3728
  DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
3790
- return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */
3729
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
3730
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
3731
+ return 0;
3791
3732
  }
3792
3733
 
3793
3734
 
3794
3735
  /* ZSTD_initCStream_advanced() :
3795
3736
  * pledgedSrcSize must be exact.
3796
3737
  * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
3797
- * 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. */
3798
3739
  size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
3799
3740
  const void* dict, size_t dictSize,
3800
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
3741
+ ZSTD_parameters params, unsigned long long pss)
3801
3742
  {
3802
- DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u",
3803
- (unsigned)pledgedSrcSize, params.fParams.contentSizeFlag);
3804
- CHECK_F( ZSTD_checkCParams(params.cParams) );
3805
- if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
3806
- zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3807
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, zcs->requestedParams, pledgedSrcSize);
3743
+ /* for compatibility with older programs relying on this behavior.
3744
+ * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.
3745
+ * This line will be removed in the future.
3746
+ */
3747
+ U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3748
+ DEBUGLOG(4, "ZSTD_initCStream_advanced");
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) , "");
3754
+ return 0;
3808
3755
  }
3809
3756
 
3810
3757
  size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3811
3758
  {
3812
- ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
3813
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, zcs->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN);
3759
+ DEBUGLOG(4, "ZSTD_initCStream_usingDict");
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) , "");
3763
+ return 0;
3814
3764
  }
3815
3765
 
3816
3766
  size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
3817
3767
  {
3818
- U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */
3819
- ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
3820
- return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, zcs->requestedParams, pledgedSrcSize);
3768
+ /* temporary : 0 interpreted as "unknown" during transition period.
3769
+ * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
3770
+ * 0 will be interpreted as "empty" in the future.
3771
+ */
3772
+ U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
3773
+ DEBUGLOG(4, "ZSTD_initCStream_srcSize");
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) , "");
3778
+ return 0;
3821
3779
  }
3822
3780
 
3823
3781
  size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
3824
3782
  {
3825
3783
  DEBUGLOG(4, "ZSTD_initCStream");
3826
- return ZSTD_initCStream_srcSize(zcs, compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN);
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) , "");
3787
+ return 0;
3827
3788
  }
3828
3789
 
3829
3790
  /*====== Compression ======*/
@@ -3835,29 +3796,21 @@ static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
3835
3796
  return hintInSize;
3836
3797
  }
3837
3798
 
3838
- static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
3839
- const void* src, size_t srcSize)
3840
- {
3841
- size_t const length = MIN(dstCapacity, srcSize);
3842
- if (length) memcpy(dst, src, length);
3843
- return length;
3844
- }
3845
-
3846
3799
  /** ZSTD_compressStream_generic():
3847
3800
  * internal function for all *compressStream*() variants
3848
3801
  * non-static, because can be called from zstdmt_compress.c
3849
3802
  * @return : hint size for next input */
3850
- size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3851
- ZSTD_outBuffer* output,
3852
- ZSTD_inBuffer* input,
3853
- ZSTD_EndDirective const flushMode)
3803
+ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3804
+ ZSTD_outBuffer* output,
3805
+ ZSTD_inBuffer* input,
3806
+ ZSTD_EndDirective const flushMode)
3854
3807
  {
3855
3808
  const char* const istart = (const char*)input->src;
3856
- const char* const iend = istart + input->size;
3857
- 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;
3858
3811
  char* const ostart = (char*)output->dst;
3859
- char* const oend = ostart + output->size;
3860
- 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;
3861
3814
  U32 someMoreWork = 1;
3862
3815
 
3863
3816
  /* check expectations */
@@ -3873,8 +3826,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3873
3826
  switch(zcs->streamStage)
3874
3827
  {
3875
3828
  case zcss_init:
3876
- /* call ZSTD_initCStream() first ! */
3877
- return ERROR(init_missing);
3829
+ RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
3878
3830
 
3879
3831
  case zcss_load:
3880
3832
  if ( (flushMode == ZSTD_e_end)
@@ -3884,7 +3836,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3884
3836
  size_t const cSize = ZSTD_compressEnd(zcs,
3885
3837
  op, oend-op, ip, iend-ip);
3886
3838
  DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
3887
- if (ZSTD_isError(cSize)) return cSize;
3839
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed");
3888
3840
  ip = iend;
3889
3841
  op += cSize;
3890
3842
  zcs->frameEnded = 1;
@@ -3897,7 +3849,8 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3897
3849
  zcs->inBuff + zcs->inBuffPos, toLoad,
3898
3850
  ip, iend-ip);
3899
3851
  zcs->inBuffPos += loaded;
3900
- ip += loaded;
3852
+ if (loaded != 0)
3853
+ ip += loaded;
3901
3854
  if ( (flushMode == ZSTD_e_continue)
3902
3855
  && (zcs->inBuffPos < zcs->inBuffTarget) ) {
3903
3856
  /* not enough input to fill full block : stop here */
@@ -3925,7 +3878,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3925
3878
  zcs->inBuff + zcs->inToCompress, iSize) :
3926
3879
  ZSTD_compressContinue(zcs, cDst, oSize,
3927
3880
  zcs->inBuff + zcs->inToCompress, iSize);
3928
- if (ZSTD_isError(cSize)) return cSize;
3881
+ FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
3929
3882
  zcs->frameEnded = lastBlock;
3930
3883
  /* prepare next block */
3931
3884
  zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
@@ -3953,11 +3906,12 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3953
3906
  case zcss_flush:
3954
3907
  DEBUGLOG(5, "flush stage");
3955
3908
  { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
3956
- size_t const flushed = ZSTD_limitCopy(op, oend-op,
3909
+ size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
3957
3910
  zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
3958
3911
  DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
3959
3912
  (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
3960
- op += flushed;
3913
+ if (flushed)
3914
+ op += flushed;
3961
3915
  zcs->outBuffFlushedSize += flushed;
3962
3916
  if (toFlush!=flushed) {
3963
3917
  /* flush not fully completed, presumably because dst is too small */
@@ -4001,7 +3955,7 @@ static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
4001
3955
 
4002
3956
  size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
4003
3957
  {
4004
- CHECK_F( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
3958
+ FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , "");
4005
3959
  return ZSTD_nextInputSizeHint_MTorST(zcs);
4006
3960
  }
4007
3961
 
@@ -4013,14 +3967,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4013
3967
  {
4014
3968
  DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
4015
3969
  /* check conditions */
4016
- if (output->pos > output->size) return ERROR(GENERIC);
4017
- if (input->pos > input->size) return ERROR(GENERIC);
3970
+ RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer");
3971
+ RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer");
4018
3972
  assert(cctx!=NULL);
4019
3973
 
4020
3974
  /* transparent initialization stage */
4021
3975
  if (cctx->streamStage == zcss_init) {
4022
3976
  ZSTD_CCtx_params params = cctx->requestedParams;
4023
3977
  ZSTD_prefixDict const prefixDict = cctx->prefixDict;
3978
+ FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
4024
3979
  memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
4025
3980
  assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
4026
3981
  DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
@@ -4038,23 +3993,23 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4038
3993
  if (cctx->mtctx == NULL) {
4039
3994
  DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
4040
3995
  params.nbWorkers);
4041
- cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
4042
- if (cctx->mtctx == NULL) return ERROR(memory_allocation);
3996
+ cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem);
3997
+ RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
4043
3998
  }
4044
3999
  /* mt compression */
4045
4000
  DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
4046
- CHECK_F( ZSTDMT_initCStream_internal(
4001
+ FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
4047
4002
  cctx->mtctx,
4048
- prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
4049
- cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
4003
+ prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
4004
+ cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
4050
4005
  cctx->streamStage = zcss_load;
4051
4006
  cctx->appliedParams.nbWorkers = params.nbWorkers;
4052
4007
  } else
4053
4008
  #endif
4054
- { CHECK_F( ZSTD_resetCStream_internal(cctx,
4009
+ { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
4055
4010
  prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
4056
4011
  cctx->cdict,
4057
- params, cctx->pledgedSrcSizePlusOne-1) );
4012
+ params, cctx->pledgedSrcSizePlusOne-1) , "");
4058
4013
  assert(cctx->streamStage == zcss_load);
4059
4014
  assert(cctx->appliedParams.nbWorkers == 0);
4060
4015
  } }
@@ -4063,20 +4018,30 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
4063
4018
  /* compression stage */
4064
4019
  #ifdef ZSTD_MULTITHREAD
4065
4020
  if (cctx->appliedParams.nbWorkers > 0) {
4021
+ int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
4022
+ size_t flushMin;
4023
+ assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
4066
4024
  if (cctx->cParamsChanged) {
4067
4025
  ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
4068
4026
  cctx->cParamsChanged = 0;
4069
4027
  }
4070
- { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
4028
+ do {
4029
+ flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
4071
4030
  if ( ZSTD_isError(flushMin)
4072
4031
  || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
4073
4032
  ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
4074
4033
  }
4075
- DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
4076
- return flushMin;
4077
- } }
4034
+ FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
4035
+ } while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
4036
+ DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
4037
+ /* Either we don't require maximum forward progress, we've finished the
4038
+ * flush, or we are out of output space.
4039
+ */
4040
+ assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
4041
+ return flushMin;
4042
+ }
4078
4043
  #endif
4079
- CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
4044
+ FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
4080
4045
  DEBUGLOG(5, "completed ZSTD_compressStream2");
4081
4046
  return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
4082
4047
  }
@@ -4100,6 +4065,7 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
4100
4065
  void* dst, size_t dstCapacity,
4101
4066
  const void* src, size_t srcSize)
4102
4067
  {
4068
+ DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
4103
4069
  ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
4104
4070
  { size_t oPos = 0;
4105
4071
  size_t iPos = 0;
@@ -4107,10 +4073,10 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
4107
4073
  dst, dstCapacity, &oPos,
4108
4074
  src, srcSize, &iPos,
4109
4075
  ZSTD_e_end);
4110
- if (ZSTD_isError(result)) return result;
4076
+ FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
4111
4077
  if (result != 0) { /* compression not completed, due to lack of output space */
4112
4078
  assert(oPos == dstCapacity);
4113
- return ERROR(dstSize_tooSmall);
4079
+ RETURN_ERROR(dstSize_tooSmall, "");
4114
4080
  }
4115
4081
  assert(iPos == srcSize); /* all input is expected consumed */
4116
4082
  return oPos;
@@ -4132,11 +4098,11 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
4132
4098
  {
4133
4099
  ZSTD_inBuffer input = { NULL, 0, 0 };
4134
4100
  size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
4135
- CHECK_F( remainingToFlush );
4101
+ FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed");
4136
4102
  if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
4137
4103
  /* single thread mode : attempt to calculate remaining to flush more precisely */
4138
4104
  { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
4139
- 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);
4140
4106
  size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
4141
4107
  DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
4142
4108
  return toFlush;
@@ -4151,13 +4117,13 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
4151
4117
  int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
4152
4118
 
4153
4119
  static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
4154
- { /* "default" - guarantees a monotonically increasing memory budget */
4120
+ { /* "default" - for any srcSize > 256 KB */
4155
4121
  /* W, C, H, S, L, TL, strat */
4156
4122
  { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
4157
4123
  { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
4158
4124
  { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
4159
- { 21, 16, 17, 1, 5, 1, ZSTD_dfast }, /* level 3 */
4160
- { 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 */
4161
4127
  { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */
4162
4128
  { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */
4163
4129
  { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */
@@ -4181,8 +4147,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4181
4147
  /* W, C, H, S, L, T, strat */
4182
4148
  { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
4183
4149
  { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
4184
- { 18, 14, 14, 1, 5, 1, ZSTD_dfast }, /* level 2 */
4185
- { 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 */
4186
4152
  { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
4187
4153
  { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
4188
4154
  { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
@@ -4208,8 +4174,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4208
4174
  { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
4209
4175
  { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
4210
4176
  { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
4211
- { 17, 15, 16, 2, 5, 1, ZSTD_dfast }, /* level 3 */
4212
- { 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 */
4213
4179
  { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
4214
4180
  { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
4215
4181
  { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
@@ -4234,7 +4200,7 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4234
4200
  { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
4235
4201
  { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
4236
4202
  { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
4237
- { 14, 14, 15, 2, 4, 1, ZSTD_dfast }, /* level 3 */
4203
+ { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
4238
4204
  { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
4239
4205
  { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
4240
4206
  { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
@@ -4257,34 +4223,56 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
4257
4223
  },
4258
4224
  };
4259
4225
 
4260
- /*! ZSTD_getCParams() :
4261
- * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
4262
- * Size values are optional, provide 0 if not known or unused */
4263
- ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
4226
+ /*! ZSTD_getCParams_internal() :
4227
+ * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and 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)
4264
4231
  {
4265
- size_t const addedSize = srcSizeHint ? 0 : 500;
4266
- U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1;
4267
- U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
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;
4235
+ U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
4268
4236
  int row = compressionLevel;
4269
- DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
4237
+ DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
4270
4238
  if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
4271
4239
  if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
4272
4240
  if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
4273
4241
  { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
4274
4242
  if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
4243
+ /* refine parameters based on srcSize & dictSize */
4275
4244
  return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize);
4276
4245
  }
4277
4246
  }
4278
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
+
4279
4257
  /*! ZSTD_getParams() :
4280
- * same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`).
4281
- * All fields of `ZSTD_frameParameters` are set to default (0) */
4282
- ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
4258
+ * same idea as ZSTD_getCParams()
4259
+ * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
4260
+ * Fields of `ZSTD_frameParameters` are set to default values */
4261
+ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
4283
4262
  ZSTD_parameters params;
4284
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
4263
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
4285
4264
  DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
4286
4265
  memset(&params, 0, sizeof(params));
4287
4266
  params.cParams = cParams;
4288
4267
  params.fParams.contentSizeFlag = 1;
4289
4268
  return params;
4290
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
+ }