zstd-ruby 1.3.1.1 → 1.3.2.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/.gitignore +1 -0
  4. data/ext/zstdruby/libzstd/Makefile +40 -26
  5. data/ext/zstdruby/libzstd/README.md +68 -45
  6. data/ext/zstdruby/libzstd/common/bitstream.h +35 -23
  7. data/ext/zstdruby/libzstd/common/compiler.h +1 -0
  8. data/ext/zstdruby/libzstd/common/error_private.c +4 -2
  9. data/ext/zstdruby/libzstd/common/error_private.h +4 -4
  10. data/ext/zstdruby/libzstd/common/fse.h +1 -1
  11. data/ext/zstdruby/libzstd/common/huf.h +1 -1
  12. data/ext/zstdruby/libzstd/common/mem.h +1 -0
  13. data/ext/zstdruby/libzstd/common/pool.c +61 -46
  14. data/ext/zstdruby/libzstd/common/pool.h +4 -0
  15. data/ext/zstdruby/libzstd/common/threading.c +11 -15
  16. data/ext/zstdruby/libzstd/common/threading.h +52 -32
  17. data/ext/zstdruby/libzstd/common/zstd_common.c +2 -2
  18. data/ext/zstdruby/libzstd/common/zstd_errors.h +3 -1
  19. data/ext/zstdruby/libzstd/common/zstd_internal.h +95 -21
  20. data/ext/zstdruby/libzstd/compress/fse_compress.c +3 -1
  21. data/ext/zstdruby/libzstd/compress/huf_compress.c +4 -3
  22. data/ext/zstdruby/libzstd/compress/zstd_compress.c +922 -2102
  23. data/ext/zstdruby/libzstd/compress/zstd_compress.h +307 -0
  24. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +308 -0
  25. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +28 -0
  26. data/ext/zstdruby/libzstd/compress/zstd_fast.c +242 -0
  27. data/ext/zstdruby/libzstd/compress/zstd_fast.h +30 -0
  28. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +749 -0
  29. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +38 -0
  30. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +707 -0
  31. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +67 -0
  32. data/ext/zstdruby/libzstd/compress/zstd_opt.c +957 -0
  33. data/ext/zstdruby/libzstd/compress/zstd_opt.h +14 -922
  34. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +210 -133
  35. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +20 -3
  36. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +373 -196
  37. data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -0
  38. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -0
  39. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
  40. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -0
  41. data/ext/zstdruby/libzstd/dictBuilder/cover.c +33 -22
  42. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +8 -5
  43. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -0
  44. data/ext/zstdruby/libzstd/dll/example/Makefile +5 -5
  45. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -0
  46. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -0
  47. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -0
  48. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -0
  49. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -0
  50. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -0
  51. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -0
  52. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -0
  53. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -0
  54. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -0
  55. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -0
  56. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -0
  57. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -0
  58. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -0
  59. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -0
  60. data/ext/zstdruby/libzstd/zstd.h +366 -118
  61. data/lib/zstd-ruby/version.rb +1 -1
  62. metadata +11 -1
@@ -5,6 +5,7 @@
5
5
  * This source code is licensed under both the BSD-style license (found in the
6
6
  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
7
  * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
 
@@ -15,8 +16,7 @@
15
16
  #include <stdlib.h> /* malloc, calloc, free */
16
17
  #include <string.h> /* memset */
17
18
  #include "error_private.h"
18
- #define ZSTD_STATIC_LINKING_ONLY
19
- #include "zstd.h"
19
+ #include "zstd_internal.h"
20
20
 
21
21
 
22
22
  /*-****************************************
@@ -5,6 +5,7 @@
5
5
  * This source code is licensed under both the BSD-style license (found in the
6
6
  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
7
  * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
  #ifndef ZSTD_ERRORS_H_398273423
@@ -62,9 +63,10 @@ typedef enum {
62
63
  ZSTD_error_memory_allocation = 64,
63
64
  ZSTD_error_dstSize_tooSmall = 70,
64
65
  ZSTD_error_srcSize_wrong = 72,
66
+ /* following error codes are not stable and may be removed or changed in a future version */
65
67
  ZSTD_error_frameIndex_tooLarge = 100,
66
68
  ZSTD_error_seekableIO = 102,
67
- ZSTD_error_maxCode = 120 /* never EVER use this value directly, it may change in future versions! Use ZSTD_isError() instead */
69
+ ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
68
70
  } ZSTD_ErrorCode;
69
71
 
70
72
  /*! ZSTD_getErrorCode() :
@@ -5,6 +5,7 @@
5
5
  * This source code is licensed under both the BSD-style license (found in the
6
6
  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
7
  * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
  #ifndef ZSTD_CCOMMON_H_MODULE
@@ -29,6 +30,11 @@
29
30
  #include "xxhash.h" /* XXH_reset, update, digest */
30
31
 
31
32
 
33
+ #if defined (__cplusplus)
34
+ extern "C" {
35
+ #endif
36
+
37
+
32
38
  /*-*************************************
33
39
  * Debug
34
40
  ***************************************/
@@ -96,9 +102,13 @@ static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
96
102
  #define BIT0 1
97
103
 
98
104
  #define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
105
+ #define ZSTD_WINDOWLOG_DEFAULTMAX 27 /* Default maximum allowed window log */
99
106
  static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
100
107
  static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
101
108
 
109
+ #define ZSTD_FRAMEIDSIZE 4
110
+ static const size_t ZSTD_frameIdSize = ZSTD_FRAMEIDSIZE; /* magic number size */
111
+
102
112
  #define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
103
113
  static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
104
114
  typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
@@ -117,7 +127,8 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
117
127
  #define MaxLit ((1<<Litbits) - 1)
118
128
  #define MaxML 52
119
129
  #define MaxLL 35
120
- #define MaxOff 28
130
+ #define DefaultMaxOff 28
131
+ #define MaxOff 31
121
132
  #define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
122
133
  #define MLFSELog 9
123
134
  #define LLFSELog 9
@@ -143,8 +154,8 @@ static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1,
143
154
  #define ML_DEFAULTNORMLOG 6 /* for static allocation */
144
155
  static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
145
156
 
146
- static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
147
- 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
157
+ static const S16 OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
158
+ 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
148
159
  #define OF_DEFAULTNORMLOG 5 /* for static allocation */
149
160
  static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
150
161
 
@@ -243,6 +254,26 @@ typedef struct {
243
254
  const BYTE* cachedLiterals;
244
255
  } optState_t;
245
256
 
257
+ typedef struct {
258
+ U32 offset;
259
+ U32 checksum;
260
+ } ldmEntry_t;
261
+
262
+ typedef struct {
263
+ ldmEntry_t* hashTable;
264
+ BYTE* bucketOffsets; /* Next position in bucket to insert entry */
265
+ U64 hashPower; /* Used to compute the rolling hash.
266
+ * Depends on ldmParams.minMatchLength */
267
+ } ldmState_t;
268
+
269
+ typedef struct {
270
+ U32 enableLdm; /* 1 if enable long distance matching */
271
+ U32 hashLog; /* Log size of hashTable */
272
+ U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
273
+ U32 minMatchLength; /* Minimum match length */
274
+ U32 hashEveryLog; /* Log number of entries to skip */
275
+ } ldmParams_t;
276
+
246
277
  typedef struct {
247
278
  U32 hufCTable[HUF_CTABLE_SIZE_U32(255)];
248
279
  FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
@@ -255,6 +286,28 @@ typedef struct {
255
286
  FSE_repeat litlength_repeatMode;
256
287
  } ZSTD_entropyCTables_t;
257
288
 
289
+ struct ZSTD_CCtx_params_s {
290
+ ZSTD_format_e format;
291
+ ZSTD_compressionParameters cParams;
292
+ ZSTD_frameParameters fParams;
293
+
294
+ int compressionLevel;
295
+ U32 forceWindow; /* force back-references to respect limit of
296
+ * 1<<wLog, even for dictionary */
297
+
298
+ /* Multithreading: used to pass parameters to mtctx */
299
+ U32 nbThreads;
300
+ unsigned jobSize;
301
+ unsigned overlapSizeLog;
302
+
303
+ /* Long distance matching parameters */
304
+ ldmParams_t ldmParams;
305
+
306
+ /* For use with createCCtxParams() and freeCCtxParams() only */
307
+ ZSTD_customMem customMem;
308
+
309
+ }; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
310
+
258
311
  const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);
259
312
  void ZSTD_seqToCodes(const seqStore_t* seqStorePtr);
260
313
 
@@ -268,24 +321,27 @@ void ZSTD_free(void* ptr, ZSTD_customMem customMem);
268
321
 
269
322
  MEM_STATIC U32 ZSTD_highbit32(U32 val)
270
323
  {
324
+ assert(val != 0);
325
+ {
271
326
  # if defined(_MSC_VER) /* Visual */
272
- unsigned long r=0;
273
- _BitScanReverse(&r, val);
274
- return (unsigned)r;
327
+ unsigned long r=0;
328
+ _BitScanReverse(&r, val);
329
+ return (unsigned)r;
275
330
  # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
276
- return 31 - __builtin_clz(val);
331
+ return 31 - __builtin_clz(val);
277
332
  # else /* Software version */
278
- static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
279
- U32 v = val;
280
- int r;
281
- v |= v >> 1;
282
- v |= v >> 2;
283
- v |= v >> 4;
284
- v |= v >> 8;
285
- v |= v >> 16;
286
- r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
287
- return r;
333
+ static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
334
+ U32 v = val;
335
+ int r;
336
+ v |= v >> 1;
337
+ v |= v >> 2;
338
+ v |= v >> 4;
339
+ v |= v >> 8;
340
+ v |= v >> 16;
341
+ r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
342
+ return r;
288
343
  # endif
344
+ }
289
345
  }
290
346
 
291
347
 
@@ -306,7 +362,7 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);
306
362
  size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
307
363
  const void* dict, size_t dictSize,
308
364
  const ZSTD_CDict* cdict,
309
- ZSTD_parameters params, unsigned long long pledgedSrcSize);
365
+ ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
310
366
 
311
367
  /*! ZSTD_compressStream_generic() :
312
368
  * Private use only. To be called from zstdmt_compress.c in single-thread mode. */
@@ -315,10 +371,25 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
315
371
  ZSTD_inBuffer* input,
316
372
  ZSTD_EndDirective const flushMode);
317
373
 
318
- /*! ZSTD_getParamsFromCDict() :
374
+ /*! ZSTD_getCParamsFromCDict() :
319
375
  * as the name implies */
320
- ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict);
321
-
376
+ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
377
+
378
+ /* ZSTD_compressBegin_advanced_internal() :
379
+ * Private use only. To be called from zstdmt_compress.c. */
380
+ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
381
+ const void* dict, size_t dictSize,
382
+ ZSTD_dictMode_e dictMode,
383
+ ZSTD_CCtx_params params,
384
+ unsigned long long pledgedSrcSize);
385
+
386
+ /* ZSTD_compress_advanced_internal() :
387
+ * Private use only. To be called from zstdmt_compress.c. */
388
+ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
389
+ void* dst, size_t dstCapacity,
390
+ const void* src, size_t srcSize,
391
+ const void* dict,size_t dictSize,
392
+ ZSTD_CCtx_params params);
322
393
 
323
394
  typedef struct {
324
395
  blockType_e blockType;
@@ -331,5 +402,8 @@ typedef struct {
331
402
  size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
332
403
  blockProperties_t* bpPtr);
333
404
 
405
+ #if defined (__cplusplus)
406
+ }
407
+ #endif
334
408
 
335
409
  #endif /* ZSTD_CCOMMON_H_MODULE */
@@ -461,6 +461,7 @@ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
461
461
  U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
462
462
  U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
463
463
  U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
464
+ assert(srcSize > 1); /* Not supported, RLE should be used instead */
464
465
  return minBits;
465
466
  }
466
467
 
@@ -469,6 +470,7 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi
469
470
  U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;
470
471
  U32 tableLog = maxTableLog;
471
472
  U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);
473
+ assert(srcSize > 1); /* Not supported, RLE should be used instead */
472
474
  if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
473
475
  if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */
474
476
  if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */
@@ -580,7 +582,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
580
582
  if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */
581
583
  if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
582
584
 
583
- { U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
585
+ { static U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
584
586
  U64 const scale = 62 - tableLog;
585
587
  U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */
586
588
  U64 const vStep = 1ULL<<(scale-20);
@@ -167,7 +167,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
167
167
  }
168
168
 
169
169
 
170
- size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize)
170
+ size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src, size_t srcSize)
171
171
  {
172
172
  BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
173
173
  U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
@@ -179,7 +179,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, si
179
179
 
180
180
  /* check result */
181
181
  if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
182
- if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall);
182
+ if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);
183
183
 
184
184
  /* Prepare base value per rank */
185
185
  { U32 n, nextRankStart = 0;
@@ -208,9 +208,10 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, si
208
208
  min >>= 1;
209
209
  } }
210
210
  /* assign value within rank, symbol order */
