zstd-ruby 1.3.1.1 → 1.3.2.0

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