211
- { U32 n; for (n=0; n<=maxSymbolValue; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
211
+ { U32 n; for (n=0; n<nbSymbols; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
212
212
  }
213
213
 
214
+ *maxSymbolValuePtr = nbSymbols - 1;
214
215
  return readSize;
215
216
  }
216
217
 
@@ -5,6 +5,7 @@
5
5
  * This source code is licensed under both the BSD-style license (found in the
6
6
  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
7
  * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
 
@@ -25,25 +26,19 @@
25
26
  #include "fse.h"
26
27
  #define HUF_STATIC_LINKING_ONLY
27
28
  #include "huf.h"
28
- #include "zstd_internal.h" /* includes zstd.h */
29
- #include "zstdmt_compress.h"
30
-
31
-
32
- /*-*************************************
33
- * Constants
34
- ***************************************/
35
- static const U32 g_searchStrength = 8; /* control skip over incompressible data */
36
- #define HASH_READ_SIZE 8
37
- typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
29
+ #include "zstd_compress.h"
30
+ #include "zstd_fast.h"
31
+ #include "zstd_double_fast.h"
32
+ #include "zstd_lazy.h"
33
+ #include "zstd_opt.h"
34
+ #include "zstd_ldm.h"
38
35
 
39
36
 
40
37
  /*-*************************************
41
38
  * Helper functions
42
39
  ***************************************/
43
40
  size_t ZSTD_compressBound(size_t srcSize) {
44
- size_t const lowLimit = 256 KB;
45
- size_t const margin = (srcSize < lowLimit) ? (lowLimit-srcSize) >> 12 : 0; /* from 64 to 0 */
46
- return srcSize + (srcSize >> 8) + margin;
41
+ return ZSTD_COMPRESSBOUND(srcSize);
47
42
  }
48
43
 
49
44
 
@@ -61,8 +56,6 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
61
56
  /*-*************************************
62
57
  * Context memory management
63
58
  ***************************************/
64
- typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
65
-
66
59
  struct ZSTD_CDict_s {
67
60
  void* dictBuffer;
68
61
  const void* dictContent;
@@ -70,65 +63,6 @@ struct ZSTD_CDict_s {
70
63
  ZSTD_CCtx* refContext;
71
64
  }; /* typedef'd to ZSTD_CDict within "zstd.h" */
72
65
 
73
- struct ZSTD_CCtx_s {
74
- const BYTE* nextSrc; /* next block here to continue on current prefix */
75
- const BYTE* base; /* All regular indexes relative to this position */
76
- const BYTE* dictBase; /* extDict indexes relative to this position */
77
- U32 dictLimit; /* below that point, need extDict */
78
- U32 lowLimit; /* below that point, no more data */
79
- U32 nextToUpdate; /* index from which to continue dictionary update */
80
- U32 nextToUpdate3; /* index from which to continue dictionary update */
81
- U32 hashLog3; /* dispatch table : larger == faster, more memory */
82
- U32 loadedDictEnd; /* index of end of dictionary */
83
- U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */
84
- ZSTD_compressionStage_e stage;
85
- U32 dictID;
86
- int compressionLevel;
87
- ZSTD_parameters requestedParams;
88
- ZSTD_parameters appliedParams;
89
- void* workSpace;
90
- size_t workSpaceSize;
91
- size_t blockSize;
92
- U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
93
- U64 consumedSrcSize;
94
- XXH64_state_t xxhState;
95
- ZSTD_customMem customMem;
96
- size_t staticSize;
97
-
98
- seqStore_t seqStore; /* sequences storage ptrs */
99
- optState_t optState;
100
- U32* hashTable;
101
- U32* hashTable3;
102
- U32* chainTable;
103
- ZSTD_entropyCTables_t* entropy;
104
-
105
- /* streaming */
106
- char* inBuff;
107
- size_t inBuffSize;
108
- size_t inToCompress;
109
- size_t inBuffPos;
110
- size_t inBuffTarget;
111
- char* outBuff;
112
- size_t outBuffSize;
113
- size_t outBuffContentSize;
114
- size_t outBuffFlushedSize;
115
- ZSTD_cStreamStage streamStage;
116
- U32 frameEnded;
117
-
118
- /* Dictionary */
119
- ZSTD_dictMode_e dictMode; /* select restricting dictionary to "rawContent" or "fullDict" only */
120
- U32 dictContentByRef;
121
- ZSTD_CDict* cdictLocal;
122
- const ZSTD_CDict* cdict;
123
- const void* prefix;
124
- size_t prefixSize;
125
-
126
- /* Multi-threading */
127
- U32 nbThreads;
128
- ZSTDMT_CCtx* mtctx;
129
- };
130
-
131
-
132
66
  ZSTD_CCtx* ZSTD_createCCtx(void)
133
67
  {
134
68
  return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
@@ -143,7 +77,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
143
77
  cctx = (ZSTD_CCtx*) ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
144
78
  if (!cctx) return NULL;
145
79
  cctx->customMem = customMem;
146
- cctx->compressionLevel = ZSTD_CLEVEL_DEFAULT;
80
+ cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
147
81
  ZSTD_STATIC_ASSERT(zcss_init==0);
148
82
  ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
149
83
  return cctx;
@@ -151,7 +85,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
151
85
 
152
86
  ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
153
87
  {
154
- ZSTD_CCtx* cctx = (ZSTD_CCtx*) workspace;
88
+ ZSTD_CCtx* const cctx = (ZSTD_CCtx*) workspace;
155
89
  if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
156
90
  if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
157
91
  memset(workspace, 0, workspaceSize); /* may be a bit generous, could memset be smaller ? */
@@ -161,7 +95,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
161
95
 
162
96
  /* entropy space (never moves) */
163
97
  if (cctx->workSpaceSize < sizeof(ZSTD_entropyCTables_t)) return NULL;
164
- assert(((size_t)cctx->workSpace & 7) == 0); /* ensure correct alignment */
98
+ assert(((size_t)cctx->workSpace & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
165
99
  cctx->entropy = (ZSTD_entropyCTables_t*)cctx->workSpace;
166
100
 
167
101
  return cctx;
@@ -175,23 +109,36 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
175
109
  cctx->workSpace = NULL;
176
110
  ZSTD_freeCDict(cctx->cdictLocal);
177
111
  cctx->cdictLocal = NULL;
112
+ #ifdef ZSTD_MULTITHREAD
178
113
  ZSTDMT_freeCCtx(cctx->mtctx);
179
114
  cctx->mtctx = NULL;
115
+ #endif
180
116
  ZSTD_free(cctx, cctx->customMem);
181
117
  return 0; /* reserved as a potential error code in the future */
182
118
  }
183
119
 
120
+
121
+ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
122
+ {
123
+ #ifdef ZSTD_MULTITHREAD
124
+ return ZSTDMT_sizeof_CCtx(cctx->mtctx);
125
+ #else
126
+ (void) cctx;
127
+ return 0;
128
+ #endif
129
+ }
130
+
131
+
184
132
  size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
185
133
  {
186
134
  if (cctx==NULL) return 0; /* support sizeof on NULL */
187
- DEBUGLOG(5, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
188
- DEBUGLOG(5, "workSpaceSize : %u", (U32)cctx->workSpaceSize);
189
- DEBUGLOG(5, "streaming buffers : %u", (U32)(cctx->outBuffSize + cctx->inBuffSize));
190
- DEBUGLOG(5, "inner MTCTX : %u", (U32)ZSTDMT_sizeof_CCtx(cctx->mtctx));
135
+ DEBUGLOG(3, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
136
+ DEBUGLOG(3, "workSpaceSize (including streaming buffers): %u", (U32)cctx->workSpaceSize);
137
+ DEBUGLOG(3, "inner cdict : %u", (U32)ZSTD_sizeof_CDict(cctx->cdictLocal));
138
+ DEBUGLOG(3, "inner MTCTX : %u", (U32)ZSTD_sizeof_mtctx(cctx));
191
139
  return sizeof(*cctx) + cctx->workSpaceSize
192
140
  + ZSTD_sizeof_CDict(cctx->cdictLocal)
193
- + cctx->outBuffSize + cctx->inBuffSize
194
- + ZSTDMT_sizeof_CCtx(cctx->mtctx);
141
+ + ZSTD_sizeof_mtctx(cctx);
195
142
  }
196
143
 
197
144
  size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
@@ -202,29 +149,99 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
202
149
  /* private API call, for dictBuilder only */
203
150
  const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
204
151
 
205
- static ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx* cctx) { return cctx->appliedParams; }
152
+ #define ZSTD_CLEVEL_CUSTOM 999
206
153
 
207
- /* older variant; will be deprecated */
208
- size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
154
+ static ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
155
+ ZSTD_CCtx_params params, U64 srcSizeHint, size_t dictSize)
209
156
  {
210
- switch(param)
211
- {
212
- case ZSTD_p_forceWindow : cctx->forceWindow = value>0; cctx->loadedDictEnd = 0; return 0;
213
- ZSTD_STATIC_ASSERT(ZSTD_dm_auto==0);
214
- ZSTD_STATIC_ASSERT(ZSTD_dm_rawContent==1);
215
- case ZSTD_p_forceRawDict : cctx->dictMode = (ZSTD_dictMode_e)(value>0); return 0;
216
- default: return ERROR(parameter_unsupported);
217
- }
157
+ return (params.compressionLevel == ZSTD_CLEVEL_CUSTOM ?
158
+ params.cParams :
159
+ ZSTD_getCParams(params.compressionLevel, srcSizeHint, dictSize));
218
160
  }
219
161
 
162
+ static void ZSTD_cLevelToCCtxParams_srcSize(ZSTD_CCtx_params* params, U64 srcSize)
163
+ {
164
+ params->cParams = ZSTD_getCParamsFromCCtxParams(*params, srcSize, 0);
165
+ params->compressionLevel = ZSTD_CLEVEL_CUSTOM;
166
+ }
220
167
 
221
- #define ZSTD_CLEVEL_CUSTOM 999
222
168
  static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
223
169
  {
224
- if (cctx->compressionLevel==ZSTD_CLEVEL_CUSTOM) return;
225
- cctx->requestedParams.cParams = ZSTD_getCParams(cctx->compressionLevel,
226
- cctx->pledgedSrcSizePlusOne-1, 0);
227
- cctx->compressionLevel = ZSTD_CLEVEL_CUSTOM;
170
+ ZSTD_cLevelToCCtxParams_srcSize(
171
+ &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1);
172
+ }
173
+
174
+ static void ZSTD_cLevelToCCtxParams(ZSTD_CCtx_params* params)
175
+ {
176
+ ZSTD_cLevelToCCtxParams_srcSize(params, 0);
177
+ }
178
+
179
+ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
180
+ ZSTD_compressionParameters cParams)
181
+ {
182
+ ZSTD_CCtx_params cctxParams;
183
+ memset(&cctxParams, 0, sizeof(cctxParams));
184
+ cctxParams.cParams = cParams;
185
+ cctxParams.compressionLevel = ZSTD_CLEVEL_CUSTOM;
186
+ return cctxParams;
187
+ }
188
+
189
+ static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
190
+ ZSTD_customMem customMem)
191
+ {
192
+ ZSTD_CCtx_params* params;
193
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
194
+ params = (ZSTD_CCtx_params*)ZSTD_calloc(
195
+ sizeof(ZSTD_CCtx_params), customMem);
196
+ if (!params) { return NULL; }
197
+ params->customMem = customMem;
198
+ params->compressionLevel = ZSTD_CLEVEL_DEFAULT;
199
+ return params;
200
+ }
201
+
202
+ ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
203
+ {
204
+ return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);
205
+ }
206
+
207
+ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
208
+ {
209
+ if (params == NULL) { return 0; }
210
+ ZSTD_free(params, params->customMem);
211
+ return 0;
212
+ }
213
+
214
+ size_t ZSTD_resetCCtxParams(ZSTD_CCtx_params* params)
215
+ {
216
+ return ZSTD_initCCtxParams(params, ZSTD_CLEVEL_DEFAULT);
217
+ }
218
+
219
+ size_t ZSTD_initCCtxParams(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
220
+ if (!cctxParams) { return ERROR(GENERIC); }
221
+ memset(cctxParams, 0, sizeof(*cctxParams));
222
+ cctxParams->compressionLevel = compressionLevel;
223
+ return 0;
224
+ }
225
+
226
+ size_t ZSTD_initCCtxParams_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
227
+ {
228
+ if (!cctxParams) { return ERROR(GENERIC); }
229
+ CHECK_F( ZSTD_checkCParams(params.cParams) );
230
+ memset(cctxParams, 0, sizeof(*cctxParams));
231
+ cctxParams->cParams = params.cParams;
232
+ cctxParams->fParams = params.fParams;
233
+ cctxParams->compressionLevel = ZSTD_CLEVEL_CUSTOM;
234
+ return 0;
235
+ }
236
+
237
+ static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
238
+ ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
239
+ {
240
+ ZSTD_CCtx_params ret = cctxParams;
241
+ ret.cParams = params.cParams;
242
+ ret.fParams = params.fParams;
243
+ ret.compressionLevel = ZSTD_CLEVEL_CUSTOM;
244
+ return ret;
228
245
  }
229
246
 
230
247
  #define CLAMPCHECK(val,min,max) { \
@@ -238,167 +255,285 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
238
255
 
239
256
  switch(param)
240
257
  {
241
- case ZSTD_p_compressionLevel :
242
- if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel(); /* cap max compression level */
258
+ case ZSTD_p_format :
259
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
260
+
261
+ case ZSTD_p_compressionLevel:
243
262
  if (value == 0) return 0; /* special value : 0 means "don't change anything" */
244
263
  if (cctx->cdict) return ERROR(stage_wrong);
245
- cctx->compressionLevel = value;
246
- return 0;
264
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
265
+
266
+ case ZSTD_p_windowLog:
267
+ case ZSTD_p_hashLog:
268
+ case ZSTD_p_chainLog:
269
+ case ZSTD_p_searchLog:
270
+ case ZSTD_p_minMatch:
271
+ case ZSTD_p_targetLength:
272
+ case ZSTD_p_compressionStrategy:
273
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
274
+ if (cctx->cdict) return ERROR(stage_wrong);
275
+ ZSTD_cLevelToCParams(cctx); /* Can optimize if srcSize is known */
276
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
247
277
 
248
- case ZSTD_p_windowLog :
249
- DEBUGLOG(5, "setting ZSTD_p_windowLog = %u (cdict:%u)",
250
- value, (cctx->cdict!=NULL));
278
+ case ZSTD_p_contentSizeFlag:
279
+ case ZSTD_p_checksumFlag:
280
+ case ZSTD_p_dictIDFlag:
281
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
282
+
283
+ case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
284
+ * even when referencing into Dictionary content
285
+ * default : 0 when using a CDict, 1 when using a Prefix */
286
+ cctx->loadedDictEnd = 0;
287
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
288
+
289
+ case ZSTD_p_nbThreads:
290
+ if (value==0) return 0;
291
+ DEBUGLOG(5, " setting nbThreads : %u", value);
292
+ if (value > 1 && cctx->staticSize) {
293
+ return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
294
+ }
295
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
296
+
297
+ case ZSTD_p_jobSize:
298
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
299
+
300
+ case ZSTD_p_overlapSizeLog:
301
+ DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->requestedParams.nbThreads);
302
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
303
+
304
+ case ZSTD_p_enableLongDistanceMatching:
305
+ if (cctx->cdict) return ERROR(stage_wrong);
306
+ if (value != 0) {
307
+ ZSTD_cLevelToCParams(cctx);
308
+ }
309
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
310
+
311
+ case ZSTD_p_ldmHashLog:
312
+ case ZSTD_p_ldmMinMatch:
251
313
  if (value == 0) return 0; /* special value : 0 means "don't change anything" */
252
314
  if (cctx->cdict) return ERROR(stage_wrong);
315
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
316
+
317
+ case ZSTD_p_ldmBucketSizeLog:
318
+ case ZSTD_p_ldmHashEveryLog:
319
+ if (cctx->cdict) return ERROR(stage_wrong);
320
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
321
+
322
+ default: return ERROR(parameter_unsupported);
323
+ }
324
+ }
325
+
326
+ size_t ZSTD_CCtxParam_setParameter(
327
+ ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value)
328
+ {
329
+ switch(param)
330
+ {
331
+ case ZSTD_p_format :
332
+ if (value > (unsigned)ZSTD_f_zstd1_magicless)
333
+ return ERROR(parameter_unsupported);
334
+ params->format = (ZSTD_format_e)value;
335
+ return 0;
336
+
337
+ case ZSTD_p_compressionLevel :
338
+ if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel();
339
+ if (value == 0) return 0;
340
+ params->compressionLevel = value;
341
+ return 0;
342
+
343
+ case ZSTD_p_windowLog :
344
+ if (value == 0) return 0;
253
345
  CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
254
- ZSTD_cLevelToCParams(cctx);
255
- cctx->requestedParams.cParams.windowLog = value;
346
+ ZSTD_cLevelToCCtxParams(params);
347
+ params->cParams.windowLog = value;
256
348
  return 0;
257
349
 
258
350
  case ZSTD_p_hashLog :
259
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
260
- if (cctx->cdict) return ERROR(stage_wrong);
351
+ if (value == 0) return 0;
261
352
  CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
262
- ZSTD_cLevelToCParams(cctx);
263
- cctx->requestedParams.cParams.hashLog = value;
353
+ ZSTD_cLevelToCCtxParams(params);
354
+ params->cParams.hashLog = value;
264
355
  return 0;
265
356
 
266
357
  case ZSTD_p_chainLog :
267
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
268
- if (cctx->cdict) return ERROR(stage_wrong);
358
+ if (value == 0) return 0;
269
359
  CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
270
- ZSTD_cLevelToCParams(cctx);
271
- cctx->requestedParams.cParams.chainLog = value;
360
+ ZSTD_cLevelToCCtxParams(params);
361
+ params->cParams.chainLog = value;
272
362
  return 0;
273
363
 
274
364
  case ZSTD_p_searchLog :
275
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
276
- if (cctx->cdict) return ERROR(stage_wrong);
365
+ if (value == 0) return 0;
277
366
  CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
278
- ZSTD_cLevelToCParams(cctx);
279
- cctx->requestedParams.cParams.searchLog = value;
367
+ ZSTD_cLevelToCCtxParams(params);
368
+ params->cParams.searchLog = value;
280
369
  return 0;
281
370
 
282
371
  case ZSTD_p_minMatch :
283
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
284
- if (cctx->cdict) return ERROR(stage_wrong);
372
+ if (value == 0) return 0;
285
373
  CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
286
- ZSTD_cLevelToCParams(cctx);
287
- cctx->requestedParams.cParams.searchLength = value;
374
+ ZSTD_cLevelToCCtxParams(params);
375
+ params->cParams.searchLength = value;
288
376
  return 0;
289
377
 
290
378
  case ZSTD_p_targetLength :
291
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
292
- if (cctx->cdict) return ERROR(stage_wrong);
379
+ if (value == 0) return 0;
293
380
  CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
294
- ZSTD_cLevelToCParams(cctx);
295
- cctx->requestedParams.cParams.targetLength = value;
381
+ ZSTD_cLevelToCCtxParams(params);
382
+ params->cParams.targetLength = value;
296
383
  return 0;
297
384
 
298
385
  case ZSTD_p_compressionStrategy :
299
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
300
- if (cctx->cdict) return ERROR(stage_wrong);
386
+ if (value == 0) return 0;
301
387
  CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
302
- ZSTD_cLevelToCParams(cctx);
303
- cctx->requestedParams.cParams.strategy = (ZSTD_strategy)value;
388
+ ZSTD_cLevelToCCtxParams(params);
389
+ params->cParams.strategy = (ZSTD_strategy)value;
304
390
  return 0;
305
391
 
306
392
  case ZSTD_p_contentSizeFlag :
307
- DEBUGLOG(5, "set content size flag = %u", (value>0));
308
393
  /* Content size written in frame header _when known_ (default:1) */
309
- cctx->requestedParams.fParams.contentSizeFlag = value>0;
394
+ DEBUGLOG(5, "set content size flag = %u", (value>0));
395
+ params->fParams.contentSizeFlag = value > 0;
310
396
  return 0;
311
397
 
312
398
  case ZSTD_p_checksumFlag :
313
399
  /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
314
- cctx->requestedParams.fParams.checksumFlag = value>0;
400
+ params->fParams.checksumFlag = value > 0;
315
401
  return 0;
316
402
 
317
403
  case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
318
404
  DEBUGLOG(5, "set dictIDFlag = %u", (value>0));
319
- cctx->requestedParams.fParams.noDictIDFlag = (value==0);
405
+ params->fParams.noDictIDFlag = (value == 0);
320
406
  return 0;
321
407
 
322
- /* Dictionary parameters */
323
- case ZSTD_p_dictMode :
324
- if (cctx->cdict) return ERROR(stage_wrong); /* must be set before loading */
325
- /* restrict dictionary mode, to "rawContent" or "fullDict" only */
326
- ZSTD_STATIC_ASSERT((U32)ZSTD_dm_fullDict > (U32)ZSTD_dm_rawContent);
327
- if (value > (unsigned)ZSTD_dm_fullDict)
328
- return ERROR(parameter_outOfBound);
329
- cctx->dictMode = (ZSTD_dictMode_e)value;
408
+ case ZSTD_p_forceMaxWindow :
409
+ params->forceWindow = value > 0;
330
410
  return 0;
331
411
 
332
- case ZSTD_p_refDictContent :
333
- if (cctx->cdict) return ERROR(stage_wrong); /* must be set before loading */
334
- /* dictionary content will be referenced, instead of copied */
335
- cctx->dictContentByRef = value>0;
412
+ case ZSTD_p_nbThreads :
413
+ if (value == 0) return 0;
414
+ #ifndef ZSTD_MULTITHREAD
415
+ if (value > 1) return ERROR(parameter_unsupported);
336
416
  return 0;
417
+ #else
418
+ return ZSTDMT_initializeCCtxParameters(params, value);
419
+ #endif
337
420
 
338
- case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
339
- * even when referencing into Dictionary content
340
- * default : 0 when using a CDict, 1 when using a Prefix */
341
- cctx->forceWindow = value>0;
342
- cctx->loadedDictEnd = 0;
343
- return 0;
421
+ case ZSTD_p_jobSize :
422
+ #ifndef ZSTD_MULTITHREAD
423
+ return ERROR(parameter_unsupported);
424
+ #else
425
+ if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
426
+ return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_sectionSize, value);
427
+ #endif
344
428
 
345
- case ZSTD_p_nbThreads:
346
- if (value==0) return 0;
347
- DEBUGLOG(5, " setting nbThreads : %u", value);
429
+ case ZSTD_p_overlapSizeLog :
348
430
  #ifndef ZSTD_MULTITHREAD
349
- if (value > 1) return ERROR(parameter_unsupported);
431
+ return ERROR(parameter_unsupported);
432
+ #else
433
+ if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
434
+ return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_overlapSectionLog, value);
350
435
  #endif
351
- if ((value>1) && (cctx->nbThreads != value)) {
352
- if (cctx->staticSize) /* MT not compatible with static alloc */
353
- return ERROR(parameter_unsupported);
354
- ZSTDMT_freeCCtx(cctx->mtctx);
355
- cctx->nbThreads = 1;
356
- cctx->mtctx = ZSTDMT_createCCtx_advanced(value, cctx->customMem);
357
- if (cctx->mtctx == NULL) return ERROR(memory_allocation);
436
+
437
+ case ZSTD_p_enableLongDistanceMatching :
438
+ if (value != 0) {
439
+ ZSTD_cLevelToCCtxParams(params);
440
+ params->cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
358
441
  }
359
- cctx->nbThreads = value;
442
+ return ZSTD_ldm_initializeParameters(&params->ldmParams, value);
443
+
444
+ case ZSTD_p_ldmHashLog :
445
+ if (value == 0) return 0;
446
+ CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
447
+ params->ldmParams.hashLog = value;
360
448
  return 0;
361
449
 
362
- case ZSTD_p_jobSize:
363
- if (cctx->nbThreads <= 1) return ERROR(parameter_unsupported);
364
- assert(cctx->mtctx != NULL);
365
- return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_sectionSize, value);
450
+ case ZSTD_p_ldmMinMatch :
451
+ if (value == 0) return 0;
452
+ CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
453
+ params->ldmParams.minMatchLength = value;
454
+ return 0;
366
455
 
367
- case ZSTD_p_overlapSizeLog:
368
- DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->nbThreads);
369
- if (cctx->nbThreads <= 1) return ERROR(parameter_unsupported);
370
- assert(cctx->mtctx != NULL);
371
- return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_overlapSectionLog, value);
456
+ case ZSTD_p_ldmBucketSizeLog :
457
+ if (value > ZSTD_LDM_BUCKETSIZELOG_MAX) {
458
+ return ERROR(parameter_outOfBound);
459
+ }
460
+ params->ldmParams.bucketSizeLog = value;
461
+ return 0;
462
+
463
+ case ZSTD_p_ldmHashEveryLog :
464
+ if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) {
465
+ return ERROR(parameter_outOfBound);
466
+ }
467
+ params->ldmParams.hashEveryLog = value;
468
+ return 0;
372
469
 
373
470
  default: return ERROR(parameter_unsupported);
374
471
  }
375
472
  }
376
473
 
474
+ /**
475
+ * This function should be updated whenever ZSTD_CCtx_params is updated.
476
+ * Parameters are copied manually before the dictionary is loaded.
477
+ * The multithreading parameters jobSize and overlapSizeLog are set only if
478
+ * nbThreads > 1.
479
+ *
480
+ * Pledged srcSize is treated as unknown.
481
+ */
482
+ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
483
+ ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
484
+ {
485
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
486
+ if (cctx->cdict) return ERROR(stage_wrong);
487
+
488
+ /* Assume the compression and frame parameters are validated */
489
+ cctx->requestedParams.cParams = params->cParams;
490
+ cctx->requestedParams.fParams = params->fParams;
491
+ cctx->requestedParams.compressionLevel = params->compressionLevel;
492
+
493
+ /* Set force window explicitly since it sets cctx->loadedDictEnd */
494
+ CHECK_F( ZSTD_CCtx_setParameter(
495
+ cctx, ZSTD_p_forceMaxWindow, params->forceWindow) );
496
+
497
+ /* Set multithreading parameters explicitly */
498
+ CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_nbThreads, params->nbThreads) );
499
+ if (params->nbThreads > 1) {
500
+ CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_jobSize, params->jobSize) );
501
+ CHECK_F( ZSTD_CCtx_setParameter(
502
+ cctx, ZSTD_p_overlapSizeLog, params->overlapSizeLog) );
503
+ }
504
+
505
+ /* Copy long distance matching parameters */
506
+ cctx->requestedParams.ldmParams = params->ldmParams;
507
+
508
+ /* customMem is used only for create/free params and can be ignored */
509
+ return 0;
510
+ }
511
+
377
512
  ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
378
513
  {
379
- DEBUGLOG(5, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
514
+ DEBUGLOG(4, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
380
515
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
381
516
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
382
517
  return 0;
383
518
  }
384
519
 
385
- ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
520
+ size_t ZSTD_CCtx_loadDictionary_advanced(
521
+ ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
522
+ ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode)
386
523
  {
387
524
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
388
525
  if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
389
- DEBUGLOG(5, "load dictionary of size %u", (U32)dictSize);
526
+ DEBUGLOG(4, "load dictionary of size %u", (U32)dictSize);
390
527
  ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
391
528
  if (dict==NULL || dictSize==0) { /* no dictionary mode */
392
529
  cctx->cdictLocal = NULL;
393
530
  cctx->cdict = NULL;
394
531
  } else {
395
532
  ZSTD_compressionParameters const cParams =
396
- cctx->compressionLevel == ZSTD_CLEVEL_CUSTOM ?
397
- cctx->requestedParams.cParams :
398
- ZSTD_getCParams(cctx->compressionLevel, 0, dictSize);
533
+ ZSTD_getCParamsFromCCtxParams(cctx->requestedParams, 0, dictSize);
399
534
  cctx->cdictLocal = ZSTD_createCDict_advanced(
400
535
  dict, dictSize,
401
- cctx->dictContentByRef, cctx->dictMode,
536
+ dictLoadMethod, dictMode,
402
537
  cParams, cctx->customMem);
403
538
  cctx->cdict = cctx->cdictLocal;
404
539
  if (cctx->cdictLocal == NULL)
@@ -407,21 +542,41 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
407
542
  return 0;
408
543
  }
409
544
 
545
+ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
546
+ ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
547
+ {
548
+ return ZSTD_CCtx_loadDictionary_advanced(
549
+ cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dm_auto);
550
+ }
551
+
552
+ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
553
+ {
554
+ return ZSTD_CCtx_loadDictionary_advanced(
555
+ cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dm_auto);
556
+ }
557
+
558
+
410
559
  size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
411
560
  {
412
561
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
413
562
  cctx->cdict = cdict;
414
- cctx->prefix = NULL; /* exclusive */
415
- cctx->prefixSize = 0;
563
+ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
416
564
  return 0;
417
565
  }
418
566
 
419
567
  size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
568
+ {
569
+ return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dm_rawContent);
570
+ }
571
+
572
+ size_t ZSTD_CCtx_refPrefix_advanced(
573
+ ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode)
420
574
  {
421
575
  if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
422
576
  cctx->cdict = NULL; /* prefix discards any prior cdict */
423
- cctx->prefix = prefix;
424
- cctx->prefixSize = prefixSize;
577
+ cctx->prefixDict.dict = prefix;
578
+ cctx->prefixDict.dictSize = prefixSize;
579
+ cctx->prefixDict.dictMode = dictMode;
425
580
  return 0;
426
581
  }
427
582
 
@@ -484,28 +639,37 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
484
639
 
485
640
  /** ZSTD_adjustCParams_internal() :
486
641
  optimize `cPar` for a given input (`srcSize` and `dictSize`).
487
- mostly downsizing to reduce memory consumption and initialization.
488
- Both `srcSize` and `dictSize` are optional (use 0 if unknown),
489
- but if both are 0, no optimization can be done.
490
- Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
642
+ mostly downsizing to reduce memory consumption and initialization latency.
643
+ Both `srcSize` and `dictSize` are optional (use 0 if unknown).
644
+ Note : cPar is considered validated at this stage. Use ZSTD_checkCParams() to ensure that condition. */
491
645
  ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
492
646
  {
647
+ static const U64 minSrcSize = 513; /* (1<<9) + 1 */
648
+ static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
493
649
  assert(ZSTD_checkCParams(cPar)==0);
494
- if (srcSize+dictSize == 0) return cPar; /* no size information available : no adjustment */
495
-
496
- /* resize params, to use less memory when necessary */
497
- { U32 const minSrcSize = (srcSize==0) ? 500 : 0;
498
- U64 const rSize = srcSize + dictSize + minSrcSize;
499
- if (rSize < ((U64)1<<ZSTD_WINDOWLOG_MAX)) {
500
- U32 const srcLog = MAX(ZSTD_HASHLOG_MIN, ZSTD_highbit32((U32)(rSize)-1) + 1);
501
- if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
502
- } }
650
+
651
+ if (dictSize && (srcSize+1<2) /* srcSize unknown */ )
652
+ srcSize = minSrcSize; /* presumed small when there is a dictionary */
653
+ else if (srcSize == 0)
654
+ srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
655
+
656
+ /* resize windowLog if input is small enough, to use less memory */
657
+ if ( (srcSize < maxWindowResize)
658
+ && (dictSize < maxWindowResize) ) {
659
+ U32 const tSize = (U32)(srcSize + dictSize);
660
+ static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;
661
+ U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :
662
+ ZSTD_highbit32(tSize-1) + 1;
663
+ if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
664
+ }
503
665
  if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog;
504
666
  { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
505
- if (cycleLog > cPar.windowLog) cPar.chainLog -= (cycleLog - cPar.windowLog);
667
+ if (cycleLog > cPar.windowLog)
668
+ cPar.chainLog -= (cycleLog - cPar.windowLog);
506
669
  }
507
670
 
508
- if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
671
+ if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
672
+ cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
509
673
 
510
674
  return cPar;
511
675
  }
@@ -516,56 +680,81 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
516
680
  return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
517
681
  }
518
682
 
519
-
520
- size_t ZSTD_estimateCCtxSize_advanced(ZSTD_compressionParameters cParams)
683
+ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
521
684
  {
522
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
523
- U32 const divider = (cParams.searchLength==3) ? 3 : 4;
524
- size_t const maxNbSeq = blockSize / divider;
525
- size_t const tokenSpace = blockSize + 11*maxNbSeq;
685
+ /* Estimate CCtx size is supported for single-threaded compression only. */
686
+ if (params->nbThreads > 1) { return ERROR(GENERIC); }
687
+ { ZSTD_compressionParameters const cParams =
688
+ ZSTD_getCParamsFromCCtxParams(*params, 0, 0);
689
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
690
+ U32 const divider = (cParams.searchLength==3) ? 3 : 4;
691
+ size_t const maxNbSeq = blockSize / divider;
692
+ size_t const tokenSpace = blockSize + 11*maxNbSeq;
693
+ size_t const chainSize =
694
+ (cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams.chainLog);
695
+ size_t const hSize = ((size_t)1) << cParams.hashLog;
696
+ U32 const hashLog3 = (cParams.searchLength>3) ?
697
+ 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
698
+ size_t const h3Size = ((size_t)1) << hashLog3;
699
+ size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
700
+ size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
701
+
702
+ size_t const optBudget =
703
+ ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
704
+ + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
705
+ size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
526
706
 
527
- size_t const chainSize = (cParams.strategy == ZSTD_fast) ? 0 : (1 << cParams.chainLog);
528
- size_t const hSize = ((size_t)1) << cParams.hashLog;
529
- U32 const hashLog3 = (cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
530
- size_t const h3Size = ((size_t)1) << hashLog3;
531
- size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
532
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
707
+ size_t const ldmSpace = params->ldmParams.enableLdm ?
708
+ ZSTD_ldm_getTableSize(params->ldmParams.hashLog,
709
+ params->ldmParams.bucketSizeLog) : 0;
533
710
 
534
- size_t const optBudget = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
535
- + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
536
- size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
537
- size_t const neededSpace = entropySpace + tableSpace + tokenSpace + optSpace;
711
+ size_t const neededSpace = entropySpace + tableSpace + tokenSpace +
712
+ optSpace + ldmSpace;
713
+
714
+ DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
715
+ DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
716
+ return sizeof(ZSTD_CCtx) + neededSpace;
717
+ }
718
+ }
538
719
 
539
- DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
540
- DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
541
- return sizeof(ZSTD_CCtx) + neededSpace;
720
+ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
721
+ {
722
+ ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
723
+ return ZSTD_estimateCCtxSize_usingCCtxParams(&params);
542
724
  }
543
725
 
544
726
  size_t ZSTD_estimateCCtxSize(int compressionLevel)
545
727
  {
546
728
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
547
- return ZSTD_estimateCCtxSize_advanced(cParams);
729
+ return ZSTD_estimateCCtxSize_usingCParams(cParams);
548
730
  }
549
731
 
550
- size_t ZSTD_estimateCStreamSize_advanced(ZSTD_compressionParameters cParams)
732
+ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
551
733
  {
552
- size_t const CCtxSize = ZSTD_estimateCCtxSize_advanced(cParams);
553
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
554
- size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
555
- size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
556
- size_t const streamingSize = inBuffSize + outBuffSize;
734
+ if (params->nbThreads > 1) { return ERROR(GENERIC); }
735
+ { size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
736
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
737
+ size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
738
+ size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
739
+ size_t const streamingSize = inBuffSize + outBuffSize;
740
+
741
+ return CCtxSize + streamingSize;
742
+ }
743
+ }
557
744
 
558
- return CCtxSize + streamingSize;
745
+ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
746
+ {
747
+ ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
748
+ return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
559
749
  }
560
750
 
561
751
  size_t ZSTD_estimateCStreamSize(int compressionLevel) {
562
752
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
563
- return ZSTD_estimateCStreamSize_advanced(cParams);
753
+ return ZSTD_estimateCStreamSize_usingCParams(cParams);
564
754
  }
565
755
 
566
-
567
- static U32 ZSTD_equivalentParams(ZSTD_compressionParameters cParams1,
568
- ZSTD_compressionParameters cParams2)
756
+ static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
757
+ ZSTD_compressionParameters cParams2)
569
758
  {
570
759
  U32 bslog1 = MIN(cParams1.windowLog, ZSTD_BLOCKSIZELOG_MAX);
571
760
  U32 bslog2 = MIN(cParams2.windowLog, ZSTD_BLOCKSIZELOG_MAX);
@@ -576,18 +765,39 @@ static U32 ZSTD_equivalentParams(ZSTD_compressionParameters cParams1,
576
765
  & ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
577
766
  }
578
767
 
768
+ /** The parameters are equivalent if ldm is not enabled in both sets or
769
+ * all the parameters are equivalent. */
770
+ static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
771
+ ldmParams_t ldmParams2)
772
+ {
773
+ return (!ldmParams1.enableLdm && !ldmParams2.enableLdm) ||
774
+ (ldmParams1.enableLdm == ldmParams2.enableLdm &&
775
+ ldmParams1.hashLog == ldmParams2.hashLog &&
776
+ ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
777
+ ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
778
+ ldmParams1.hashEveryLog == ldmParams2.hashEveryLog);
779
+ }
780
+
781
+ /** Equivalence for resetCCtx purposes */
782
+ static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
783
+ ZSTD_CCtx_params params2)
784
+ {
785
+ return ZSTD_equivalentCParams(params1.cParams, params2.cParams) &&
786
+ ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams);
787
+ }
788
+
579
789
  /*! ZSTD_continueCCtx() :
580
790
  * reuse CCtx without reset (note : requires no dictionary) */
581
- static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 pledgedSrcSize)
791
+ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
582
792
  {
583
793
  U32 const end = (U32)(cctx->nextSrc - cctx->base);
584
- DEBUGLOG(5, "continue mode");
794
+ DEBUGLOG(4, "continue mode");
585
795
  cctx->appliedParams = params;
586
796
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
587
797
  cctx->consumedSrcSize = 0;
588
798
  if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
589
799
  cctx->appliedParams.fParams.contentSizeFlag = 0;
590
- DEBUGLOG(5, "pledged content size : %u ; flag : %u",
800
+ DEBUGLOG(4, "pledged content size : %u ; flag : %u",
591
801
  (U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
592
802
  cctx->lowLimit = end;
593
803
  cctx->dictLimit = end;
@@ -607,15 +817,19 @@ typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
607
817
  /*! ZSTD_resetCCtx_internal() :
608
818
  note : `params` are assumed fully validated at this stage */
609
819
  static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
610
- ZSTD_parameters params, U64 pledgedSrcSize,
820
+ ZSTD_CCtx_params params, U64 pledgedSrcSize,
611
821
  ZSTD_compResetPolicy_e const crp,
612
822
  ZSTD_buffered_policy_e const zbuff)
613
823
  {
824
+ DEBUGLOG(4, "ZSTD_resetCCtx_internal");
614
825
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
826
+ DEBUGLOG(4, "pledgedSrcSize: %u", (U32)pledgedSrcSize);
615
827
 
616
828
  if (crp == ZSTDcrp_continue) {
617
- if (ZSTD_equivalentParams(params.cParams, zc->appliedParams.cParams)) {
618
- DEBUGLOG(5, "ZSTD_equivalentParams()==1");
829
+ if (ZSTD_equivalentParams(params, zc->appliedParams)) {
830
+ DEBUGLOG(4, "ZSTD_equivalentParams()==1");
831
+ assert(!(params.ldmParams.enableLdm &&
832
+ params.ldmParams.hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET));
619
833
  zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
620
834
  zc->entropy->offcode_repeatMode = FSE_repeat_none;
621
835
  zc->entropy->matchlength_repeatMode = FSE_repeat_none;
@@ -623,12 +837,21 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
623
837
  return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
624
838
  } }
625
839
 
840
+ if (params.ldmParams.enableLdm) {
841
+ /* Adjust long distance matching parameters */
842
+ ZSTD_ldm_adjustParameters(&params.ldmParams, params.cParams.windowLog);
843
+ assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
844
+ assert(params.ldmParams.hashEveryLog < 32);
845
+ zc->ldmState.hashPower =
846
+ ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
847
+ }
848
+
626
849
  { size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
627
850
  U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
628
851
  size_t const maxNbSeq = blockSize / divider;
629
852
  size_t const tokenSpace = blockSize + 11*maxNbSeq;
630
853
  size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ?
631
- 0 : (1 << params.cParams.chainLog);
854
+ 0 : ((size_t)1 << params.cParams.chainLog);
632
855
  size_t const hSize = ((size_t)1) << params.cParams.hashLog;
633
856
  U32 const hashLog3 = (params.cParams.searchLength>3) ?
634
857
  0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
@@ -646,10 +869,13 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
646
869
  || (params.cParams.strategy == ZSTD_btultra)) ?
647
870
  optPotentialSpace : 0;
648
871
  size_t const bufferSpace = buffInSize + buffOutSize;
649
- size_t const neededSpace = entropySpace + optSpace + tableSpace
650
- + tokenSpace + bufferSpace;
872
+ size_t const ldmSpace = params.ldmParams.enableLdm
873
+ ? ZSTD_ldm_getTableSize(params.ldmParams.hashLog, params.ldmParams.bucketSizeLog)
874
+ : 0;
875
+ size_t const neededSpace = entropySpace + optSpace + ldmSpace +
876
+ tableSpace + tokenSpace + bufferSpace;
651
877
 
652
- if (zc->workSpaceSize < neededSpace) { /* too small : resize /*/
878
+ if (zc->workSpaceSize < neededSpace) { /* too small : resize */
653
879
  DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
654
880
  (unsigned)zc->workSpaceSize>>10,
655
881
  (unsigned)neededSpace>>10);
@@ -714,6 +940,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
714
940
  ptr = zc->optState.priceTable + ZSTD_OPT_NUM+1;
715
941
  }
716
942
 
943
+ /* ldm hash table */
944
+ /* initialize bucketOffsets table later for pointer alignment */
945
+ if (params.ldmParams.enableLdm) {
946
+ size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
947
+ memset(ptr, 0, ldmHSize * sizeof(ldmEntry_t));
948
+ assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
949
+ zc->ldmState.hashTable = (ldmEntry_t*)ptr;
950
+ ptr = zc->ldmState.hashTable + ldmHSize;
951
+ }
952
+
717
953
  /* table Space */
718
954
  if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
719
955
  assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
@@ -731,6 +967,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
731
967
  zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
732
968
  ptr = zc->seqStore.litStart + blockSize;
733
969
 
970
+ /* ldm bucketOffsets table */
971
+ if (params.ldmParams.enableLdm) {
972
+ size_t const ldmBucketSize =
973
+ ((size_t)1) << (params.ldmParams.hashLog -
974
+ params.ldmParams.bucketSizeLog);
975
+ memset(ptr, 0, ldmBucketSize);
976
+ zc->ldmState.bucketOffsets = (BYTE*)ptr;
977
+ ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
978
+ }
979
+
734
980
  /* buffers */
735
981
  zc->inBuffSize = buffInSize;
736
982
  zc->inBuff = (char*)ptr;
@@ -753,6 +999,8 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
753
999
 
754
1000
  /*! ZSTD_copyCCtx_internal() :
755
1001
  * Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
1002
+ * The "context", in this case, refers to the hash and chain tables, entropy
1003
+ * tables, and dictionary offsets.
756
1004
  * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
757
1005
  * pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
758
1006
  * @return : 0, or an error code */
@@ -766,14 +1014,16 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
766
1014
  if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
767
1015
 
768
1016
  memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
769
- { ZSTD_parameters params = srcCCtx->appliedParams;
1017
+ { ZSTD_CCtx_params params = dstCCtx->requestedParams;
1018
+ /* Copy only compression parameters related to tables. */
1019
+ params.cParams = srcCCtx->appliedParams.cParams;
770
1020
  params.fParams = fParams;
771
1021
  ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
772
1022
  ZSTDcrp_noMemset, zbuff);
773
1023
  }
774
1024
 
775
1025
  /* copy tables */
776
- { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->appliedParams.cParams.chainLog);
1026
+ { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
777
1027
  size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
778
1028
  size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
779
1029
  size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
@@ -826,18 +1076,36 @@ static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reduce
826
1076
  }
827
1077
  }
828
1078
 
1079
+ /*! ZSTD_ldm_reduceTable() :
1080
+ * reduce table indexes by `reducerValue` */
1081
+ static void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,
1082
+ U32 const reducerValue)
1083
+ {
1084
+ U32 u;
1085
+ for (u = 0; u < size; u++) {
1086
+ if (table[u].offset < reducerValue) table[u].offset = 0;
1087
+ else table[u].offset -= reducerValue;
1088
+ }
1089
+ }
1090
+
829
1091
  /*! ZSTD_reduceIndex() :
830
1092
  * rescale all indexes to avoid future overflow (indexes are U32) */
831
1093
  static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
832
1094
  {
833
- { U32 const hSize = 1 << zc->appliedParams.cParams.hashLog;
1095
+ { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
834
1096
  ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
835
1097
 
836
- { U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->appliedParams.cParams.chainLog);
1098
+ { U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((U32)1 << zc->appliedParams.cParams.chainLog);
837
1099
  ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
838
1100
 
839
- { U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
1101
+ { U32 const h3Size = (zc->hashLog3) ? (U32)1 << zc->hashLog3 : 0;
840
1102
  ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
1103
+
1104
+ { if (zc->appliedParams.ldmParams.enableLdm) {
1105
+ U32 const ldmHSize = (U32)1 << zc->appliedParams.ldmParams.hashLog;
1106
+ ZSTD_ldm_reduceTable(zc->ldmState.hashTable, ldmHSize, reducerValue);
1107
+ }
1108
+ }
841
1109
  }
842
1110
 
843
1111
 
@@ -976,24 +1244,6 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
976
1244
  return lhSize+cLitSize;
977
1245
  }
978
1246
 
979
- static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
980
- 8, 9, 10, 11, 12, 13, 14, 15,
981
- 16, 16, 17, 17, 18, 18, 19, 19,
982
- 20, 20, 20, 20, 21, 21, 21, 21,
983
- 22, 22, 22, 22, 22, 22, 22, 22,
984
- 23, 23, 23, 23, 23, 23, 23, 23,
985
- 24, 24, 24, 24, 24, 24, 24, 24,
986
- 24, 24, 24, 24, 24, 24, 24, 24 };
987
-
988
- static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
989
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
990
- 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
991
- 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
992
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
993
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
994
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
995
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
996
-
997
1247
 
998
1248
  void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
999
1249
  {
@@ -1018,20 +1268,30 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1018
1268
  mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
1019
1269
  }
1020
1270
 
1021
- MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(FSE_repeat* repeatMode,
1022
- size_t const mostFrequent, size_t nbSeq, U32 defaultNormLog)
1271
+ typedef enum {
1272
+ ZSTD_defaultDisallowed = 0,
1273
+ ZSTD_defaultAllowed = 1
1274
+ } ZSTD_defaultPolicy_e;
1275
+
1276
+ MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(
1277
+ FSE_repeat* repeatMode, size_t const mostFrequent, size_t nbSeq,
1278
+ U32 defaultNormLog, ZSTD_defaultPolicy_e const isDefaultAllowed)
1023
1279
  {
1024
1280
  #define MIN_SEQ_FOR_DYNAMIC_FSE 64
1025
1281
  #define MAX_SEQ_FOR_STATIC_FSE 1000
1026
-
1027
- if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
1282
+ ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
1283
+ if ((mostFrequent == nbSeq) && (!isDefaultAllowed || nbSeq > 2)) {
1284
+ /* Prefer set_basic over set_rle when there are 2 or less symbols,
1285
+ * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
1286
+ * If basic encoding isn't possible, always choose RLE.
1287
+ */
1028
1288
  *repeatMode = FSE_repeat_check;
1029
1289
  return set_rle;
1030
1290
  }
1031
- if ((*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
1291
+ if (isDefaultAllowed && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
1032
1292
  return set_repeat;
1033
1293
  }
1034
- if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1)))) {
1294
+ if (isDefaultAllowed && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1))))) {
1035
1295
  *repeatMode = FSE_repeat_valid;
1036
1296
  return set_basic;
1037
1297
  }
@@ -1059,1748 +1319,234 @@ MEM_STATIC size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
1059
1319
  case set_basic:
1060
1320
  CHECK_F(FSE_buildCTable_wksp(CTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize));
1061
1321
  return 0;
1062
- case set_compressed: {
1063
- S16 norm[MaxSeq + 1];
1064
- size_t nbSeq_1 = nbSeq;
1065
- const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
1066
- if (count[codeTable[nbSeq-1]] > 1) {
1067
- count[codeTable[nbSeq-1]]--;
1068
- nbSeq_1--;
1069
- }
1070
- CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
1071
- { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
1072
- if (FSE_isError(NCountSize)) return NCountSize;
1073
- CHECK_F(FSE_buildCTable_wksp(CTable, norm, max, tableLog, workspace, workspaceSize));
1074
- return NCountSize;
1075
- }
1076
- }
1077
- default: return assert(0), ERROR(GENERIC);
1078
- }
1079
- }
1080
-
1081
- MEM_STATIC size_t ZSTD_encodeSequences(void* dst, size_t dstCapacity,
1082
- FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1083
- FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1084
- FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1085
- seqDef const* sequences, size_t nbSeq, int longOffsets)
1086
- {
1087
- BIT_CStream_t blockStream;
1088
- FSE_CState_t stateMatchLength;
1089
- FSE_CState_t stateOffsetBits;
1090
- FSE_CState_t stateLitLength;
1091
-
1092
- CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
1093
-
1094
- /* first symbols */
1095
- FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
1096
- FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
1097
- FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
1098
- BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
1099
- if (MEM_32bits()) BIT_flushBits(&blockStream);
1100
- BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
1101
- if (MEM_32bits()) BIT_flushBits(&blockStream);
1102
- if (longOffsets) {
1103
- U32 const ofBits = ofCodeTable[nbSeq-1];
1104
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
1105
- if (extraBits) {
1106
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
1107
- BIT_flushBits(&blockStream);
1108
- }
1109
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
1110
- ofBits - extraBits);
1111
- } else {
1112
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
1113
- }
1114
- BIT_flushBits(&blockStream);
1115
-
1116
- { size_t n;
1117
- for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
1118
- BYTE const llCode = llCodeTable[n];
1119
- BYTE const ofCode = ofCodeTable[n];
1120
- BYTE const mlCode = mlCodeTable[n];
1121
- U32 const llBits = LL_bits[llCode];
1122
- U32 const ofBits = ofCode; /* 32b*/ /* 64b*/
1123
- U32 const mlBits = ML_bits[mlCode];
1124
- /* (7)*/ /* (7)*/
1125
- FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
1126
- FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
1127
- if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
1128
- FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
1129
- if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
1130
- BIT_flushBits(&blockStream); /* (7)*/
1131
- BIT_addBits(&blockStream, sequences[n].litLength, llBits);
1132
- if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
1133
- BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
1134
- if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
1135
- if (longOffsets) {
1136
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
1137
- if (extraBits) {
1138
- BIT_addBits(&blockStream, sequences[n].offset, extraBits);
1139
- BIT_flushBits(&blockStream); /* (7)*/
1140
- }
1141
- BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
1142
- ofBits - extraBits); /* 31 */
1143
- } else {
1144
- BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
1145
- }
1146
- BIT_flushBits(&blockStream); /* (7)*/
1147
- } }
1148
-
1149
- FSE_flushCState(&blockStream, &stateMatchLength);
1150
- FSE_flushCState(&blockStream, &stateOffsetBits);
1151
- FSE_flushCState(&blockStream, &stateLitLength);
1152
-
1153
- { size_t const streamSize = BIT_closeCStream(&blockStream);
1154
- if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
1155
- return streamSize;
1156
- }
1157
- }
1158
-
1159
- MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1160
- ZSTD_entropyCTables_t* entropy,
1161
- ZSTD_compressionParameters const* cParams,
1162
- void* dst, size_t dstCapacity)
1163
- {
1164
- const int longOffsets = cParams->windowLog > STREAM_ACCUMULATOR_MIN;
1165
- U32 count[MaxSeq+1];
1166
- FSE_CTable* CTable_LitLength = entropy->litlengthCTable;
1167
- FSE_CTable* CTable_OffsetBits = entropy->offcodeCTable;
1168
- FSE_CTable* CTable_MatchLength = entropy->matchlengthCTable;
1169
- U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
1170
- const seqDef* const sequences = seqStorePtr->sequencesStart;
1171
- const BYTE* const ofCodeTable = seqStorePtr->ofCode;
1172
- const BYTE* const llCodeTable = seqStorePtr->llCode;
1173
- const BYTE* const mlCodeTable = seqStorePtr->mlCode;
1174
- BYTE* const ostart = (BYTE*)dst;
1175
- BYTE* const oend = ostart + dstCapacity;
1176
- BYTE* op = ostart;
1177
- size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
1178
- BYTE* seqHead;
1179
-
1180
- ZSTD_STATIC_ASSERT(sizeof(entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
1181
-
1182
- /* Compress literals */
1183
- { const BYTE* const literals = seqStorePtr->litStart;
1184
- size_t const litSize = seqStorePtr->lit - literals;
1185
- size_t const cSize = ZSTD_compressLiterals(
1186
- entropy, cParams->strategy, op, dstCapacity, literals, litSize);
1187
- if (ZSTD_isError(cSize))
1188
- return cSize;
1189
- op += cSize;
1190
- }
1191
-
1192
- /* Sequences Header */
1193
- if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
1194
- if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
1195
- else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
1196
- else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1197
- if (nbSeq==0) return op - ostart;
1198
-
1199
- /* seqHead : flags for FSE encoding type */
1200
- seqHead = op++;
1201
-
1202
- /* convert length/distances into codes */
1203
- ZSTD_seqToCodes(seqStorePtr);
1204
- /* CTable for Literal Lengths */
1205
- { U32 max = MaxLL;
1206
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
1207
- LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog);
1208
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
1209
- count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
1210
- entropy->workspace, sizeof(entropy->workspace));
1211
- if (ZSTD_isError(countSize)) return countSize;
1212
- op += countSize;
1213
- } }
1214
- /* CTable for Offsets */
1215
- { U32 max = MaxOff;
1216
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
1217
- Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog);
1218
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
1219
- count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, MaxOff,
1220
- entropy->workspace, sizeof(entropy->workspace));
1221
- if (ZSTD_isError(countSize)) return countSize;
1222
- op += countSize;
1223
- } }
1224
- /* CTable for MatchLengths */
1225
- { U32 max = MaxML;
1226
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
1227
- MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog);
1228
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
1229
- count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
1230
- entropy->workspace, sizeof(entropy->workspace));
1231
- if (ZSTD_isError(countSize)) return countSize;
1232
- op += countSize;
1233
- } }
1234
-
1235
- *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
1236
-
1237
- { size_t const streamSize = ZSTD_encodeSequences(op, oend - op,
1238
- CTable_MatchLength, mlCodeTable,
1239
- CTable_OffsetBits, ofCodeTable,
1240
- CTable_LitLength, llCodeTable,
1241
- sequences, nbSeq, longOffsets);
1242
- if (ZSTD_isError(streamSize)) return streamSize;
1243
- op += streamSize;
1244
- }
1245
-
1246
- return op - ostart;
1247
- }
1248
-
1249
- MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1250
- ZSTD_entropyCTables_t* entropy,
1251
- ZSTD_compressionParameters const* cParams,
1252
- void* dst, size_t dstCapacity,
1253
- size_t srcSize)
1254
- {
1255
- size_t const cSize = ZSTD_compressSequences_internal(seqStorePtr, entropy, cParams,
1256
- dst, dstCapacity);
1257
- size_t const minGain = ZSTD_minGain(srcSize);
1258
- size_t const maxCSize = srcSize - minGain;
1259
- /* If the srcSize <= dstCapacity, then there is enough space to write a
1260
- * raw uncompressed block. Since we ran out of space, the block must not
1261
- * be compressible, so fall back to a raw uncompressed block.
1262
- */
1263
- int const uncompressibleError = cSize == ERROR(dstSize_tooSmall) && srcSize <= dstCapacity;
1264
-
1265
- if (ZSTD_isError(cSize) && !uncompressibleError)
1266
- return cSize;
1267
- /* Check compressibility */
1268
- if (cSize >= maxCSize || uncompressibleError) {
1269
- entropy->hufCTable_repeatMode = HUF_repeat_none;
1270
- entropy->offcode_repeatMode = FSE_repeat_none;
1271
- entropy->matchlength_repeatMode = FSE_repeat_none;
1272
- entropy->litlength_repeatMode = FSE_repeat_none;
1273
- return 0;
1274
- }
1275
- assert(!ZSTD_isError(cSize));
1276
-
1277
- /* confirm repcodes */
1278
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->rep[i] = seqStorePtr->repToConfirm[i]; }
1279
- return cSize;
1280
- }
1281
-
1282
-
1283
- /*! ZSTD_storeSeq() :
1284
- Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
1285
- `offsetCode` : distance to match, or 0 == repCode.
1286
- `matchCode` : matchLength - MINMATCH
1287
- */
1288
- MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
1289
- {
1290
- #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 6)
1291
- static const BYTE* g_start = NULL;
1292
- U32 const pos = (U32)((const BYTE*)literals - g_start);
1293
- if (g_start==NULL) g_start = (const BYTE*)literals;
1294
- if ((pos > 0) && (pos < 1000000000))
1295
- DEBUGLOG(6, "Cpos %6u :%5u literals & match %3u bytes at distance %6u",
1296
- pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
1297
- #endif
1298
- /* copy Literals */
1299
- assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + 128 KB);
1300
- ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
1301
- seqStorePtr->lit += litLength;
1302
-
1303
- /* literal Length */
1304
- if (litLength>0xFFFF) {
1305
- seqStorePtr->longLengthID = 1;
1306
- seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
1307
- }
1308
- seqStorePtr->sequences[0].litLength = (U16)litLength;
1309
-
1310
- /* match offset */
1311
- seqStorePtr->sequences[0].offset = offsetCode + 1;
1312
-
1313
- /* match Length */
1314
- if (matchCode>0xFFFF) {
1315
- seqStorePtr->longLengthID = 2;
1316
- seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
1317
- }
1318
- seqStorePtr->sequences[0].matchLength = (U16)matchCode;
1319
-
1320
- seqStorePtr->sequences++;
1321
- }
1322
-
1323
-
1324
- /*-*************************************
1325
- * Match length counter
1326
- ***************************************/
1327
- static unsigned ZSTD_NbCommonBytes (register size_t val)
1328
- {
1329
- if (MEM_isLittleEndian()) {
1330
- if (MEM_64bits()) {
1331
- # if defined(_MSC_VER) && defined(_WIN64)
1332
- unsigned long r = 0;
1333
- _BitScanForward64( &r, (U64)val );
1334
- return (unsigned)(r>>3);
1335
- # elif defined(__GNUC__) && (__GNUC__ >= 3)
1336
- return (__builtin_ctzll((U64)val) >> 3);
1337
- # else
1338
- static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
1339
- 0, 3, 1, 3, 1, 4, 2, 7,
1340
- 0, 2, 3, 6, 1, 5, 3, 5,
1341
- 1, 3, 4, 4, 2, 5, 6, 7,
1342
- 7, 0, 1, 2, 3, 3, 4, 6,
1343
- 2, 6, 5, 5, 3, 4, 5, 6,
1344
- 7, 1, 2, 4, 6, 4, 4, 5,
1345
- 7, 2, 6, 5, 7, 6, 7, 7 };
1346
- return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
1347
- # endif
1348
- } else { /* 32 bits */
1349
- # if defined(_MSC_VER)
1350
- unsigned long r=0;
1351
- _BitScanForward( &r, (U32)val );
1352
- return (unsigned)(r>>3);
1353
- # elif defined(__GNUC__) && (__GNUC__ >= 3)
1354
- return (__builtin_ctz((U32)val) >> 3);
1355
- # else
1356
- static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
1357
- 3, 2, 2, 1, 3, 2, 0, 1,
1358
- 3, 3, 1, 2, 2, 2, 2, 0,
1359
- 3, 1, 2, 0, 1, 0, 1, 1 };
1360
- return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
1361
- # endif
1362
- }
1363
- } else { /* Big Endian CPU */
1364
- if (MEM_64bits()) {
1365
- # if defined(_MSC_VER) && defined(_WIN64)
1366
- unsigned long r = 0;
1367
- _BitScanReverse64( &r, val );
1368
- return (unsigned)(r>>3);
1369
- # elif defined(__GNUC__) && (__GNUC__ >= 3)
1370
- return (__builtin_clzll(val) >> 3);
1371
- # else
1372
- unsigned r;
1373
- const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
1374
- if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
1375
- if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
1376
- r += (!val);
1377
- return r;
1378
- # endif
1379
- } else { /* 32 bits */
1380
- # if defined(_MSC_VER)
1381
- unsigned long r = 0;
1382
- _BitScanReverse( &r, (unsigned long)val );
1383
- return (unsigned)(r>>3);
1384
- # elif defined(__GNUC__) && (__GNUC__ >= 3)
1385
- return (__builtin_clz((U32)val) >> 3);
1386
- # else
1387
- unsigned r;
1388
- if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
1389
- r += (!val);
1390
- return r;
1391
- # endif
1392
- } }
1393
- }
1394
-
1395
-
1396
- static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
1397
- {
1398
- const BYTE* const pStart = pIn;
1399
- const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);
1400
-
1401
- while (pIn < pInLoopLimit) {
1402
- size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
1403
- if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
1404
- pIn += ZSTD_NbCommonBytes(diff);
1405
- return (size_t)(pIn - pStart);
1406
- }
1407
- if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
1408
- if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
1409
- if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
1410
- return (size_t)(pIn - pStart);
1411
- }
1412
-
1413
- /** ZSTD_count_2segments() :
1414
- * can count match length with `ip` & `match` in 2 different segments.
1415
- * convention : on reaching mEnd, match count continue starting from iStart
1416
- */
1417
- static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
1418
- {
1419
- const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
1420
- size_t const matchLength = ZSTD_count(ip, match, vEnd);
1421
- if (match + matchLength != mEnd) return matchLength;
1422
- return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
1423
- }
1424
-
1425
-
1426
- /*-*************************************
1427
- * Hashes
1428
- ***************************************/
1429
- static const U32 prime3bytes = 506832829U;
1430
- static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
1431
- MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
1432
-
1433
- static const U32 prime4bytes = 2654435761U;
1434
- static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
1435
- static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
1436
-
1437
- static const U64 prime5bytes = 889523592379ULL;
1438
- static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
1439
- static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
1440
-
1441
- static const U64 prime6bytes = 227718039650203ULL;
1442
- static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
1443
- static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
1444
-
1445
- static const U64 prime7bytes = 58295818150454627ULL;
1446
- static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
1447
- static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
1448
-
1449
- static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
1450
- static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
1451
- static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
1452
-
1453
- static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
1454
- {
1455
- switch(mls)
1456
- {
1457
- default:
1458
- case 4: return ZSTD_hash4Ptr(p, hBits);
1459
- case 5: return ZSTD_hash5Ptr(p, hBits);
1460
- case 6: return ZSTD_hash6Ptr(p, hBits);
1461
- case 7: return ZSTD_hash7Ptr(p, hBits);
1462
- case 8: return ZSTD_hash8Ptr(p, hBits);
1463
- }
1464
- }
1465
-
1466
-
1467
- /*-*************************************
1468
- * Fast Scan
1469
- ***************************************/
1470
- static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
1471
- {
1472
- U32* const hashTable = zc->hashTable;
1473
- U32 const hBits = zc->appliedParams.cParams.hashLog;
1474
- const BYTE* const base = zc->base;
1475
- const BYTE* ip = base + zc->nextToUpdate;
1476
- const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
1477
- const size_t fastHashFillStep = 3;
1478
-
1479
- while(ip <= iend) {
1480
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
1481
- ip += fastHashFillStep;
1482
- }
1483
- }
1484
-
1485
-
1486
- FORCE_INLINE_TEMPLATE
1487
- void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
1488
- const void* src, size_t srcSize,
1489
- const U32 mls)
1490
- {
1491
- U32* const hashTable = cctx->hashTable;
1492
- U32 const hBits = cctx->appliedParams.cParams.hashLog;
1493
- seqStore_t* seqStorePtr = &(cctx->seqStore);
1494
- const BYTE* const base = cctx->base;
1495
- const BYTE* const istart = (const BYTE*)src;
1496
- const BYTE* ip = istart;
1497
- const BYTE* anchor = istart;
1498
- const U32 lowestIndex = cctx->dictLimit;
1499
- const BYTE* const lowest = base + lowestIndex;
1500
- const BYTE* const iend = istart + srcSize;
1501
- const BYTE* const ilimit = iend - HASH_READ_SIZE;
1502
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
1503
- U32 offsetSaved = 0;
1504
-
1505
- /* init */
1506
- ip += (ip==lowest);
1507
- { U32 const maxRep = (U32)(ip-lowest);
1508
- if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
1509
- if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
1510
- }
1511
-
1512
- /* Main Search Loop */
1513
- while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
1514
- size_t mLength;
1515
- size_t const h = ZSTD_hashPtr(ip, hBits, mls);
1516
- U32 const current = (U32)(ip-base);
1517
- U32 const matchIndex = hashTable[h];
1518
- const BYTE* match = base + matchIndex;
1519
- hashTable[h] = current; /* update hash table */
1520
-
1521
- if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
1522
- mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
1523
- ip++;
1524
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1525
- } else {
1526
- U32 offset;
1527
- if ( (matchIndex <= lowestIndex) || (MEM_read32(match) != MEM_read32(ip)) ) {
1528
- ip += ((ip-anchor) >> g_searchStrength) + 1;
1529
- continue;
1530
- }
1531
- mLength = ZSTD_count(ip+4, match+4, iend) + 4;
1532
- offset = (U32)(ip-match);
1533
- while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1534
- offset_2 = offset_1;
1535
- offset_1 = offset;
1536
-
1537
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1538
- }
1539
-
1540
- /* match found */
1541
- ip += mLength;
1542
- anchor = ip;
1543
-
1544
- if (ip <= ilimit) {
1545
- /* Fill Table */
1546
- hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
1547
- hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1548
- /* check immediate repcode */
1549
- while ( (ip <= ilimit)
1550
- && ( (offset_2>0)
1551
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
1552
- /* store sequence */
1553
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
1554
- { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
1555
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
1556
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
1557
- ip += rLength;
1558
- anchor = ip;
1559
- continue; /* faster when present ... (?) */
1560
- } } }
1561
-
1562
- /* save reps for next block */
1563
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
1564
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
1565
-
1566
- /* Last Literals */
1567
- { size_t const lastLLSize = iend - anchor;
1568
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
1569
- seqStorePtr->lit += lastLLSize;
1570
- }
1571
- }
1572
-
1573
-
1574
- static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
1575
- const void* src, size_t srcSize)
1576
- {
1577
- const U32 mls = ctx->appliedParams.cParams.searchLength;
1578
- switch(mls)
1579
- {
1580
- default: /* includes case 3 */
1581
- case 4 :
1582
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
1583
- case 5 :
1584
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
1585
- case 6 :
1586
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
1587
- case 7 :
1588
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
1589
- }
1590
- }
1591
-
1592
-
1593
- static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
1594
- const void* src, size_t srcSize,
1595
- const U32 mls)
1596
- {
1597
- U32* hashTable = ctx->hashTable;
1598
- const U32 hBits = ctx->appliedParams.cParams.hashLog;
1599
- seqStore_t* seqStorePtr = &(ctx->seqStore);
1600
- const BYTE* const base = ctx->base;
1601
- const BYTE* const dictBase = ctx->dictBase;
1602
- const BYTE* const istart = (const BYTE*)src;
1603
- const BYTE* ip = istart;
1604
- const BYTE* anchor = istart;
1605
- const U32 lowestIndex = ctx->lowLimit;
1606
- const BYTE* const dictStart = dictBase + lowestIndex;
1607
- const U32 dictLimit = ctx->dictLimit;
1608
- const BYTE* const lowPrefixPtr = base + dictLimit;
1609
- const BYTE* const dictEnd = dictBase + dictLimit;
1610
- const BYTE* const iend = istart + srcSize;
1611
- const BYTE* const ilimit = iend - 8;
1612
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
1613
-
1614
- /* Search Loop */
1615
- while (ip < ilimit) { /* < instead of <=, because (ip+1) */
1616
- const size_t h = ZSTD_hashPtr(ip, hBits, mls);
1617
- const U32 matchIndex = hashTable[h];
1618
- const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
1619
- const BYTE* match = matchBase + matchIndex;
1620
- const U32 current = (U32)(ip-base);
1621
- const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
1622
- const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
1623
- const BYTE* repMatch = repBase + repIndex;
1624
- size_t mLength;
1625
- hashTable[h] = current; /* update hash table */
1626
-
1627
- if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
1628
- && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
1629
- const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
1630
- mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
1631
- ip++;
1632
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1633
- } else {
1634
- if ( (matchIndex < lowestIndex) ||
1635
- (MEM_read32(match) != MEM_read32(ip)) ) {
1636
- ip += ((ip-anchor) >> g_searchStrength) + 1;
1637
- continue;
1638
- }
1639
- { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
1640
- const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
1641
- U32 offset;
1642
- mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
1643
- while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1644
- offset = current - matchIndex;
1645
- offset_2 = offset_1;
1646
- offset_1 = offset;
1647
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1648
- } }
1649
-
1650
- /* found a match : store it */
1651
- ip += mLength;
1652
- anchor = ip;
1653
-
1654
- if (ip <= ilimit) {
1655
- /* Fill Table */
1656
- hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
1657
- hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1658
- /* check immediate repcode */
1659
- while (ip <= ilimit) {
1660
- U32 const current2 = (U32)(ip-base);
1661
- U32 const repIndex2 = current2 - offset_2;
1662
- const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
1663
- if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
1664
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
1665
- const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
1666
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
1667
- U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
1668
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
1669
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
1670
- ip += repLength2;
1671
- anchor = ip;
1672
- continue;
1673
- }
1674
- break;
1675
- } } }
1676
-
1677
- /* save reps for next block */
1678
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
1679
-
1680
- /* Last Literals */
1681
- { size_t const lastLLSize = iend - anchor;
1682
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
1683
- seqStorePtr->lit += lastLLSize;
1684
- }
1685
- }
1686
-
1687
-
1688
- static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
1689
- const void* src, size_t srcSize)
1690
- {
1691
- U32 const mls = ctx->appliedParams.cParams.searchLength;
1692
- switch(mls)
1693
- {
1694
- default: /* includes case 3 */
1695
- case 4 :
1696
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
1697
- case 5 :
1698
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return;
1699
- case 6 :
1700
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return;
1701
- case 7 :
1702
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return;
1703
- }
1704
- }
1705
-
1706
-
1707
- /*-*************************************
1708
- * Double Fast
1709
- ***************************************/
1710
- static void ZSTD_fillDoubleHashTable (ZSTD_CCtx* cctx, const void* end, const U32 mls)
1711
- {
1712
- U32* const hashLarge = cctx->hashTable;
1713
- U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
1714
- U32* const hashSmall = cctx->chainTable;
1715
- U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
1716
- const BYTE* const base = cctx->base;
1717
- const BYTE* ip = base + cctx->nextToUpdate;
1718
- const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
1719
- const size_t fastHashFillStep = 3;
1720
-
1721
- while(ip <= iend) {
1722
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base);
1723
- hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base);
1724
- ip += fastHashFillStep;
1725
- }
1726
- }
1727
-
1728
-
1729
- FORCE_INLINE_TEMPLATE
1730
- void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
1731
- const void* src, size_t srcSize,
1732
- const U32 mls)
1733
- {
1734
- U32* const hashLong = cctx->hashTable;
1735
- const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
1736
- U32* const hashSmall = cctx->chainTable;
1737
- const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
1738
- seqStore_t* seqStorePtr = &(cctx->seqStore);
1739
- const BYTE* const base = cctx->base;
1740
- const BYTE* const istart = (const BYTE*)src;
1741
- const BYTE* ip = istart;
1742
- const BYTE* anchor = istart;
1743
- const U32 lowestIndex = cctx->dictLimit;
1744
- const BYTE* const lowest = base + lowestIndex;
1745
- const BYTE* const iend = istart + srcSize;
1746
- const BYTE* const ilimit = iend - HASH_READ_SIZE;
1747
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
1748
- U32 offsetSaved = 0;
1749
-
1750
- /* init */
1751
- ip += (ip==lowest);
1752
- { U32 const maxRep = (U32)(ip-lowest);
1753
- if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
1754
- if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
1755
- }
1756
-
1757
- /* Main Search Loop */
1758
- while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
1759
- size_t mLength;
1760
- size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
1761
- size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
1762
- U32 const current = (U32)(ip-base);
1763
- U32 const matchIndexL = hashLong[h2];
1764
- U32 const matchIndexS = hashSmall[h];
1765
- const BYTE* matchLong = base + matchIndexL;
1766
- const BYTE* match = base + matchIndexS;
1767
- hashLong[h2] = hashSmall[h] = current; /* update hash tables */
1768
-
1769
- assert(offset_1 <= current); /* supposed guaranteed by construction */
1770
- if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
1771
- /* favor repcode */
1772
- mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
1773
- ip++;
1774
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1775
- } else {
1776
- U32 offset;
1777
- if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
1778
- mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;
1779
- offset = (U32)(ip-matchLong);
1780
- while (((ip>anchor) & (matchLong>lowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
1781
- } else if ( (matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
1782
- size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
1783
- U32 const matchIndexL3 = hashLong[hl3];
1784
- const BYTE* matchL3 = base + matchIndexL3;
1785
- hashLong[hl3] = current + 1;
1786
- if ( (matchIndexL3 > lowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
1787
- mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
1788
- ip++;
1789
- offset = (U32)(ip-matchL3);
1790
- while (((ip>anchor) & (matchL3>lowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
1791
- } else {
1792
- mLength = ZSTD_count(ip+4, match+4, iend) + 4;
1793
- offset = (U32)(ip-match);
1794
- while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1795
- }
1796
- } else {
1797
- ip += ((ip-anchor) >> g_searchStrength) + 1;
1798
- continue;
1799
- }
1800
-
1801
- offset_2 = offset_1;
1802
- offset_1 = offset;
1803
-
1804
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1805
- }
1806
-
1807
- /* match found */
1808
- ip += mLength;
1809
- anchor = ip;
1810
-
1811
- if (ip <= ilimit) {
1812
- /* Fill Table */
1813
- hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] =
1814
- hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; /* here because current+2 could be > iend-8 */
1815
- hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] =
1816
- hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
1817
-
1818
- /* check immediate repcode */
1819
- while ( (ip <= ilimit)
1820
- && ( (offset_2>0)
1821
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
1822
- /* store sequence */
1823
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
1824
- { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
1825
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
1826
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
1827
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
1828
- ip += rLength;
1829
- anchor = ip;
1830
- continue; /* faster when present ... (?) */
1831
- } } }
1832
-
1833
- /* save reps for next block */
1834
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
1835
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
1836
-
1837
- /* Last Literals */
1838
- { size_t const lastLLSize = iend - anchor;
1839
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
1840
- seqStorePtr->lit += lastLLSize;
1841
- }
1842
- }
1843
-
1844
-
1845
- static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1846
- {
1847
- const U32 mls = ctx->appliedParams.cParams.searchLength;
1848
- switch(mls)
1849
- {
1850
- default: /* includes case 3 */
1851
- case 4 :
1852
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); return;
1853
- case 5 :
1854
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5); return;
1855
- case 6 :
1856
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6); return;
1857
- case 7 :
1858
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7); return;
1859
- }
1860
- }
1861
-
1862
-
1863
- static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
1864
- const void* src, size_t srcSize,
1865
- const U32 mls)
1866
- {
1867
- U32* const hashLong = ctx->hashTable;
1868
- U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
1869
- U32* const hashSmall = ctx->chainTable;
1870
- U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
1871
- seqStore_t* seqStorePtr = &(ctx->seqStore);
1872
- const BYTE* const base = ctx->base;
1873
- const BYTE* const dictBase = ctx->dictBase;
1874
- const BYTE* const istart = (const BYTE*)src;
1875
- const BYTE* ip = istart;
1876
- const BYTE* anchor = istart;
1877
- const U32 lowestIndex = ctx->lowLimit;
1878
- const BYTE* const dictStart = dictBase + lowestIndex;
1879
- const U32 dictLimit = ctx->dictLimit;
1880
- const BYTE* const lowPrefixPtr = base + dictLimit;
1881
- const BYTE* const dictEnd = dictBase + dictLimit;
1882
- const BYTE* const iend = istart + srcSize;
1883
- const BYTE* const ilimit = iend - 8;
1884
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
1885
-
1886
- /* Search Loop */
1887
- while (ip < ilimit) { /* < instead of <=, because (ip+1) */
1888
- const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
1889
- const U32 matchIndex = hashSmall[hSmall];
1890
- const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
1891
- const BYTE* match = matchBase + matchIndex;
1892
-
1893
- const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);
1894
- const U32 matchLongIndex = hashLong[hLong];
1895
- const BYTE* matchLongBase = matchLongIndex < dictLimit ? dictBase : base;
1896
- const BYTE* matchLong = matchLongBase + matchLongIndex;
1897
-
1898
- const U32 current = (U32)(ip-base);
1899
- const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
1900
- const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
1901
- const BYTE* repMatch = repBase + repIndex;
1902
- size_t mLength;
1903
- hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
1904
-
1905
- if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
1906
- && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
1907
- const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
1908
- mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
1909
- ip++;
1910
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1911
- } else {
1912
- if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
1913
- const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
1914
- const BYTE* lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr;
1915
- U32 offset;
1916
- mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, lowPrefixPtr) + 8;
1917
- offset = current - matchLongIndex;
1918
- while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
1919
- offset_2 = offset_1;
1920
- offset_1 = offset;
1921
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1922
-
1923
- } else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
1924
- size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
1925
- U32 const matchIndex3 = hashLong[h3];
1926
- const BYTE* const match3Base = matchIndex3 < dictLimit ? dictBase : base;
1927
- const BYTE* match3 = match3Base + matchIndex3;
1928
- U32 offset;
1929
- hashLong[h3] = current + 1;
1930
- if ( (matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
1931
- const BYTE* matchEnd = matchIndex3 < dictLimit ? dictEnd : iend;
1932
- const BYTE* lowMatchPtr = matchIndex3 < dictLimit ? dictStart : lowPrefixPtr;
1933
- mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, lowPrefixPtr) + 8;
1934
- ip++;
1935
- offset = current+1 - matchIndex3;
1936
- while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
1937
- } else {
1938
- const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
1939
- const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
1940
- mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
1941
- offset = current - matchIndex;
1942
- while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1943
- }
1944
- offset_2 = offset_1;
1945
- offset_1 = offset;
1946
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1947
-
1948
- } else {
1949
- ip += ((ip-anchor) >> g_searchStrength) + 1;
1950
- continue;
1951
- } }
1952
-
1953
- /* found a match : store it */
1954
- ip += mLength;
1955
- anchor = ip;
1956
-
1957
- if (ip <= ilimit) {
1958
- /* Fill Table */
1959
- hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
1960
- hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
1961
- hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
1962
- hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
1963
- /* check immediate repcode */
1964
- while (ip <= ilimit) {
1965
- U32 const current2 = (U32)(ip-base);
1966
- U32 const repIndex2 = current2 - offset_2;
1967
- const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
1968
- if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
1969
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
1970
- const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
1971
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
1972
- U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
1973
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
1974
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
1975
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
1976
- ip += repLength2;
1977
- anchor = ip;
1978
- continue;
1979
- }
1980
- break;
1981
- } } }
1982
-
1983
- /* save reps for next block */
1984
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
1985
-
1986
- /* Last Literals */
1987
- { size_t const lastLLSize = iend - anchor;
1988
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
1989
- seqStorePtr->lit += lastLLSize;
1990
- }
1991
- }
1992
-
1993
-
1994
- static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
1995
- const void* src, size_t srcSize)
1996
- {
1997
- U32 const mls = ctx->appliedParams.cParams.searchLength;
1998
- switch(mls)
1999
- {
2000
- default: /* includes case 3 */
2001
- case 4 :
2002
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); return;
2003
- case 5 :
2004
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5); return;
2005
- case 6 :
2006
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6); return;
2007
- case 7 :
2008
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7); return;
2009
- }
2010
- }
2011
-
2012
-
2013
- /*-*************************************
2014
- * Binary Tree search
2015
- ***************************************/
2016
- /** ZSTD_insertBt1() : add one or multiple positions to tree.
2017
- * ip : assumed <= iend-8 .
2018
- * @return : nb of positions added */
2019
- static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares,
2020
- U32 extDict)
2021
- {
2022
- U32* const hashTable = zc->hashTable;
2023
- U32 const hashLog = zc->appliedParams.cParams.hashLog;
2024
- size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
2025
- U32* const bt = zc->chainTable;
2026
- U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
2027
- U32 const btMask = (1 << btLog) - 1;
2028
- U32 matchIndex = hashTable[h];
2029
- size_t commonLengthSmaller=0, commonLengthLarger=0;
2030
- const BYTE* const base = zc->base;
2031
- const BYTE* const dictBase = zc->dictBase;
2032
- const U32 dictLimit = zc->dictLimit;
2033
- const BYTE* const dictEnd = dictBase + dictLimit;
2034
- const BYTE* const prefixStart = base + dictLimit;
2035
- const BYTE* match;
2036
- const U32 current = (U32)(ip-base);
2037
- const U32 btLow = btMask >= current ? 0 : current - btMask;
2038
- U32* smallerPtr = bt + 2*(current&btMask);
2039
- U32* largerPtr = smallerPtr + 1;
2040
- U32 dummy32; /* to be nullified at the end */
2041
- U32 const windowLow = zc->lowLimit;
2042
- U32 matchEndIdx = current+8;
2043
- size_t bestLength = 8;
2044
- #ifdef ZSTD_C_PREDICT
2045
- U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
2046
- U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
2047
- predictedSmall += (predictedSmall>0);
2048
- predictedLarge += (predictedLarge>0);
2049
- #endif /* ZSTD_C_PREDICT */
2050
-
2051
- hashTable[h] = current; /* Update Hash Table */
2052
-
2053
- while (nbCompares-- && (matchIndex > windowLow)) {
2054
- U32* const nextPtr = bt + 2*(matchIndex & btMask);
2055
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
2056
-
2057
- #ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
2058
- const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
2059
- if (matchIndex == predictedSmall) {
2060
- /* no need to check length, result known */
2061
- *smallerPtr = matchIndex;
2062
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
2063
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
2064
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
2065
- predictedSmall = predictPtr[1] + (predictPtr[1]>0);
2066
- continue;
2067
- }
2068
- if (matchIndex == predictedLarge) {
2069
- *largerPtr = matchIndex;
2070
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
2071
- largerPtr = nextPtr;
2072
- matchIndex = nextPtr[0];
2073
- predictedLarge = predictPtr[0] + (predictPtr[0]>0);
2074
- continue;
2075
- }
2076
- #endif
2077
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
2078
- match = base + matchIndex;
2079
- if (match[matchLength] == ip[matchLength])
2080
- matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
2081
- } else {
2082
- match = dictBase + matchIndex;
2083
- matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
2084
- if (matchIndex+matchLength >= dictLimit)
2085
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
2086
- }
2087
-
2088
- if (matchLength > bestLength) {
2089
- bestLength = matchLength;
2090
- if (matchLength > matchEndIdx - matchIndex)
2091
- matchEndIdx = matchIndex + (U32)matchLength;
2092
- }
2093
-
2094
- if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
2095
- break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
2096
-
2097
- if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */
2098
- /* match is smaller than current */
2099
- *smallerPtr = matchIndex; /* update smaller idx */
2100
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
2101
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
2102
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
2103
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
2104
- } else {
2105
- /* match is larger than current */
2106
- *largerPtr = matchIndex;
2107
- commonLengthLarger = matchLength;
2108
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
2109
- largerPtr = nextPtr;
2110
- matchIndex = nextPtr[0];
2111
- } }
2112
-
2113
- *smallerPtr = *largerPtr = 0;
2114
- if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
2115
- if (matchEndIdx > current + 8) return matchEndIdx - current - 8;
2116
- return 1;
2117
- }
2118
-
2119
-
2120
- static size_t ZSTD_insertBtAndFindBestMatch (
2121
- ZSTD_CCtx* zc,
2122
- const BYTE* const ip, const BYTE* const iend,
2123
- size_t* offsetPtr,
2124
- U32 nbCompares, const U32 mls,
2125
- U32 extDict)
2126
- {
2127
- U32* const hashTable = zc->hashTable;
2128
- U32 const hashLog = zc->appliedParams.cParams.hashLog;
2129
- size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
2130
- U32* const bt = zc->chainTable;
2131
- U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
2132
- U32 const btMask = (1 << btLog) - 1;
2133
- U32 matchIndex = hashTable[h];
2134
- size_t commonLengthSmaller=0, commonLengthLarger=0;
2135
- const BYTE* const base = zc->base;
2136
- const BYTE* const dictBase = zc->dictBase;
2137
- const U32 dictLimit = zc->dictLimit;
2138
- const BYTE* const dictEnd = dictBase + dictLimit;
2139
- const BYTE* const prefixStart = base + dictLimit;
2140
- const U32 current = (U32)(ip-base);
2141
- const U32 btLow = btMask >= current ? 0 : current - btMask;
2142
- const U32 windowLow = zc->lowLimit;
2143
- U32* smallerPtr = bt + 2*(current&btMask);
2144
- U32* largerPtr = bt + 2*(current&btMask) + 1;
2145
- U32 matchEndIdx = current+8;
2146
- U32 dummy32; /* to be nullified at the end */
2147
- size_t bestLength = 0;
2148
-
2149
- hashTable[h] = current; /* Update Hash Table */
2150
-
2151
- while (nbCompares-- && (matchIndex > windowLow)) {
2152
- U32* const nextPtr = bt + 2*(matchIndex & btMask);
2153
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
2154
- const BYTE* match;
2155
-
2156
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
2157
- match = base + matchIndex;
2158
- if (match[matchLength] == ip[matchLength])
2159
- matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
2160
- } else {
2161
- match = dictBase + matchIndex;
2162
- matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
2163
- if (matchIndex+matchLength >= dictLimit)
2164
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
2165
- }
2166
-
2167
- if (matchLength > bestLength) {
2168
- if (matchLength > matchEndIdx - matchIndex)
2169
- matchEndIdx = matchIndex + (U32)matchLength;
2170
- if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
2171
- bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
2172
- if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
2173
- break; /* drop, to guarantee consistency (miss a little bit of compression) */
2174
- }
2175
-
2176
- if (match[matchLength] < ip[matchLength]) {
2177
- /* match is smaller than current */
2178
- *smallerPtr = matchIndex; /* update smaller idx */
2179
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
2180
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
2181
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
2182
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
2183
- } else {
2184
- /* match is larger than current */
2185
- *largerPtr = matchIndex;
2186
- commonLengthLarger = matchLength;
2187
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
2188
- largerPtr = nextPtr;
2189
- matchIndex = nextPtr[0];
2190
- } }
2191
-
2192
- *smallerPtr = *largerPtr = 0;
2193
-
2194
- zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
2195
- return bestLength;
2196
- }
2197
-
2198
-
2199
- static void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
2200
- {
2201
- const BYTE* const base = zc->base;
2202
- const U32 target = (U32)(ip - base);
2203
- U32 idx = zc->nextToUpdate;
2204
-
2205
- while(idx < target)
2206
- idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
2207
- }
2208
-
2209
- /** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
2210
- static size_t ZSTD_BtFindBestMatch (
2211
- ZSTD_CCtx* zc,
2212
- const BYTE* const ip, const BYTE* const iLimit,
2213
- size_t* offsetPtr,
2214
- const U32 maxNbAttempts, const U32 mls)
2215
- {
2216
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
2217
- ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
2218
- return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
2219
- }
2220
-
2221
-
2222
- static size_t ZSTD_BtFindBestMatch_selectMLS (
2223
- ZSTD_CCtx* zc, /* Index table will be updated */
2224
- const BYTE* ip, const BYTE* const iLimit,
2225
- size_t* offsetPtr,
2226
- const U32 maxNbAttempts, const U32 matchLengthSearch)
2227
- {
2228
- switch(matchLengthSearch)
2229
- {
2230
- default : /* includes case 3 */
2231
- case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
2232
- case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
2233
- case 7 :
2234
- case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
2235
- }
2236
- }
2237
-
2238
-
2239
- static void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
2240
- {
2241
- const BYTE* const base = zc->base;
2242
- const U32 target = (U32)(ip - base);
2243
- U32 idx = zc->nextToUpdate;
2244
-
2245
- while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
2246
- }
2247
-
2248
-
2249
- /** Tree updater, providing best match */
2250
- static size_t ZSTD_BtFindBestMatch_extDict (
2251
- ZSTD_CCtx* zc,
2252
- const BYTE* const ip, const BYTE* const iLimit,
2253
- size_t* offsetPtr,
2254
- const U32 maxNbAttempts, const U32 mls)
2255
- {
2256
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
2257
- ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
2258
- return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
2259
- }
2260
-
2261
-
2262
- static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
2263
- ZSTD_CCtx* zc, /* Index table will be updated */
2264
- const BYTE* ip, const BYTE* const iLimit,
2265
- size_t* offsetPtr,
2266
- const U32 maxNbAttempts, const U32 matchLengthSearch)
2267
- {
2268
- switch(matchLengthSearch)
2269
- {
2270
- default : /* includes case 3 */
2271
- case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
2272
- case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
2273
- case 7 :
2274
- case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
2275
- }
2276
- }
2277
-
2278
-
2279
-
2280
- /* *********************************
2281
- * Hash Chain
2282
- ***********************************/
2283
- #define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
2284
-
2285
- /* Update chains up to ip (excluded)
2286
- Assumption : always within prefix (i.e. not within extDict) */
2287
- FORCE_INLINE_TEMPLATE
2288
- U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
2289
- {
2290
- U32* const hashTable = zc->hashTable;
2291
- const U32 hashLog = zc->appliedParams.cParams.hashLog;
2292
- U32* const chainTable = zc->chainTable;
2293
- const U32 chainMask = (1 << zc->appliedParams.cParams.chainLog) - 1;
2294
- const BYTE* const base = zc->base;
2295
- const U32 target = (U32)(ip - base);
2296
- U32 idx = zc->nextToUpdate;
2297
-
2298
- while(idx < target) { /* catch up */
2299
- size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
2300
- NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
2301
- hashTable[h] = idx;
2302
- idx++;
2303
- }
2304
-
2305
- zc->nextToUpdate = target;
2306
- return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
2307
- }
2308
-
2309
-
2310
- /* inlining is important to hardwire a hot branch (template emulation) */
2311
- FORCE_INLINE_TEMPLATE
2312
- size_t ZSTD_HcFindBestMatch_generic (
2313
- ZSTD_CCtx* zc, /* Index table will be updated */
2314
- const BYTE* const ip, const BYTE* const iLimit,
2315
- size_t* offsetPtr,
2316
- const U32 maxNbAttempts, const U32 mls, const U32 extDict)
2317
- {
2318
- U32* const chainTable = zc->chainTable;
2319
- const U32 chainSize = (1 << zc->appliedParams.cParams.chainLog);
2320
- const U32 chainMask = chainSize-1;
2321
- const BYTE* const base = zc->base;
2322
- const BYTE* const dictBase = zc->dictBase;
2323
- const U32 dictLimit = zc->dictLimit;
2324
- const BYTE* const prefixStart = base + dictLimit;
2325
- const BYTE* const dictEnd = dictBase + dictLimit;
2326
- const U32 lowLimit = zc->lowLimit;
2327
- const U32 current = (U32)(ip-base);
2328
- const U32 minChain = current > chainSize ? current - chainSize : 0;
2329
- int nbAttempts=maxNbAttempts;
2330
- size_t ml=4-1;
2331
-
2332
- /* HC4 match finder */
2333
- U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
2334
-
2335
- for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
2336
- const BYTE* match;
2337
- size_t currentMl=0;
2338
- if ((!extDict) || matchIndex >= dictLimit) {
2339
- match = base + matchIndex;
2340
- if (match[ml] == ip[ml]) /* potentially better */
2341
- currentMl = ZSTD_count(ip, match, iLimit);
2342
- } else {
2343
- match = dictBase + matchIndex;
2344
- if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
2345
- currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;
2346
- }
2347
-
2348
- /* save best solution */
2349
- if (currentMl > ml) {
2350
- ml = currentMl;
2351
- *offsetPtr = current - matchIndex + ZSTD_REP_MOVE;
2352
- if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
2353
- }
2354
-
2355
- if (matchIndex <= minChain) break;
2356
- matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
2357
- }
2358
-
2359
- return ml;
2360
- }
2361
-
2362
-
2363
- FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
2364
- ZSTD_CCtx* zc,
2365
- const BYTE* ip, const BYTE* const iLimit,
2366
- size_t* offsetPtr,
2367
- const U32 maxNbAttempts, const U32 matchLengthSearch)
2368
- {
2369
- switch(matchLengthSearch)
2370
- {
2371
- default : /* includes case 3 */
2372
- case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
2373
- case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
2374
- case 7 :
2375
- case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
2376
- }
2377
- }
2378
-
2379
-
2380
- FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
2381
- ZSTD_CCtx* zc,
2382
- const BYTE* ip, const BYTE* const iLimit,
2383
- size_t* offsetPtr,
2384
- const U32 maxNbAttempts, const U32 matchLengthSearch)
2385
- {
2386
- switch(matchLengthSearch)
2387
- {
2388
- default : /* includes case 3 */
2389
- case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
2390
- case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
2391
- case 7 :
2392
- case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
2393
- }
2394
- }
2395
-
2396
-
2397
- /* *******************************
2398
- * Common parser - lazy strategy
2399
- *********************************/
2400
- FORCE_INLINE_TEMPLATE
2401
- void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
2402
- const void* src, size_t srcSize,
2403
- const U32 searchMethod, const U32 depth)
2404
- {
2405
- seqStore_t* seqStorePtr = &(ctx->seqStore);
2406
- const BYTE* const istart = (const BYTE*)src;
2407
- const BYTE* ip = istart;
2408
- const BYTE* anchor = istart;
2409
- const BYTE* const iend = istart + srcSize;
2410
- const BYTE* const ilimit = iend - 8;
2411
- const BYTE* const base = ctx->base + ctx->dictLimit;
2412
-
2413
- U32 const maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
2414
- U32 const mls = ctx->appliedParams.cParams.searchLength;
2415
-
2416
- typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
2417
- size_t* offsetPtr,
2418
- U32 maxNbAttempts, U32 matchLengthSearch);
2419
- searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
2420
- U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1], savedOffset=0;
2421
-
2422
- /* init */
2423
- ip += (ip==base);
2424
- ctx->nextToUpdate3 = ctx->nextToUpdate;
2425
- { U32 const maxRep = (U32)(ip-base);
2426
- if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
2427
- if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
2428
- }
2429
-
2430
- /* Match Loop */
2431
- while (ip < ilimit) {
2432
- size_t matchLength=0;
2433
- size_t offset=0;
2434
- const BYTE* start=ip+1;
2435
-
2436
- /* check repCode */
2437
- if ((offset_1>0) & (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))) {
2438
- /* repcode : we take it */
2439
- matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
2440
- if (depth==0) goto _storeSequence;
2441
- }
2442
-
2443
- /* first search (depth 0) */
2444
- { size_t offsetFound = 99999999;
2445
- size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
2446
- if (ml2 > matchLength)
2447
- matchLength = ml2, start = ip, offset=offsetFound;
2448
- }
2449
-
2450
- if (matchLength < 4) {
2451
- ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
2452
- continue;
2453
- }
2454
-
2455
- /* let's try to find a better solution */
2456
- if (depth>=1)
2457
- while (ip<ilimit) {
2458
- ip ++;
2459
- if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
2460
- size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
2461
- int const gain2 = (int)(mlRep * 3);
2462
- int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
2463
- if ((mlRep >= 4) && (gain2 > gain1))
2464
- matchLength = mlRep, offset = 0, start = ip;
2465
- }
2466
- { size_t offset2=99999999;
2467
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2468
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2469
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
2470
- if ((ml2 >= 4) && (gain2 > gain1)) {
2471
- matchLength = ml2, offset = offset2, start = ip;
2472
- continue; /* search a better one */
2473
- } }
2474
-
2475
- /* let's find an even better one */
2476
- if ((depth==2) && (ip<ilimit)) {
2477
- ip ++;
2478
- if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
2479
- size_t const ml2 = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
2480
- int const gain2 = (int)(ml2 * 4);
2481
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
2482
- if ((ml2 >= 4) && (gain2 > gain1))
2483
- matchLength = ml2, offset = 0, start = ip;
2484
- }
2485
- { size_t offset2=99999999;
2486
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2487
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2488
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
2489
- if ((ml2 >= 4) && (gain2 > gain1)) {
2490
- matchLength = ml2, offset = offset2, start = ip;
2491
- continue;
2492
- } } }
2493
- break; /* nothing found : store previous solution */
2494
- }
2495
-
2496
- /* NOTE:
2497
- * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior.
2498
- * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which
2499
- * overflows the pointer, which is undefined behavior.
2500
- */
2501
- /* catch up */
2502
- if (offset) {
2503
- while ( (start > anchor)
2504
- && (start > base+offset-ZSTD_REP_MOVE)
2505
- && (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1]) ) /* only search for offset within prefix */
2506
- { start--; matchLength++; }
2507
- offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
2508
- }
2509
- /* store sequence */
2510
- _storeSequence:
2511
- { size_t const litLength = start - anchor;
2512
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
2513
- anchor = ip = start + matchLength;
2514
- }
2515
-
2516
- /* check immediate repcode */
2517
- while ( (ip <= ilimit)
2518
- && ((offset_2>0)
2519
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
2520
- /* store sequence */
2521
- matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
2522
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
2523
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
2524
- ip += matchLength;
2525
- anchor = ip;
2526
- continue; /* faster when present ... (?) */
2527
- } }
2528
-
2529
- /* Save reps for next block */
2530
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
2531
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
2532
-
2533
- /* Last Literals */
2534
- { size_t const lastLLSize = iend - anchor;
2535
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
2536
- seqStorePtr->lit += lastLLSize;
2537
- }
2538
- }
2539
-
2540
-
2541
- static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2542
- {
2543
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
2544
- }
2545
-
2546
- static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2547
- {
2548
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
2549
- }
2550
-
2551
- static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2552
- {
2553
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
2554
- }
2555
-
2556
- static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2557
- {
2558
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
2559
- }
2560
-
2561
-
2562
- FORCE_INLINE_TEMPLATE
2563
- void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
2564
- const void* src, size_t srcSize,
2565
- const U32 searchMethod, const U32 depth)
2566
- {
2567
- seqStore_t* seqStorePtr = &(ctx->seqStore);
2568
- const BYTE* const istart = (const BYTE*)src;
2569
- const BYTE* ip = istart;
2570
- const BYTE* anchor = istart;
2571
- const BYTE* const iend = istart + srcSize;
2572
- const BYTE* const ilimit = iend - 8;
2573
- const BYTE* const base = ctx->base;
2574
- const U32 dictLimit = ctx->dictLimit;
2575
- const U32 lowestIndex = ctx->lowLimit;
2576
- const BYTE* const prefixStart = base + dictLimit;
2577
- const BYTE* const dictBase = ctx->dictBase;
2578
- const BYTE* const dictEnd = dictBase + dictLimit;
2579
- const BYTE* const dictStart = dictBase + ctx->lowLimit;
2580
-
2581
- const U32 maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
2582
- const U32 mls = ctx->appliedParams.cParams.searchLength;
2583
-
2584
- typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
2585
- size_t* offsetPtr,
2586
- U32 maxNbAttempts, U32 matchLengthSearch);
2587
- searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
2588
-
2589
- U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1];
2590
-
2591
- /* init */
2592
- ctx->nextToUpdate3 = ctx->nextToUpdate;
2593
- ip += (ip == prefixStart);
2594
-
2595
- /* Match Loop */
2596
- while (ip < ilimit) {
2597
- size_t matchLength=0;
2598
- size_t offset=0;
2599
- const BYTE* start=ip+1;
2600
- U32 current = (U32)(ip-base);
2601
-
2602
- /* check repCode */
2603
- { const U32 repIndex = (U32)(current+1 - offset_1);
2604
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2605
- const BYTE* const repMatch = repBase + repIndex;
2606
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2607
- if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
2608
- /* repcode detected we should take it */
2609
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2610
- matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;
2611
- if (depth==0) goto _storeSequence;
2612
- } }
2613
-
2614
- /* first search (depth 0) */
2615
- { size_t offsetFound = 99999999;
2616
- size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
2617
- if (ml2 > matchLength)
2618
- matchLength = ml2, start = ip, offset=offsetFound;
1322
+ case set_compressed: {
1323
+ S16 norm[MaxSeq + 1];
1324
+ size_t nbSeq_1 = nbSeq;
1325
+ const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
1326
+ if (count[codeTable[nbSeq-1]] > 1) {
1327
+ count[codeTable[nbSeq-1]]--;
1328
+ nbSeq_1--;
2619
1329
  }
2620
-
2621
- if (matchLength < 4) {
2622
- ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
2623
- continue;
1330
+ assert(nbSeq_1 > 1);
1331
+ CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
1332
+ { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
1333
+ if (FSE_isError(NCountSize)) return NCountSize;
1334
+ CHECK_F(FSE_buildCTable_wksp(CTable, norm, max, tableLog, workspace, workspaceSize));
1335
+ return NCountSize;
2624
1336
  }
1337
+ }
1338
+ default: return assert(0), ERROR(GENERIC);
1339
+ }
1340
+ }
2625
1341
 
2626
- /* let's try to find a better solution */
2627
- if (depth>=1)
2628
- while (ip<ilimit) {
2629
- ip ++;
2630
- current++;
2631
- /* check repCode */
2632
- if (offset) {
2633
- const U32 repIndex = (U32)(current - offset_1);
2634
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2635
- const BYTE* const repMatch = repBase + repIndex;
2636
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2637
- if (MEM_read32(ip) == MEM_read32(repMatch)) {
2638
- /* repcode detected */
2639
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2640
- size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
2641
- int const gain2 = (int)(repLength * 3);
2642
- int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
2643
- if ((repLength >= 4) && (gain2 > gain1))
2644
- matchLength = repLength, offset = 0, start = ip;
2645
- } }
2646
-
2647
- /* search match, depth 1 */
2648
- { size_t offset2=99999999;
2649
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2650
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2651
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
2652
- if ((ml2 >= 4) && (gain2 > gain1)) {
2653
- matchLength = ml2, offset = offset2, start = ip;
2654
- continue; /* search a better one */
2655
- } }
2656
-
2657
- /* let's find an even better one */
2658
- if ((depth==2) && (ip<ilimit)) {
2659
- ip ++;
2660
- current++;
2661
- /* check repCode */
2662
- if (offset) {
2663
- const U32 repIndex = (U32)(current - offset_1);
2664
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2665
- const BYTE* const repMatch = repBase + repIndex;
2666
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2667
- if (MEM_read32(ip) == MEM_read32(repMatch)) {
2668
- /* repcode detected */
2669
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2670
- size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
2671
- int const gain2 = (int)(repLength * 4);
2672
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
2673
- if ((repLength >= 4) && (gain2 > gain1))
2674
- matchLength = repLength, offset = 0, start = ip;
2675
- } }
2676
-
2677
- /* search match, depth 2 */
2678
- { size_t offset2=99999999;
2679
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2680
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2681
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
2682
- if ((ml2 >= 4) && (gain2 > gain1)) {
2683
- matchLength = ml2, offset = offset2, start = ip;
2684
- continue;
2685
- } } }
2686
- break; /* nothing found : store previous solution */
2687
- }
1342
+ MEM_STATIC size_t ZSTD_encodeSequences(void* dst, size_t dstCapacity,
1343
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
1344
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
1345
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
1346
+ seqDef const* sequences, size_t nbSeq, int longOffsets)
1347
+ {
1348
+ BIT_CStream_t blockStream;
1349
+ FSE_CState_t stateMatchLength;
1350
+ FSE_CState_t stateOffsetBits;
1351
+ FSE_CState_t stateLitLength;
2688
1352
 
2689
- /* catch up */
2690
- if (offset) {
2691
- U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
2692
- const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
2693
- const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
2694
- while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
2695
- offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
2696
- }
1353
+ CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
2697
1354
 
2698
- /* store sequence */
2699
- _storeSequence:
2700
- { size_t const litLength = start - anchor;
2701
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
2702
- anchor = ip = start + matchLength;
1355
+ /* first symbols */
1356
+ FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
1357
+ FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
1358
+ FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
1359
+ BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
1360
+ if (MEM_32bits()) BIT_flushBits(&blockStream);
1361
+ BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
1362
+ if (MEM_32bits()) BIT_flushBits(&blockStream);
1363
+ if (longOffsets) {
1364
+ U32 const ofBits = ofCodeTable[nbSeq-1];
1365
+ int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
1366
+ if (extraBits) {
1367
+ BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
1368
+ BIT_flushBits(&blockStream);
2703
1369
  }
1370
+ BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
1371
+ ofBits - extraBits);
1372
+ } else {
1373
+ BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
1374
+ }
1375
+ BIT_flushBits(&blockStream);
2704
1376
 
2705
- /* check immediate repcode */
2706
- while (ip <= ilimit) {
2707
- const U32 repIndex = (U32)((ip-base) - offset_2);
2708
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2709
- const BYTE* const repMatch = repBase + repIndex;
2710
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2711
- if (MEM_read32(ip) == MEM_read32(repMatch)) {
2712
- /* repcode detected we should take it */
2713
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2714
- matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
2715
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
2716
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
2717
- ip += matchLength;
2718
- anchor = ip;
2719
- continue; /* faster when present ... (?) */
1377
+ { size_t n;
1378
+ for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
1379
+ BYTE const llCode = llCodeTable[n];
1380
+ BYTE const ofCode = ofCodeTable[n];
1381
+ BYTE const mlCode = mlCodeTable[n];
1382
+ U32 const llBits = LL_bits[llCode];
1383
+ U32 const ofBits = ofCode; /* 32b*/ /* 64b*/
1384
+ U32 const mlBits = ML_bits[mlCode];
1385
+ /* (7)*/ /* (7)*/
1386
+ FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
1387
+ FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
1388
+ if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
1389
+ FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
1390
+ if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
1391
+ BIT_flushBits(&blockStream); /* (7)*/
1392
+ BIT_addBits(&blockStream, sequences[n].litLength, llBits);
1393
+ if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
1394
+ BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
1395
+ if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
1396
+ if (longOffsets) {
1397
+ int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
1398
+ if (extraBits) {
1399
+ BIT_addBits(&blockStream, sequences[n].offset, extraBits);
1400
+ BIT_flushBits(&blockStream); /* (7)*/
1401
+ }
1402
+ BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
1403
+ ofBits - extraBits); /* 31 */
1404
+ } else {
1405
+ BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
2720
1406
  }
2721
- break;
1407
+ BIT_flushBits(&blockStream); /* (7)*/
2722
1408
  } }
2723
1409
 
2724
- /* Save reps for next block */
2725
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
1410
+ FSE_flushCState(&blockStream, &stateMatchLength);
1411
+ FSE_flushCState(&blockStream, &stateOffsetBits);
1412
+ FSE_flushCState(&blockStream, &stateLitLength);
2726
1413
 
2727
- /* Last Literals */
2728
- { size_t const lastLLSize = iend - anchor;
2729
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
2730
- seqStorePtr->lit += lastLLSize;
1414
+ { size_t const streamSize = BIT_closeCStream(&blockStream);
1415
+ if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
1416
+ return streamSize;
2731
1417
  }
2732
1418
  }
2733
1419
 
2734
-
2735
- void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1420
+ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
1421
+ ZSTD_entropyCTables_t* entropy,
1422
+ ZSTD_compressionParameters const* cParams,
1423
+ void* dst, size_t dstCapacity)
2736
1424
  {
2737
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
2738
- }
1425
+ const int longOffsets = cParams->windowLog > STREAM_ACCUMULATOR_MIN;
1426
+ U32 count[MaxSeq+1];
1427
+ FSE_CTable* CTable_LitLength = entropy->litlengthCTable;
1428
+ FSE_CTable* CTable_OffsetBits = entropy->offcodeCTable;
1429
+ FSE_CTable* CTable_MatchLength = entropy->matchlengthCTable;
1430
+ U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
1431
+ const seqDef* const sequences = seqStorePtr->sequencesStart;
1432
+ const BYTE* const ofCodeTable = seqStorePtr->ofCode;
1433
+ const BYTE* const llCodeTable = seqStorePtr->llCode;
1434
+ const BYTE* const mlCodeTable = seqStorePtr->mlCode;
1435
+ BYTE* const ostart = (BYTE*)dst;
1436
+ BYTE* const oend = ostart + dstCapacity;
1437
+ BYTE* op = ostart;
1438
+ size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
1439
+ BYTE* seqHead;
2739
1440
 
2740
- static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2741
- {
2742
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
2743
- }
1441
+ ZSTD_STATIC_ASSERT(sizeof(entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
2744
1442
 
2745
- static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2746
- {
2747
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
2748
- }
1443
+ /* Compress literals */
1444
+ { const BYTE* const literals = seqStorePtr->litStart;
1445
+ size_t const litSize = seqStorePtr->lit - literals;
1446
+ size_t const cSize = ZSTD_compressLiterals(
1447
+ entropy, cParams->strategy, op, dstCapacity, literals, litSize);
1448
+ if (ZSTD_isError(cSize))
1449
+ return cSize;
1450
+ op += cSize;
1451
+ }
2749
1452
 
2750
- static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2751
- {
2752
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
2753
- }
1453
+ /* Sequences Header */
1454
+ if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
1455
+ if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
1456
+ else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
1457
+ else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
1458
+ if (nbSeq==0) return op - ostart;
2754
1459
 
1460
+ /* seqHead : flags for FSE encoding type */
1461
+ seqHead = op++;
2755
1462
 
2756
- /* The optimal parser */
2757
- #include "zstd_opt.h"
1463
+ /* convert length/distances into codes */
1464
+ ZSTD_seqToCodes(seqStorePtr);
1465
+ /* CTable for Literal Lengths */
1466
+ { U32 max = MaxLL;
1467
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
1468
+ LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
1469
+ { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
1470
+ count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
1471
+ entropy->workspace, sizeof(entropy->workspace));
1472
+ if (ZSTD_isError(countSize)) return countSize;
1473
+ op += countSize;
1474
+ } }
1475
+ /* CTable for Offsets */
1476
+ { U32 max = MaxOff;
1477
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
1478
+ /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
1479
+ ZSTD_defaultPolicy_e const defaultPolicy = max <= DefaultMaxOff ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
1480
+ Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
1481
+ { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
1482
+ count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
1483
+ entropy->workspace, sizeof(entropy->workspace));
1484
+ if (ZSTD_isError(countSize)) return countSize;
1485
+ op += countSize;
1486
+ } }
1487
+ /* CTable for MatchLengths */
1488
+ { U32 max = MaxML;
1489
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
1490
+ MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
1491
+ { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
1492
+ count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
1493
+ entropy->workspace, sizeof(entropy->workspace));
1494
+ if (ZSTD_isError(countSize)) return countSize;
1495
+ op += countSize;
1496
+ } }
2758
1497
 
2759
- static void ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2760
- {
2761
- #ifdef ZSTD_OPT_H_91842398743
2762
- ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0);
2763
- #else
2764
- (void)ctx; (void)src; (void)srcSize;
2765
- return;
2766
- #endif
2767
- }
1498
+ *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
2768
1499
 
2769
- static void ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2770
- {
2771
- #ifdef ZSTD_OPT_H_91842398743
2772
- ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1);
2773
- #else
2774
- (void)ctx; (void)src; (void)srcSize;
2775
- return;
2776
- #endif
2777
- }
1500
+ { size_t const streamSize = ZSTD_encodeSequences(op, oend - op,
1501
+ CTable_MatchLength, mlCodeTable,
1502
+ CTable_OffsetBits, ofCodeTable,
1503
+ CTable_LitLength, llCodeTable,
1504
+ sequences, nbSeq, longOffsets);
1505
+ if (ZSTD_isError(streamSize)) return streamSize;
1506
+ op += streamSize;
1507
+ }
2778
1508
 
2779
- static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2780
- {
2781
- #ifdef ZSTD_OPT_H_91842398743
2782
- ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0);
2783
- #else
2784
- (void)ctx; (void)src; (void)srcSize;
2785
- return;
2786
- #endif
1509
+ return op - ostart;
2787
1510
  }
2788
1511
 
2789
- static void ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1512
+ MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
1513
+ ZSTD_entropyCTables_t* entropy,
1514
+ ZSTD_compressionParameters const* cParams,
1515
+ void* dst, size_t dstCapacity,
1516
+ size_t srcSize)
2790
1517
  {
2791
- #ifdef ZSTD_OPT_H_91842398743
2792
- ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1);
2793
- #else
2794
- (void)ctx; (void)src; (void)srcSize;
2795
- return;
2796
- #endif
2797
- }
1518
+ size_t const cSize = ZSTD_compressSequences_internal(seqStorePtr, entropy, cParams,
1519
+ dst, dstCapacity);
1520
+ size_t const minGain = ZSTD_minGain(srcSize);
1521
+ size_t const maxCSize = srcSize - minGain;
1522
+ /* If the srcSize <= dstCapacity, then there is enough space to write a
1523
+ * raw uncompressed block. Since we ran out of space, the block must not
1524
+ * be compressible, so fall back to a raw uncompressed block.
1525
+ */
1526
+ int const uncompressibleError = cSize == ERROR(dstSize_tooSmall) && srcSize <= dstCapacity;
1527
+
1528
+ if (ZSTD_isError(cSize) && !uncompressibleError)
1529
+ return cSize;
1530
+ /* Check compressibility */
1531
+ if (cSize >= maxCSize || uncompressibleError) {
1532
+ entropy->hufCTable_repeatMode = HUF_repeat_none;
1533
+ entropy->offcode_repeatMode = FSE_repeat_none;
1534
+ entropy->matchlength_repeatMode = FSE_repeat_none;
1535
+ entropy->litlength_repeatMode = FSE_repeat_none;
1536
+ return 0;
1537
+ }
1538
+ assert(!ZSTD_isError(cSize));
2798
1539
 
1540
+ /* confirm repcodes */
1541
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->rep[i] = seqStorePtr->repToConfirm[i]; }
1542
+ return cSize;
1543
+ }
2799
1544
 
2800
1545
  /* ZSTD_selectBlockCompressor() :
1546
+ * Not static, but internal use only (used by long distance matcher)
2801
1547
  * assumption : strat is a valid strategy */
2802
- typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
2803
- static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
1548
+ typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
1549
+ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
2804
1550
  {
2805
1551
  static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
2806
1552
  { ZSTD_compressBlock_fast /* default for 0 */,
@@ -2819,18 +1565,37 @@ static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int
2819
1565
  return blockCompressor[extDict!=0][(U32)strat];
2820
1566
  }
2821
1567
 
1568
+ static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
1569
+ const BYTE* anchor, size_t lastLLSize)
1570
+ {
1571
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
1572
+ seqStorePtr->lit += lastLLSize;
1573
+ }
2822
1574
 
2823
1575
  static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2824
1576
  {
2825
- ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, zc->lowLimit < zc->dictLimit);
2826
1577
  const BYTE* const base = zc->base;
2827
1578
  const BYTE* const istart = (const BYTE*)src;
2828
1579
  const U32 current = (U32)(istart-base);
1580
+ size_t lastLLSize;
1581
+ const BYTE* anchor;
1582
+ U32 const extDict = zc->lowLimit < zc->dictLimit;
1583
+ const ZSTD_blockCompressor blockCompressor =
1584
+ zc->appliedParams.ldmParams.enableLdm
1585
+ ? (extDict ? ZSTD_compressBlock_ldm_extDict : ZSTD_compressBlock_ldm)
1586
+ : ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
1587
+
2829
1588
  if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0; /* don't even attempt compression below a certain srcSize */
2830
1589
  ZSTD_resetSeqStore(&(zc->seqStore));
2831
1590
  if (current > zc->nextToUpdate + 384)
2832
1591
  zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384)); /* limited update after finding a very long match */
2833
- blockCompressor(zc, src, srcSize);
1592
+
1593
+ lastLLSize = blockCompressor(zc, src, srcSize);
1594
+
1595
+ /* Last literals */
1596
+ anchor = (const BYTE*)src + srcSize - lastLLSize;
1597
+ ZSTD_storeLastLiterals(&zc->seqStore, anchor, lastLLSize);
1598
+
2834
1599
  return ZSTD_compressSequences(&zc->seqStore, zc->entropy, &zc->appliedParams.cParams, dst, dstCapacity, srcSize);
2835
1600
  }
2836
1601
 
@@ -2852,7 +1617,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2852
1617
  const BYTE* ip = (const BYTE*)src;
2853
1618
  BYTE* const ostart = (BYTE*)dst;
2854
1619
  BYTE* op = ostart;
2855
- U32 const maxDist = 1 << cctx->appliedParams.cParams.windowLog;
1620
+ U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
2856
1621
 
2857
1622
  if (cctx->appliedParams.fParams.checksumFlag && srcSize)
2858
1623
  XXH64_update(&cctx->xxhState, src, srcSize);
@@ -2865,13 +1630,33 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2865
1630
  return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
2866
1631
  if (remaining < blockSize) blockSize = remaining;
2867
1632
 
2868
- /* preemptive overflow correction */
1633
+ /* preemptive overflow correction:
1634
+ * 1. correction is large enough:
1635
+ * lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog - blockSize
1636
+ * 1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
1637
+ *
1638
+ * current - newCurrent
1639
+ * > (3<<29 + 1<<windowLog - blockSize) - (1<<windowLog + 1<<chainLog)
1640
+ * > (3<<29 - blockSize) - (1<<chainLog)
1641
+ * > (3<<29 - blockSize) - (1<<30) (NOTE: chainLog <= 30)
1642
+ * > 1<<29 - 1<<17
1643
+ *
1644
+ * 2. (ip+blockSize - cctx->base) doesn't overflow:
1645
+ * In 32 bit mode we limit windowLog to 30 so we don't get
1646
+ * differences larger than 1<<31-1.
1647
+ * 3. cctx->lowLimit < 1<<32:
1648
+ * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
1649
+ */
2869
1650
  if (cctx->lowLimit > (3U<<29)) {
2870
- U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->appliedParams.cParams.hashLog, cctx->appliedParams.cParams.strategy)) - 1;
1651
+ U32 const cycleMask = ((U32)1 << ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy)) - 1;
2871
1652
  U32 const current = (U32)(ip - cctx->base);
2872
- U32 const newCurrent = (current & cycleMask) + (1 << cctx->appliedParams.cParams.windowLog);
1653
+ U32 const newCurrent = (current & cycleMask) + ((U32)1 << cctx->appliedParams.cParams.windowLog);
2873
1654
  U32 const correction = current - newCurrent;
2874
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_64 <= 30);
1655
+ ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
1656
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
1657
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
1658
+ assert(current > newCurrent);
1659
+ assert(correction > 1<<28); /* Loose bound, should be about 1<<29 */
2875
1660
  ZSTD_reduceIndex(cctx, correction);
2876
1661
  cctx->base += correction;
2877
1662
  cctx->dictBase += correction;
@@ -2879,6 +1664,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2879
1664
  cctx->dictLimit -= correction;
2880
1665
  if (cctx->nextToUpdate < correction) cctx->nextToUpdate = 0;
2881
1666
  else cctx->nextToUpdate -= correction;
1667
+ DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x\n", correction, cctx->lowLimit);
2882
1668
  }
2883
1669
 
2884
1670
  if ((U32)(ip+blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) {
@@ -2915,25 +1701,29 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2915
1701
 
2916
1702
 
2917
1703
  static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2918
- ZSTD_parameters params, U64 pledgedSrcSize, U32 dictID)
1704
+ ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
2919
1705
  { BYTE* const op = (BYTE*)dst;
2920
1706
  U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
2921
1707
  U32 const dictIDSizeCode = params.fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
2922
1708
  U32 const checksumFlag = params.fParams.checksumFlag>0;
2923
- U32 const windowSize = 1U << params.cParams.windowLog;
1709
+ U32 const windowSize = (U32)1 << params.cParams.windowLog;
2924
1710
  U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
2925
1711
  BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2926
1712
  U32 const fcsCode = params.fParams.contentSizeFlag ?
2927
1713
  (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
2928
1714
  BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2929
- size_t pos;
1715
+ size_t pos=0;
2930
1716
 
2931
1717
  if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
2932
- DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
1718
+ DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2933
1719
  !params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
2934
1720
 
2935
- MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2936
- op[4] = frameHeaderDecriptionByte; pos=5;
1721
+ if (params.format == ZSTD_f_zstd1) {
1722
+ DEBUGLOG(4, "writing zstd magic number");
1723
+ MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
1724
+ pos = 4;
1725
+ }
1726
+ op[pos++] = frameHeaderDecriptionByte;
2937
1727
  if (!singleSegment) op[pos++] = windowLogByte;
2938
1728
  switch(dictIDSizeCode)
2939
1729
  {
@@ -2969,7 +1759,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2969
1759
 
2970
1760
  if (frame && (cctx->stage==ZSTDcs_init)) {
2971
1761
  fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
2972
- cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
1762
+ cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
2973
1763
  if (ZSTD_isError(fhSize)) return fhSize;
2974
1764
  dstCapacity -= fhSize;
2975
1765
  dst = (char*)dst + fhSize;
@@ -3018,11 +1808,9 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
3018
1808
 
3019
1809
  size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
3020
1810
  {
3021
- U32 const cLevel = cctx->compressionLevel;
3022
- ZSTD_compressionParameters cParams = (cLevel == ZSTD_CLEVEL_CUSTOM) ?
3023
- cctx->appliedParams.cParams :
3024
- ZSTD_getCParams(cLevel, 0, 0);
3025
- return MIN (ZSTD_BLOCKSIZE_MAX, 1 << cParams.windowLog);
1811
+ ZSTD_compressionParameters const cParams =
1812
+ ZSTD_getCParamsFromCCtxParams(cctx->appliedParams, 0, 0);
1813
+ return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
3026
1814
  }
3027
1815
 
3028
1816
  size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
@@ -3046,7 +1834,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
3046
1834
  zc->dictBase = zc->base;
3047
1835
  zc->base += ip - zc->nextSrc;
3048
1836
  zc->nextToUpdate = zc->dictLimit;
3049
- zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base);
1837
+ zc->loadedDictEnd = zc->appliedParams.forceWindow ? 0 : (U32)(iend - zc->base);
3050
1838
 
3051
1839
  zc->nextSrc = iend;
3052
1840
  if (srcSize <= HASH_READ_SIZE) return 0;
@@ -3056,7 +1844,6 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
3056
1844
  case ZSTD_fast:
3057
1845
  ZSTD_fillHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
3058
1846
  break;
3059
-
3060
1847
  case ZSTD_dfast:
3061
1848
  ZSTD_fillDoubleHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
3062
1849
  break;
@@ -3072,7 +1859,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
3072
1859
  case ZSTD_btopt:
3073
1860
  case ZSTD_btultra:
3074
1861
  if (srcSize >= HASH_READ_SIZE)
3075
- ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
1862
+ ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, (U32)1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
3076
1863
  break;
3077
1864
 
3078
1865
  default:
@@ -3120,8 +1907,10 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
3120
1907
  cctx->dictID = cctx->appliedParams.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
3121
1908
  dictPtr += 4;
3122
1909
 
3123
- { size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)cctx->entropy->hufCTable, 255, dictPtr, dictEnd-dictPtr);
1910
+ { unsigned maxSymbolValue = 255;
1911
+ size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)cctx->entropy->hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
3124
1912
  if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
1913
+ if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
3125
1914
  dictPtr += hufHeaderSize;
3126
1915
  }
3127
1916
 
@@ -3221,12 +2010,10 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
3221
2010
  const void* dict, size_t dictSize,
3222
2011
  ZSTD_dictMode_e dictMode,
3223
2012
  const ZSTD_CDict* cdict,
3224
- ZSTD_parameters params, U64 pledgedSrcSize,
2013
+ ZSTD_CCtx_params params, U64 pledgedSrcSize,
3225
2014
  ZSTD_buffered_policy_e zbuff)
3226
2015
  {
3227
2016
  DEBUGLOG(4, "ZSTD_compressBegin_internal");
3228
- DEBUGLOG(4, "dict ? %s", dict ? "dict" : (cdict ? "cdict" : "none"));
3229
- DEBUGLOG(4, "dictMode : %u", (U32)dictMode);
3230
2017
  /* params are supposed to be fully validated at this point */
3231
2018
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3232
2019
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
@@ -3242,6 +2029,19 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
3242
2029
  return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
3243
2030
  }
3244
2031
 
2032
+ size_t ZSTD_compressBegin_advanced_internal(
2033
+ ZSTD_CCtx* cctx,
2034
+ const void* dict, size_t dictSize,
2035
+ ZSTD_dictMode_e dictMode,
2036
+ ZSTD_CCtx_params params,
2037
+ unsigned long long pledgedSrcSize)
2038
+ {
2039
+ /* compression parameters verification and optimization */
2040
+ CHECK_F( ZSTD_checkCParams(params.cParams) );
2041
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, dictMode, NULL,
2042
+ params, pledgedSrcSize,
2043
+ ZSTDb_not_buffered);
2044
+ }
3245
2045
 
3246
2046
  /*! ZSTD_compressBegin_advanced() :
3247
2047
  * @return : 0, or an error code */
@@ -3249,21 +2049,22 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
3249
2049
  const void* dict, size_t dictSize,
3250
2050
  ZSTD_parameters params, unsigned long long pledgedSrcSize)
3251
2051
  {
3252
- /* compression parameters verification and optimization */
3253
- CHECK_F(ZSTD_checkCParams(params.cParams));
3254
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
3255
- params, pledgedSrcSize, ZSTDb_not_buffered);
2052
+ ZSTD_CCtx_params const cctxParams =
2053
+ ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2054
+ return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dm_auto,
2055
+ cctxParams,
2056
+ pledgedSrcSize);
3256
2057
  }
3257
2058
 
3258
-
3259
2059
  size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
3260
2060
  {
3261
2061
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
2062
+ ZSTD_CCtx_params const cctxParams =
2063
+ ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
3262
2064
  return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
3263
- params, 0, ZSTDb_not_buffered);
2065
+ cctxParams, 0, ZSTDb_not_buffered);
3264
2066
  }
3265
2067
 
3266
-
3267
2068
  size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
3268
2069
  {
3269
2070
  return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
@@ -3324,9 +2125,9 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
3324
2125
  endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
3325
2126
  if (ZSTD_isError(endResult)) return endResult;
3326
2127
  if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
3327
- DEBUGLOG(5, "end of frame : controlling src size");
2128
+ DEBUGLOG(4, "end of frame : controlling src size");
3328
2129
  if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
3329
- DEBUGLOG(5, "error : pledgedSrcSize = %u, while realSrcSize = %u",
2130
+ DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
3330
2131
  (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
3331
2132
  return ERROR(srcSize_wrong);
3332
2133
  } }
@@ -3340,9 +2141,13 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
3340
2141
  const void* dict,size_t dictSize,
3341
2142
  ZSTD_parameters params)
3342
2143
  {
3343
- CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
3344
- params, srcSize, ZSTDb_not_buffered) );
3345
- return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
2144
+ ZSTD_CCtx_params const cctxParams =
2145
+ ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
2146
+ return ZSTD_compress_advanced_internal(cctx,
2147
+ dst, dstCapacity,
2148
+ src, srcSize,
2149
+ dict, dictSize,
2150
+ cctxParams);
3346
2151
  }
3347
2152
 
3348
2153
  size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
@@ -3355,6 +2160,19 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
3355
2160
  return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
3356
2161
  }
3357
2162
 
2163
+ /* Internal */
2164
+ size_t ZSTD_compress_advanced_internal(
2165
+ ZSTD_CCtx* cctx,
2166
+ void* dst, size_t dstCapacity,
2167
+ const void* src, size_t srcSize,
2168
+ const void* dict,size_t dictSize,
2169
+ ZSTD_CCtx_params params)
2170
+ {
2171
+ CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
2172
+ params, srcSize, ZSTDb_not_buffered) );
2173
+ return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
2174
+ }
2175
+
3358
2176
  size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
3359
2177
  const void* dict, size_t dictSize, int compressionLevel)
3360
2178
  {
@@ -3384,18 +2202,21 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
3384
2202
 
3385
2203
  /*! ZSTD_estimateCDictSize_advanced() :
3386
2204
  * Estimate amount of memory that will be needed to create a dictionary with following arguments */
3387
- size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, unsigned byReference)
2205
+ size_t ZSTD_estimateCDictSize_advanced(
2206
+ size_t dictSize, ZSTD_compressionParameters cParams,
2207
+ ZSTD_dictLoadMethod_e dictLoadMethod)
3388
2208
  {
3389
2209
  DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
3390
- DEBUGLOG(5, "CCtx estimate : %u", (U32)ZSTD_estimateCCtxSize_advanced(cParams));
3391
- return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_advanced(cParams)
3392
- + (byReference ? 0 : dictSize);
2210
+ DEBUGLOG(5, "CCtx estimate : %u",
2211
+ (U32)ZSTD_estimateCCtxSize_usingCParams(cParams));
2212
+ return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_usingCParams(cParams)
2213
+ + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
3393
2214
  }
3394
2215
 
3395
2216
  size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
3396
2217
  {
3397
2218
  ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3398
- return ZSTD_estimateCDictSize_advanced(dictSize, cParams, 0);
2219
+ return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
3399
2220
  }
3400
2221
 
3401
2222
  size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
@@ -3406,22 +2227,15 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
3406
2227
  return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
3407
2228
  }
3408
2229
 
3409
- static ZSTD_parameters ZSTD_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)
3410
- {
3411
- ZSTD_parameters params;
3412
- params.cParams = cParams;
3413
- params.fParams = fParams;
3414
- return params;
3415
- }
3416
-
3417
2230
  static size_t ZSTD_initCDict_internal(
3418
2231
  ZSTD_CDict* cdict,
3419
2232
  const void* dictBuffer, size_t dictSize,
3420
- unsigned byReference, ZSTD_dictMode_e dictMode,
2233
+ ZSTD_dictLoadMethod_e dictLoadMethod,
2234
+ ZSTD_dictMode_e dictMode,
3421
2235
  ZSTD_compressionParameters cParams)
3422
2236
  {
3423
2237
  DEBUGLOG(5, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
3424
- if ((byReference) || (!dictBuffer) || (!dictSize)) {
2238
+ if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
3425
2239
  cdict->dictBuffer = NULL;
3426
2240
  cdict->dictContent = dictBuffer;
3427
2241
  } else {
@@ -3433,13 +2247,12 @@ static size_t ZSTD_initCDict_internal(
3433
2247
  }
3434
2248
  cdict->dictContentSize = dictSize;
3435
2249
 
3436
- { ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */,
3437
- 0 /* checksumFlag */, 0 /* noDictIDFlag */ }; /* dummy */
3438
- ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
2250
+ { ZSTD_CCtx_params cctxParams = cdict->refContext->requestedParams;
2251
+ cctxParams.cParams = cParams;
3439
2252
  CHECK_F( ZSTD_compressBegin_internal(cdict->refContext,
3440
2253
  cdict->dictContent, dictSize, dictMode,
3441
2254
  NULL,
3442
- params, ZSTD_CONTENTSIZE_UNKNOWN,
2255
+ cctxParams, ZSTD_CONTENTSIZE_UNKNOWN,
3443
2256
  ZSTDb_not_buffered) );
3444
2257
  }
3445
2258
 
@@ -3447,7 +2260,8 @@ static size_t ZSTD_initCDict_internal(
3447
2260
  }
3448
2261
 
3449
2262
  ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3450
- unsigned byReference, ZSTD_dictMode_e dictMode,
2263
+ ZSTD_dictLoadMethod_e dictLoadMethod,
2264
+ ZSTD_dictMode_e dictMode,
3451
2265
  ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
3452
2266
  {
3453
2267
  DEBUGLOG(5, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
@@ -3462,10 +2276,9 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3462
2276
  return NULL;
3463
2277
  }
3464
2278
  cdict->refContext = cctx;
3465
-
3466
2279
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3467
2280
  dictBuffer, dictSize,
3468
- byReference, dictMode,
2281
+ dictLoadMethod, dictMode,
3469
2282
  cParams) )) {
3470
2283
  ZSTD_freeCDict(cdict);
3471
2284
  return NULL;
@@ -3479,7 +2292,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
3479
2292
  {
3480
2293
  ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3481
2294
  return ZSTD_createCDict_advanced(dict, dictSize,
3482
- 0 /* byReference */, ZSTD_dm_auto,
2295
+ ZSTD_dlm_byCopy, ZSTD_dm_auto,
3483
2296
  cParams, ZSTD_defaultCMem);
3484
2297
  }
3485
2298
 
@@ -3487,7 +2300,7 @@ ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int
3487
2300
  {
3488
2301
  ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3489
2302
  return ZSTD_createCDict_advanced(dict, dictSize,
3490
- 1 /* byReference */, ZSTD_dm_auto,
2303
+ ZSTD_dlm_byRef, ZSTD_dm_auto,
3491
2304
  cParams, ZSTD_defaultCMem);
3492
2305
  }
3493
2306
 
@@ -3517,11 +2330,12 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
3517
2330
  */
3518
2331
  ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
3519
2332
  const void* dict, size_t dictSize,
3520
- unsigned byReference, ZSTD_dictMode_e dictMode,
2333
+ ZSTD_dictLoadMethod_e dictLoadMethod,
2334
+ ZSTD_dictMode_e dictMode,
3521
2335
  ZSTD_compressionParameters cParams)
3522
2336
  {
3523
- size_t const cctxSize = ZSTD_estimateCCtxSize_advanced(cParams);
3524
- size_t const neededSize = sizeof(ZSTD_CDict) + (byReference ? 0 : dictSize)
2337
+ size_t const cctxSize = ZSTD_estimateCCtxSize_usingCParams(cParams);
2338
+ size_t const neededSize = sizeof(ZSTD_CDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize)
3525
2339
  + cctxSize;
3526
2340
  ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
3527
2341
  void* ptr;
@@ -3531,7 +2345,7 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
3531
2345
  (U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
3532
2346
  if (workspaceSize < neededSize) return NULL;
3533
2347
 
3534
- if (!byReference) {
2348
+ if (dictLoadMethod == ZSTD_dlm_byCopy) {
3535
2349
  memcpy(cdict+1, dict, dictSize);
3536
2350
  dict = cdict+1;
3537
2351
  ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
@@ -3542,15 +2356,15 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
3542
2356
 
3543
2357
  if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3544
2358
  dict, dictSize,
3545
- 1 /* byReference */, dictMode,
2359
+ ZSTD_dlm_byRef, dictMode,
3546
2360
  cParams) ))
3547
2361
  return NULL;
3548
2362
 
3549
2363
  return cdict;
3550
2364
  }
3551
2365
 
3552
- ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
3553
- return ZSTD_getParamsFromCCtx(cdict->refContext);
2366
+ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) {
2367
+ return cdict->refContext->appliedParams.cParams;
3554
2368
  }
3555
2369
 
3556
2370
  /* ZSTD_compressBegin_usingCDict_advanced() :
@@ -3560,7 +2374,8 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
3560
2374
  ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
3561
2375
  {
3562
2376
  if (cdict==NULL) return ERROR(dictionary_wrong);
3563
- { ZSTD_parameters params = cdict->refContext->appliedParams;
2377
+ { ZSTD_CCtx_params params = cctx->requestedParams;
2378
+ params.cParams = ZSTD_getCParamsFromCDict(cdict);
3564
2379
  params.fParams = fParams;
3565
2380
  DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced");
3566
2381
  return ZSTD_compressBegin_internal(cctx,
@@ -3644,7 +2459,7 @@ size_t ZSTD_CStreamOutSize(void)
3644
2459
  static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
3645
2460
  const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
3646
2461
  const ZSTD_CDict* cdict,
3647
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
2462
+ const ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
3648
2463
  {
3649
2464
  DEBUGLOG(4, "ZSTD_resetCStream_internal");
3650
2465
  /* params are supposed to be fully validated at this point */
@@ -3668,13 +2483,11 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
3668
2483
 
3669
2484
  size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
3670
2485
  {
3671
- ZSTD_parameters params = zcs->requestedParams;
2486
+ ZSTD_CCtx_params params = zcs->requestedParams;
3672
2487
  params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
3673
- DEBUGLOG(5, "ZSTD_resetCStream");
3674
- if (zcs->compressionLevel != ZSTD_CLEVEL_CUSTOM) {
3675
- params.cParams = ZSTD_getCParams(zcs->compressionLevel, pledgedSrcSize, 0 /* dictSize */);
3676
- }
3677
- return ZSTD_resetCStream_internal(zcs, NULL, 0, zcs->dictMode, zcs->cdict, params, pledgedSrcSize);
2488
+ params.cParams = ZSTD_getCParamsFromCCtxParams(params, pledgedSrcSize, 0);
2489
+ DEBUGLOG(4, "ZSTD_resetCStream");
2490
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
3678
2491
  }
3679
2492
 
3680
2493
  /*! ZSTD_initCStream_internal() :
@@ -3683,9 +2496,9 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
3683
2496
  * Assumption 2 : either dict, or cdict, is defined, not both */
3684
2497
  size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3685
2498
  const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3686
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
2499
+ ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
3687
2500
  {
3688
- DEBUGLOG(5, "ZSTD_initCStream_internal");
2501
+ DEBUGLOG(4, "ZSTD_initCStream_internal");
3689
2502
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3690
2503
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3691
2504
 
@@ -3697,23 +2510,23 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3697
2510
  }
3698
2511
  ZSTD_freeCDict(zcs->cdictLocal);
3699
2512
  zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
3700
- zcs->dictContentByRef, zcs->dictMode,
2513
+ ZSTD_dlm_byCopy, ZSTD_dm_auto,
3701
2514
  params.cParams, zcs->customMem);
3702
2515
  zcs->cdict = zcs->cdictLocal;
3703
2516
  if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
3704
2517
  } else {
3705
2518
  if (cdict) {
3706
- ZSTD_parameters const cdictParams = ZSTD_getParamsFromCDict(cdict);
3707
- params.cParams = cdictParams.cParams; /* cParams are enforced from cdict */
2519
+ params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict */
3708
2520
  }
3709
2521
  ZSTD_freeCDict(zcs->cdictLocal);
3710
2522
  zcs->cdictLocal = NULL;
3711
2523
  zcs->cdict = cdict;
3712
2524
  }
3713
2525
 
2526
+ params.compressionLevel = ZSTD_CLEVEL_CUSTOM;
3714
2527
  zcs->requestedParams = params;
3715
- zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
3716
- return ZSTD_resetCStream_internal(zcs, NULL, 0, zcs->dictMode, zcs->cdict, params, pledgedSrcSize);
2528
+
2529
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
3717
2530
  }
3718
2531
 
3719
2532
  /* ZSTD_initCStream_usingCDict_advanced() :
@@ -3724,7 +2537,8 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
3724
2537
  unsigned long long pledgedSrcSize)
3725
2538
  { /* cannot handle NULL cdict (does not know what to do) */
3726
2539
  if (!cdict) return ERROR(dictionary_wrong);
3727
- { ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
2540
+ { ZSTD_CCtx_params params = zcs->requestedParams;
2541
+ params.cParams = ZSTD_getCParamsFromCDict(cdict);
3728
2542
  params.fParams = fParams;
3729
2543
  return ZSTD_initCStream_internal(zcs,
3730
2544
  NULL, 0, cdict,
@@ -3743,30 +2557,32 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
3743
2557
  const void* dict, size_t dictSize,
3744
2558
  ZSTD_parameters params, unsigned long long pledgedSrcSize)
3745
2559
  {
2560
+ ZSTD_CCtx_params const cctxParams =
2561
+ ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3746
2562
  CHECK_F( ZSTD_checkCParams(params.cParams) );
3747
- zcs->requestedParams = params;
3748
- zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
3749
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, pledgedSrcSize);
2563
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, pledgedSrcSize);
3750
2564
  }
3751
2565
 
3752
2566
  size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3753
2567
  {
3754
2568
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
3755
- zcs->compressionLevel = compressionLevel;
3756
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, 0);
2569
+ ZSTD_CCtx_params const cctxParams =
2570
+ ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2571
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, 0);
3757
2572
  }
3758
2573
 
3759
2574
  size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
3760
2575
  {
3761
- ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
3762
- params.fParams.contentSizeFlag = (pledgedSrcSize>0);
3763
- return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, pledgedSrcSize);
2576
+ ZSTD_CCtx_params cctxParams;
2577
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
2578
+ cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
2579
+ cctxParams.fParams.contentSizeFlag = (pledgedSrcSize>0);
2580
+ return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, cctxParams, pledgedSrcSize);
3764
2581
  }
3765
2582
 
3766
2583
  size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
3767
2584
  {
3768
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
3769
- return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
2585
+ return ZSTD_initCStream_srcSize(zcs, compressionLevel, 0);
3770
2586
  }
3771
2587
 
3772
2588
  /*====== Compression ======*/
@@ -3781,6 +2597,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
3781
2597
 
3782
2598
  /** ZSTD_compressStream_generic():
3783
2599
  * internal function for all *compressStream*() variants and *compress_generic()
2600
+ * non-static, because can be called from zstdmt.c
3784
2601
  * @return : hint size for next input */
3785
2602
  size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3786
2603
  ZSTD_outBuffer* output,
@@ -3934,21 +2751,13 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
3934
2751
  return ZSTD_compressStream_generic(zcs, output, input, ZSTD_e_continue);
3935
2752
  }
3936
2753
 
3937
- /*! ZSTDMT_initCStream_internal() :
3938
- * Private use only. Init streaming operation.
3939
- * expects params to be valid.
3940
- * must receive dict, or cdict, or none, but not both.
3941
- * @return : 0, or an error code */
3942
- size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
3943
- const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3944
- ZSTD_parameters params, unsigned long long pledgedSrcSize);
3945
-
3946
2754
 
3947
2755
  size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
3948
2756
  ZSTD_outBuffer* output,
3949
2757
  ZSTD_inBuffer* input,
3950
2758
  ZSTD_EndDirective endOp)
3951
2759
  {
2760
+ DEBUGLOG(5, "ZSTD_compress_generic");
3952
2761
  /* check conditions */
3953
2762
  if (output->pos > output->size) return ERROR(GENERIC);
3954
2763
  if (input->pos > input->size) return ERROR(GENERIC);
@@ -3956,31 +2765,42 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
3956
2765
 
3957
2766
  /* transparent initialization stage */
3958
2767
  if (cctx->streamStage == zcss_init) {
3959
- const void* const prefix = cctx->prefix;
3960
- size_t const prefixSize = cctx->prefixSize;
3961
- ZSTD_parameters params = cctx->requestedParams;
3962
- if (cctx->compressionLevel != ZSTD_CLEVEL_CUSTOM)
3963
- params.cParams = ZSTD_getCParams(cctx->compressionLevel,
3964
- cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
3965
- cctx->prefix = NULL; cctx->prefixSize = 0; /* single usage */
3966
- assert(prefix==NULL || cctx->cdict==NULL); /* only one can be set */
2768
+ ZSTD_prefixDict const prefixDict = cctx->prefixDict;
2769
+ ZSTD_CCtx_params params = cctx->requestedParams;
2770
+ params.cParams = ZSTD_getCParamsFromCCtxParams(
2771
+ cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
2772
+ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
2773
+ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
2774
+ DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
3967
2775
 
3968
2776
  #ifdef ZSTD_MULTITHREAD
3969
- if (cctx->nbThreads > 1) {
3970
- DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", cctx->nbThreads);
3971
- CHECK_F( ZSTDMT_initCStream_internal(cctx->mtctx, prefix, prefixSize, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
2777
+ if (params.nbThreads > 1) {
2778
+ if (cctx->mtctx == NULL || cctx->appliedParams.nbThreads != params.nbThreads) {
2779
+ ZSTDMT_freeCCtx(cctx->mtctx);
2780
+ cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbThreads, cctx->customMem);
2781
+ if (cctx->mtctx == NULL) return ERROR(memory_allocation);
2782
+ }
2783
+ DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", params.nbThreads);
2784
+ CHECK_F( ZSTDMT_initCStream_internal(
2785
+ cctx->mtctx,
2786
+ prefixDict.dict, prefixDict.dictSize, ZSTD_dm_rawContent,
2787
+ cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
3972
2788
  cctx->streamStage = zcss_load;
2789
+ cctx->appliedParams.nbThreads = params.nbThreads;
3973
2790
  } else
3974
2791
  #endif
3975
2792
  {
3976
- CHECK_F( ZSTD_resetCStream_internal(cctx, prefix, prefixSize, cctx->dictMode, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
2793
+ CHECK_F( ZSTD_resetCStream_internal(
2794
+ cctx, prefixDict.dict, prefixDict.dictSize,
2795
+ prefixDict.dictMode, cctx->cdict, params,
2796
+ cctx->pledgedSrcSizePlusOne-1) );
3977
2797
  } }
3978
2798
 
3979
2799
  /* compression stage */
3980
2800
  #ifdef ZSTD_MULTITHREAD
3981
- if (cctx->nbThreads > 1) {
2801
+ if (cctx->appliedParams.nbThreads > 1) {
3982
2802
  size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
3983
- DEBUGLOG(5, "ZSTDMT_compressStream_generic : %u", (U32)flushMin);
2803
+ DEBUGLOG(5, "ZSTDMT_compressStream_generic result : %u", (U32)flushMin);
3984
2804
  if ( ZSTD_isError(flushMin)
3985
2805
  || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
3986
2806
  ZSTD_startNewCompression(cctx);
@@ -3988,7 +2808,6 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
3988
2808
  return flushMin;
3989
2809
  }
3990
2810
  #endif
3991
-
3992
2811
  CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
3993
2812
  DEBUGLOG(5, "completed ZSTD_compress_generic");
3994
2813
  return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
@@ -4189,6 +3008,7 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
4189
3008
  if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
4190
3009
  { ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
4191
3010
  return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
3011
+
4192
3012
  }
4193
3013
 
4194
3014
  /*! ZSTD_getParams() :