zstd-ruby 1.4.1.0 → 1.5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/ruby.yml +35 -0
  4. data/README.md +2 -2
  5. data/ext/zstdruby/libzstd/BUCK +5 -7
  6. data/ext/zstdruby/libzstd/Makefile +304 -113
  7. data/ext/zstdruby/libzstd/README.md +83 -20
  8. data/ext/zstdruby/libzstd/common/bitstream.h +59 -51
  9. data/ext/zstdruby/libzstd/common/compiler.h +150 -8
  10. data/ext/zstdruby/libzstd/common/cpu.h +1 -3
  11. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  12. data/ext/zstdruby/libzstd/common/debug.h +22 -49
  13. data/ext/zstdruby/libzstd/common/entropy_common.c +201 -75
  14. data/ext/zstdruby/libzstd/common/error_private.c +3 -1
  15. data/ext/zstdruby/libzstd/common/error_private.h +8 -4
  16. data/ext/zstdruby/libzstd/common/fse.h +50 -42
  17. data/ext/zstdruby/libzstd/common/fse_decompress.c +149 -55
  18. data/ext/zstdruby/libzstd/common/huf.h +43 -39
  19. data/ext/zstdruby/libzstd/common/mem.h +69 -25
  20. data/ext/zstdruby/libzstd/common/pool.c +30 -20
  21. data/ext/zstdruby/libzstd/common/pool.h +3 -3
  22. data/ext/zstdruby/libzstd/common/threading.c +51 -4
  23. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  24. data/ext/zstdruby/libzstd/common/xxhash.c +40 -92
  25. data/ext/zstdruby/libzstd/common/xxhash.h +12 -32
  26. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
  27. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  28. data/ext/zstdruby/libzstd/common/zstd_internal.h +230 -111
  29. data/ext/zstdruby/libzstd/common/zstd_trace.h +154 -0
  30. data/ext/zstdruby/libzstd/compress/fse_compress.c +47 -63
  31. data/ext/zstdruby/libzstd/compress/hist.c +41 -63
  32. data/ext/zstdruby/libzstd/compress/hist.h +13 -33
  33. data/ext/zstdruby/libzstd/compress/huf_compress.c +332 -193
  34. data/ext/zstdruby/libzstd/compress/zstd_compress.c +3614 -1696
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +546 -86
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +441 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +572 -0
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  42. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +662 -0
  43. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +43 -41
  44. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  45. data/ext/zstdruby/libzstd/compress/zstd_fast.c +85 -80
  46. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  47. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1184 -111
  48. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +59 -1
  49. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +333 -208
  50. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +15 -3
  51. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
  52. data/ext/zstdruby/libzstd/compress/zstd_opt.c +228 -129
  53. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  54. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +151 -440
  55. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +32 -114
  56. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +395 -276
  57. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +20 -16
  58. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
  59. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +630 -231
  60. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +606 -380
  61. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +8 -5
  62. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +39 -9
  63. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  64. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  65. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  66. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  67. data/ext/zstdruby/libzstd/dictBuilder/cover.c +55 -46
  68. data/ext/zstdruby/libzstd/dictBuilder/cover.h +20 -9
  69. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
  70. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +43 -31
  71. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +53 -30
  72. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  73. data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
  74. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +4 -4
  75. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +24 -14
  76. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
  77. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +17 -8
  78. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
  79. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +17 -8
  80. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
  81. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +25 -11
  82. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
  83. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +43 -32
  84. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +2 -2
  85. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +27 -19
  86. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
  87. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +32 -20
  88. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
  89. data/ext/zstdruby/libzstd/libzstd.pc.in +2 -1
  90. data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +201 -31
  91. data/ext/zstdruby/libzstd/zstd.h +740 -153
  92. data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +3 -1
  93. data/lib/zstd-ruby/version.rb +1 -1
  94. data/zstd-ruby.gemspec +1 -1
  95. metadata +21 -10
  96. data/.travis.yml +0 -14
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -18,7 +18,8 @@
18
18
  /*-*************************************
19
19
  * Dependencies
20
20
  ***************************************/
21
- #include "zstd_internal.h"
21
+ #include "../common/zstd_internal.h"
22
+ #include "zstd_cwksp.h"
22
23
  #ifdef ZSTD_MULTITHREAD
23
24
  # include "zstdmt_compress.h"
24
25
  #endif
@@ -27,7 +28,6 @@
27
28
  extern "C" {
28
29
  #endif
29
30
 
30
-
31
31
  /*-*************************************
32
32
  * Constants
33
33
  ***************************************/
@@ -63,7 +63,7 @@ typedef struct {
63
63
  } ZSTD_localDict;
64
64
 
65
65
  typedef struct {
66
- U32 CTable[HUF_CTABLE_SIZE_U32(255)];
66
+ HUF_CElt CTable[HUF_CTABLE_SIZE_U32(255)];
67
67
  HUF_repeat repeatMode;
68
68
  } ZSTD_hufCTables_t;
69
69
 
@@ -81,11 +81,75 @@ typedef struct {
81
81
  ZSTD_fseCTables_t fse;
82
82
  } ZSTD_entropyCTables_t;
83
83
 
84
+ /***********************************************
85
+ * Entropy buffer statistics structs and funcs *
86
+ ***********************************************/
87
+ /** ZSTD_hufCTablesMetadata_t :
88
+ * Stores Literals Block Type for a super-block in hType, and
89
+ * huffman tree description in hufDesBuffer.
90
+ * hufDesSize refers to the size of huffman tree description in bytes.
91
+ * This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */
84
92
  typedef struct {
85
- U32 off;
86
- U32 len;
93
+ symbolEncodingType_e hType;
94
+ BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
95
+ size_t hufDesSize;
96
+ } ZSTD_hufCTablesMetadata_t;
97
+
98
+ /** ZSTD_fseCTablesMetadata_t :
99
+ * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
100
+ * fse tables in fseTablesBuffer.
101
+ * fseTablesSize refers to the size of fse tables in bytes.
102
+ * This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */
103
+ typedef struct {
104
+ symbolEncodingType_e llType;
105
+ symbolEncodingType_e ofType;
106
+ symbolEncodingType_e mlType;
107
+ BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
108
+ size_t fseTablesSize;
109
+ size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */
110
+ } ZSTD_fseCTablesMetadata_t;
111
+
112
+ typedef struct {
113
+ ZSTD_hufCTablesMetadata_t hufMetadata;
114
+ ZSTD_fseCTablesMetadata_t fseMetadata;
115
+ } ZSTD_entropyCTablesMetadata_t;
116
+
117
+ /** ZSTD_buildBlockEntropyStats() :
118
+ * Builds entropy for the block.
119
+ * @return : 0 on success or error code */
120
+ size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
121
+ const ZSTD_entropyCTables_t* prevEntropy,
122
+ ZSTD_entropyCTables_t* nextEntropy,
123
+ const ZSTD_CCtx_params* cctxParams,
124
+ ZSTD_entropyCTablesMetadata_t* entropyMetadata,
125
+ void* workspace, size_t wkspSize);
126
+
127
+ /*********************************
128
+ * Compression internals structs *
129
+ *********************************/
130
+
131
+ typedef struct {
132
+ U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
133
+ U32 len; /* Raw length of match */
87
134
  } ZSTD_match_t;
88
135
 
136
+ typedef struct {
137
+ U32 offset; /* Offset of sequence */
138
+ U32 litLength; /* Length of literals prior to match */
139
+ U32 matchLength; /* Raw length of match */
140
+ } rawSeq;
141
+
142
+ typedef struct {
143
+ rawSeq* seq; /* The start of the sequences */
144
+ size_t pos; /* The index in seq where reading stopped. pos <= size. */
145
+ size_t posInSequence; /* The position within the sequence at seq[pos] where reading
146
+ stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */
147
+ size_t size; /* The number of sequences. <= capacity. */
148
+ size_t capacity; /* The capacity starting from `seq` pointer */
149
+ } rawSeqStore_t;
150
+
151
+ UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
152
+
89
153
  typedef struct {
90
154
  int price;
91
155
  U32 off;
@@ -124,25 +188,50 @@ typedef struct {
124
188
  } ZSTD_compressedBlockState_t;
125
189
 
126
190
  typedef struct {
127
- BYTE const* nextSrc; /* next block here to continue on current prefix */
128
- BYTE const* base; /* All regular indexes relative to this position */
129
- BYTE const* dictBase; /* extDict indexes relative to this position */
130
- U32 dictLimit; /* below that point, need extDict */
131
- U32 lowLimit; /* below that point, no more valid data */
191
+ BYTE const* nextSrc; /* next block here to continue on current prefix */
192
+ BYTE const* base; /* All regular indexes relative to this position */
193
+ BYTE const* dictBase; /* extDict indexes relative to this position */
194
+ U32 dictLimit; /* below that point, need extDict */
195
+ U32 lowLimit; /* below that point, no more valid data */
196
+ U32 nbOverflowCorrections; /* Number of times overflow correction has run since
197
+ * ZSTD_window_init(). Useful for debugging coredumps
198
+ * and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY.
199
+ */
132
200
  } ZSTD_window_t;
133
201
 
134
202
  typedef struct ZSTD_matchState_t ZSTD_matchState_t;
203
+
204
+ #define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */
205
+
135
206
  struct ZSTD_matchState_t {
136
207
  ZSTD_window_t window; /* State for window round buffer management */
137
- U32 loadedDictEnd; /* index of end of dictionary, within context's referential. When dict referential is copied into active context (i.e. not attached), effectively same value as dictSize, since referential starts from zero */
208
+ U32 loadedDictEnd; /* index of end of dictionary, within context's referential.
209
+ * When loadedDictEnd != 0, a dictionary is in use, and still valid.
210
+ * This relies on a mechanism to set loadedDictEnd=0 when dictionary is no longer within distance.
211
+ * Such mechanism is provided within ZSTD_window_enforceMaxDist() and ZSTD_checkDictValidity().
212
+ * When dict referential is copied into active context (i.e. not attached),
213
+ * loadedDictEnd == dictSize, since referential starts from zero.
214
+ */
138
215
  U32 nextToUpdate; /* index from which to continue table update */
139
- U32 hashLog3; /* dispatch table : larger == faster, more memory */
216
+ U32 hashLog3; /* dispatch table for matches of len==3 : larger == faster, more memory */
217
+
218
+ U32 rowHashLog; /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/
219
+ U16* tagTable; /* For row-based matchFinder: A row-based table containing the hashes and head index. */
220
+ U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */
221
+
140
222
  U32* hashTable;
141
223
  U32* hashTable3;
142
224
  U32* chainTable;
225
+
226
+ U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */
227
+
228
+ int dedicatedDictSearch; /* Indicates whether this matchState is using the
229
+ * dedicated dictionary search structure.
230
+ */
143
231
  optState_t opt; /* optimal parser state */
144
232
  const ZSTD_matchState_t* dictMatchState;
145
233
  ZSTD_compressionParameters cParams;
234
+ const rawSeqStore_t* ldmSeqStore;
146
235
  };
147
236
 
148
237
  typedef struct {
@@ -156,12 +245,22 @@ typedef struct {
156
245
  U32 checksum;
157
246
  } ldmEntry_t;
158
247
 
248
+ typedef struct {
249
+ BYTE const* split;
250
+ U32 hash;
251
+ U32 checksum;
252
+ ldmEntry_t* bucket;
253
+ } ldmMatchCandidate_t;
254
+
255
+ #define LDM_BATCH_SIZE 64
256
+
159
257
  typedef struct {
160
258
  ZSTD_window_t window; /* State for the window round buffer management */
161
259
  ldmEntry_t* hashTable;
260
+ U32 loadedDictEnd;
162
261
  BYTE* bucketOffsets; /* Next position in bucket to insert entry */
163
- U64 hashPower; /* Used to compute the rolling hash.
164
- * Depends on ldmParams.minMatchLength */
262
+ size_t splitIndices[LDM_BATCH_SIZE];
263
+ ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE];
165
264
  } ldmState_t;
166
265
 
167
266
  typedef struct {
@@ -174,17 +273,11 @@ typedef struct {
174
273
  } ldmParams_t;
175
274
 
176
275
  typedef struct {
177
- U32 offset;
178
- U32 litLength;
179
- U32 matchLength;
180
- } rawSeq;
181
-
182
- typedef struct {
183
- rawSeq* seq; /* The start of the sequences */
184
- size_t pos; /* The position where reading stopped. <= size. */
185
- size_t size; /* The number of sequences. <= capacity. */
186
- size_t capacity; /* The capacity starting from `seq` pointer */
187
- } rawSeqStore_t;
276
+ int collectSequences;
277
+ ZSTD_Sequence* seqStart;
278
+ size_t seqIndex;
279
+ size_t maxSequences;
280
+ } SeqCollector;
188
281
 
189
282
  struct ZSTD_CCtx_params_s {
190
283
  ZSTD_format_e format;
@@ -197,6 +290,9 @@ struct ZSTD_CCtx_params_s {
197
290
  size_t targetCBlockSize; /* Tries to fit compressed block size to be around targetCBlockSize.
198
291
  * No target when targetCBlockSize == 0.
199
292
  * There is no guarantee on compressed block size */
293
+ int srcSizeHint; /* User's best guess of source size.
294
+ * Hint is not valid when srcSizeHint == 0.
295
+ * There is no guarantee that hint is close to actual source size */
200
296
 
201
297
  ZSTD_dictAttachPref_e attachDictPref;
202
298
  ZSTD_literalCompressionMode_e literalCompressionMode;
@@ -210,28 +306,65 @@ struct ZSTD_CCtx_params_s {
210
306
  /* Long distance matching parameters */
211
307
  ldmParams_t ldmParams;
212
308
 
309
+ /* Dedicated dict search algorithm trigger */
310
+ int enableDedicatedDictSearch;
311
+
312
+ /* Input/output buffer modes */
313
+ ZSTD_bufferMode_e inBufferMode;
314
+ ZSTD_bufferMode_e outBufferMode;
315
+
316
+ /* Sequence compression API */
317
+ ZSTD_sequenceFormat_e blockDelimiters;
318
+ int validateSequences;
319
+
320
+ /* Block splitting */
321
+ int splitBlocks;
322
+
323
+ /* Param for deciding whether to use row-based matchfinder */
324
+ ZSTD_useRowMatchFinderMode_e useRowMatchFinder;
325
+
326
+ /* Always load a dictionary in ext-dict mode (not prefix mode)? */
327
+ int deterministicRefPrefix;
328
+
213
329
  /* Internal use, for createCCtxParams() and freeCCtxParams() only */
214
330
  ZSTD_customMem customMem;
215
331
  }; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
216
332
 
333
+ #define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))
334
+ #define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE)
335
+
336
+ /**
337
+ * Indicates whether this compression proceeds directly from user-provided
338
+ * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or
339
+ * whether the context needs to buffer the input/output (ZSTDb_buffered).
340
+ */
341
+ typedef enum {
342
+ ZSTDb_not_buffered,
343
+ ZSTDb_buffered
344
+ } ZSTD_buffered_policy_e;
345
+
217
346
  struct ZSTD_CCtx_s {
218
347
  ZSTD_compressionStage_e stage;
219
348
  int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
220
349
  int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
221
350
  ZSTD_CCtx_params requestedParams;
222
351
  ZSTD_CCtx_params appliedParams;
352
+ ZSTD_CCtx_params simpleApiParams; /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */
223
353
  U32 dictID;
354
+ size_t dictContentSize;
224
355
 
225
- int workSpaceOversizedDuration;
226
- void* workSpace;
227
- size_t workSpaceSize;
356
+ ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */
228
357
  size_t blockSize;
229
358
  unsigned long long pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
230
359
  unsigned long long consumedSrcSize;
231
360
  unsigned long long producedCSize;
232
361
  XXH64_state_t xxhState;
233
362
  ZSTD_customMem customMem;
363
+ ZSTD_threadPool* pool;
234
364
  size_t staticSize;
365
+ SeqCollector seqCollector;
366
+ int isFirstBlock;
367
+ int initialized;
235
368
 
236
369
  seqStore_t seqStore; /* sequences storage ptrs */
237
370
  ldmState_t ldmState; /* long distance matching state */
@@ -239,7 +372,10 @@ struct ZSTD_CCtx_s {
239
372
  size_t maxNbLdmSequences;
240
373
  rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */
241
374
  ZSTD_blockState_t blockState;
242
- U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
375
+ U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */
376
+
377
+ /* Wether we are streaming or not */
378
+ ZSTD_buffered_policy_e bufferedPolicy;
243
379
 
244
380
  /* streaming */
245
381
  char* inBuff;
@@ -254,6 +390,10 @@ struct ZSTD_CCtx_s {
254
390
  ZSTD_cStreamStage streamStage;
255
391
  U32 frameEnded;
256
392
 
393
+ /* Stable in/out buffer verification */
394
+ ZSTD_inBuffer expectedInBuffer;
395
+ size_t expectedOutBufferSize;
396
+
257
397
  /* Dictionary */
258
398
  ZSTD_localDict localDict;
259
399
  const ZSTD_CDict* cdict;
@@ -263,17 +403,46 @@ struct ZSTD_CCtx_s {
263
403
  #ifdef ZSTD_MULTITHREAD
264
404
  ZSTDMT_CCtx* mtctx;
265
405
  #endif
406
+
407
+ /* Tracing */
408
+ #if ZSTD_TRACE
409
+ ZSTD_TraceCtx traceCtx;
410
+ #endif
266
411
  };
267
412
 
268
413
  typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
269
414
 
270
- typedef enum { ZSTD_noDict = 0, ZSTD_extDict = 1, ZSTD_dictMatchState = 2 } ZSTD_dictMode_e;
271
-
415
+ typedef enum {
416
+ ZSTD_noDict = 0,
417
+ ZSTD_extDict = 1,
418
+ ZSTD_dictMatchState = 2,
419
+ ZSTD_dedicatedDictSearch = 3
420
+ } ZSTD_dictMode_e;
421
+
422
+ typedef enum {
423
+ ZSTD_cpm_noAttachDict = 0, /* Compression with ZSTD_noDict or ZSTD_extDict.
424
+ * In this mode we use both the srcSize and the dictSize
425
+ * when selecting and adjusting parameters.
426
+ */
427
+ ZSTD_cpm_attachDict = 1, /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch.
428
+ * In this mode we only take the srcSize into account when selecting
429
+ * and adjusting parameters.
430
+ */
431
+ ZSTD_cpm_createCDict = 2, /* Creating a CDict.
432
+ * In this mode we take both the source size and the dictionary size
433
+ * into account when selecting and adjusting the parameters.
434
+ */
435
+ ZSTD_cpm_unknown = 3, /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.
436
+ * We don't know what these parameters are for. We default to the legacy
437
+ * behavior of taking both the source size and the dict size into account
438
+ * when selecting and adjusting parameters.
439
+ */
440
+ } ZSTD_cParamMode_e;
272
441
 
273
442
  typedef size_t (*ZSTD_blockCompressor) (
274
443
  ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
275
444
  void const* src, size_t srcSize);
276
- ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode);
445
+ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
277
446
 
278
447
 
279
448
  MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
@@ -307,43 +476,162 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
307
476
  return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];
308
477
  }
309
478
 
479
+ typedef struct repcodes_s {
480
+ U32 rep[3];
481
+ } repcodes_t;
482
+
483
+ MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
484
+ {
485
+ repcodes_t newReps;
486
+ if (offset >= ZSTD_REP_NUM) { /* full offset */
487
+ newReps.rep[2] = rep[1];
488
+ newReps.rep[1] = rep[0];
489
+ newReps.rep[0] = offset - ZSTD_REP_MOVE;
490
+ } else { /* repcode */
491
+ U32 const repCode = offset + ll0;
492
+ if (repCode > 0) { /* note : if repCode==0, no change */
493
+ U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
494
+ newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
495
+ newReps.rep[1] = rep[0];
496
+ newReps.rep[0] = currentOffset;
497
+ } else { /* repCode == 0 */
498
+ ZSTD_memcpy(&newReps, rep, sizeof(newReps));
499
+ }
500
+ }
501
+ return newReps;
502
+ }
503
+
504
+ /* ZSTD_cParam_withinBounds:
505
+ * @return 1 if value is within cParam bounds,
506
+ * 0 otherwise */
507
+ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
508
+ {
509
+ ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
510
+ if (ZSTD_isError(bounds.error)) return 0;
511
+ if (value < bounds.lowerBound) return 0;
512
+ if (value > bounds.upperBound) return 0;
513
+ return 1;
514
+ }
515
+
516
+ /* ZSTD_noCompressBlock() :
517
+ * Writes uncompressed block to dst buffer from given src.
518
+ * Returns the size of the block */
519
+ MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
520
+ {
521
+ U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
522
+ RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
523
+ dstSize_tooSmall, "dst buf too small for uncompressed block");
524
+ MEM_writeLE24(dst, cBlockHeader24);
525
+ ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
526
+ return ZSTD_blockHeaderSize + srcSize;
527
+ }
528
+
529
+ MEM_STATIC size_t ZSTD_rleCompressBlock (void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock)
530
+ {
531
+ BYTE* const op = (BYTE*)dst;
532
+ U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3);
533
+ RETURN_ERROR_IF(dstCapacity < 4, dstSize_tooSmall, "");
534
+ MEM_writeLE24(op, cBlockHeader);
535
+ op[3] = src;
536
+ return 4;
537
+ }
538
+
539
+
540
+ /* ZSTD_minGain() :
541
+ * minimum compression required
542
+ * to generate a compress block or a compressed literals section.
543
+ * note : use same formula for both situations */
544
+ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
545
+ {
546
+ U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
547
+ ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
548
+ assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
549
+ return (srcSize >> minlog) + 2;
550
+ }
551
+
552
+ MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
553
+ {
554
+ switch (cctxParams->literalCompressionMode) {
555
+ case ZSTD_lcm_huffman:
556
+ return 0;
557
+ case ZSTD_lcm_uncompressed:
558
+ return 1;
559
+ default:
560
+ assert(0 /* impossible: pre-validated */);
561
+ /* fall-through */
562
+ case ZSTD_lcm_auto:
563
+ return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
564
+ }
565
+ }
566
+
567
+ /*! ZSTD_safecopyLiterals() :
568
+ * memcpy() function that won't read beyond more than WILDCOPY_OVERLENGTH bytes past ilimit_w.
569
+ * Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single
570
+ * large copies.
571
+ */
572
+ static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w) {
573
+ assert(iend > ilimit_w);
574
+ if (ip <= ilimit_w) {
575
+ ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
576
+ op += ilimit_w - ip;
577
+ ip = ilimit_w;
578
+ }
579
+ while (ip < iend) *op++ = *ip++;
580
+ }
581
+
310
582
  /*! ZSTD_storeSeq() :
311
- * Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
312
- * `offsetCode` : distance to match + 3 (values 1-3 are repCodes).
583
+ * Store a sequence (litlen, litPtr, offCode and mlBase) into seqStore_t.
584
+ * `offCode` : distance to match + ZSTD_REP_MOVE (values <= ZSTD_REP_MOVE are repCodes).
313
585
  * `mlBase` : matchLength - MINMATCH
586
+ * Allowed to overread literals up to litLimit.
314
587
  */
315
- MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t mlBase)
588
+ HINT_INLINE UNUSED_ATTR
589
+ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, const BYTE* litLimit, U32 offCode, size_t mlBase)
316
590
  {
591
+ BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;
592
+ BYTE const* const litEnd = literals + litLength;
317
593
  #if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)
318
594
  static const BYTE* g_start = NULL;
319
595
  if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */
320
596
  { U32 const pos = (U32)((const BYTE*)literals - g_start);
321
597
  DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
322
- pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offsetCode);
598
+ pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offCode);
323
599
  }
324
600
  #endif
325
601
  assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
326
602
  /* copy Literals */
327
603
  assert(seqStorePtr->maxNbLit <= 128 KB);
328
604
  assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);
329
- ZSTD_wildcopy(seqStorePtr->lit, literals, litLength, ZSTD_no_overlap);
605
+ assert(literals + litLength <= litLimit);
606
+ if (litEnd <= litLimit_w) {
607
+ /* Common case we can use wildcopy.
608
+ * First copy 16 bytes, because literals are likely short.
609
+ */
610
+ assert(WILDCOPY_OVERLENGTH >= 16);
611
+ ZSTD_copy16(seqStorePtr->lit, literals);
612
+ if (litLength > 16) {
613
+ ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, (ptrdiff_t)litLength-16, ZSTD_no_overlap);
614
+ }
615
+ } else {
616
+ ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w);
617
+ }
330
618
  seqStorePtr->lit += litLength;
331
619
 
332
620
  /* literal Length */
333
621
  if (litLength>0xFFFF) {
334
- assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
335
- seqStorePtr->longLengthID = 1;
622
+ assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
623
+ seqStorePtr->longLengthType = ZSTD_llt_literalLength;
336
624
  seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
337
625
  }
338
626
  seqStorePtr->sequences[0].litLength = (U16)litLength;
339
627
 
340
628
  /* match offset */
341
- seqStorePtr->sequences[0].offset = offsetCode + 1;
629
+ seqStorePtr->sequences[0].offset = offCode + 1;
342
630
 
343
631
  /* match Length */
344
632
  if (mlBase>0xFFFF) {
345
- assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
346
- seqStorePtr->longLengthID = 2;
633
+ assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
634
+ seqStorePtr->longLengthType = ZSTD_llt_matchLength;
347
635
  seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
348
636
  }
349
637
  seqStorePtr->sequences[0].matchLength = (U16)mlBase;
@@ -360,9 +648,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
360
648
  if (MEM_isLittleEndian()) {
361
649
  if (MEM_64bits()) {
362
650
  # if defined(_MSC_VER) && defined(_WIN64)
363
- unsigned long r = 0;
364
- _BitScanForward64( &r, (U64)val );
365
- return (unsigned)(r>>3);
651
+ # if STATIC_BMI2
652
+ return _tzcnt_u64(val) >> 3;
653
+ # else
654
+ unsigned long r = 0;
655
+ return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0;
656
+ # endif
366
657
  # elif defined(__GNUC__) && (__GNUC__ >= 4)
367
658
  return (__builtin_ctzll((U64)val) >> 3);
368
659
  # else
@@ -379,8 +670,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
379
670
  } else { /* 32 bits */
380
671
  # if defined(_MSC_VER)
381
672
  unsigned long r=0;
382
- _BitScanForward( &r, (U32)val );
383
- return (unsigned)(r>>3);
673
+ return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0;
384
674
  # elif defined(__GNUC__) && (__GNUC__ >= 3)
385
675
  return (__builtin_ctz((U32)val) >> 3);
386
676
  # else
@@ -394,9 +684,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
394
684
  } else { /* Big Endian CPU */
395
685
  if (MEM_64bits()) {
396
686
  # if defined(_MSC_VER) && defined(_WIN64)
397
- unsigned long r = 0;
398
- _BitScanReverse64( &r, val );
399
- return (unsigned)(r>>3);
687
+ # if STATIC_BMI2
688
+ return _lzcnt_u64(val) >> 3;
689
+ # else
690
+ unsigned long r = 0;
691
+ return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0;
692
+ # endif
400
693
  # elif defined(__GNUC__) && (__GNUC__ >= 4)
401
694
  return (__builtin_clzll(val) >> 3);
402
695
  # else
@@ -410,8 +703,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
410
703
  } else { /* 32 bits */
411
704
  # if defined(_MSC_VER)
412
705
  unsigned long r = 0;
413
- _BitScanReverse( &r, (unsigned long)val );
414
- return (unsigned)(r>>3);
706
+ return _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0;
415
707
  # elif defined(__GNUC__) && (__GNUC__ >= 3)
416
708
  return (__builtin_clz((U32)val) >> 3);
417
709
  # else
@@ -492,7 +784,8 @@ static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
492
784
  static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
493
785
  static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
494
786
 
495
- MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
787
+ MEM_STATIC FORCE_INLINE_ATTR
788
+ size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
496
789
  {
497
790
  switch(mls)
498
791
  {
@@ -589,6 +882,13 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
589
882
  window->dictLimit = end;
590
883
  }
591
884
 
885
+ MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)
886
+ {
887
+ return window.dictLimit == 1 &&
888
+ window.lowLimit == 1 &&
889
+ (window.nextSrc - window.base) == 1;
890
+ }
891
+
592
892
  /**
593
893
  * ZSTD_window_hasExtDict():
594
894
  * Returns non-zero if the window has a non-empty extDict.
@@ -608,20 +908,74 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
608
908
  return ZSTD_window_hasExtDict(ms->window) ?
609
909
  ZSTD_extDict :
610
910
  ms->dictMatchState != NULL ?
611
- ZSTD_dictMatchState :
911
+ (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) :
612
912
  ZSTD_noDict;
613
913
  }
614
914
 
915
+ /* Defining this macro to non-zero tells zstd to run the overflow correction
916
+ * code much more frequently. This is very inefficient, and should only be
917
+ * used for tests and fuzzers.
918
+ */
919
+ #ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY
920
+ # ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
921
+ # define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1
922
+ # else
923
+ # define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0
924
+ # endif
925
+ #endif
926
+
927
+ /**
928
+ * ZSTD_window_canOverflowCorrect():
929
+ * Returns non-zero if the indices are large enough for overflow correction
930
+ * to work correctly without impacting compression ratio.
931
+ */
932
+ MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,
933
+ U32 cycleLog,
934
+ U32 maxDist,
935
+ U32 loadedDictEnd,
936
+ void const* src)
937
+ {
938
+ U32 const cycleSize = 1u << cycleLog;
939
+ U32 const curr = (U32)((BYTE const*)src - window.base);
940
+ U32 const minIndexToOverflowCorrect = cycleSize + MAX(maxDist, cycleSize);
941
+
942
+ /* Adjust the min index to backoff the overflow correction frequency,
943
+ * so we don't waste too much CPU in overflow correction. If this
944
+ * computation overflows we don't really care, we just need to make
945
+ * sure it is at least minIndexToOverflowCorrect.
946
+ */
947
+ U32 const adjustment = window.nbOverflowCorrections + 1;
948
+ U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment,
949
+ minIndexToOverflowCorrect);
950
+ U32 const indexLargeEnough = curr > adjustedIndex;
951
+
952
+ /* Only overflow correct early if the dictionary is invalidated already,
953
+ * so we don't hurt compression ratio.
954
+ */
955
+ U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd;
956
+
957
+ return indexLargeEnough && dictionaryInvalidated;
958
+ }
959
+
615
960
  /**
616
961
  * ZSTD_window_needOverflowCorrection():
617
962
  * Returns non-zero if the indices are getting too large and need overflow
618
963
  * protection.
619
964
  */
620
965
  MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
966
+ U32 cycleLog,
967
+ U32 maxDist,
968
+ U32 loadedDictEnd,
969
+ void const* src,
621
970
  void const* srcEnd)
622
971
  {
623
- U32 const current = (U32)((BYTE const*)srcEnd - window.base);
624
- return current > ZSTD_CURRENT_MAX;
972
+ U32 const curr = (U32)((BYTE const*)srcEnd - window.base);
973
+ if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
974
+ if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) {
975
+ return 1;
976
+ }
977
+ }
978
+ return curr > ZSTD_CURRENT_MAX;
625
979
  }
626
980
 
627
981
  /**
@@ -632,7 +986,6 @@ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
632
986
  *
633
987
  * The least significant cycleLog bits of the indices must remain the same,
634
988
  * which may be 0. Every index up to maxDist in the past must be valid.
635
- * NOTE: (maxDist & cycleMask) must be zero.
636
989
  */
637
990
  MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
638
991
  U32 maxDist, void const* src)
@@ -656,19 +1009,41 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
656
1009
  * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
657
1010
  * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
658
1011
  */
659
- U32 const cycleMask = (1U << cycleLog) - 1;
660
- U32 const current = (U32)((BYTE const*)src - window->base);
661
- U32 const newCurrent = (current & cycleMask) + maxDist;
662
- U32 const correction = current - newCurrent;
663
- assert((maxDist & cycleMask) == 0);
664
- assert(current > newCurrent);
665
- /* Loose bound, should be around 1<<29 (see above) */
666
- assert(correction > 1<<28);
1012
+ U32 const cycleSize = 1u << cycleLog;
1013
+ U32 const cycleMask = cycleSize - 1;
1014
+ U32 const curr = (U32)((BYTE const*)src - window->base);
1015
+ U32 const currentCycle0 = curr & cycleMask;
1016
+ /* Exclude zero so that newCurrent - maxDist >= 1. */
1017
+ U32 const currentCycle1 = currentCycle0 == 0 ? cycleSize : currentCycle0;
1018
+ U32 const newCurrent = currentCycle1 + MAX(maxDist, cycleSize);
1019
+ U32 const correction = curr - newCurrent;
1020
+ /* maxDist must be a power of two so that:
1021
+ * (newCurrent & cycleMask) == (curr & cycleMask)
1022
+ * This is required to not corrupt the chains / binary tree.
1023
+ */
1024
+ assert((maxDist & (maxDist - 1)) == 0);
1025
+ assert((curr & cycleMask) == (newCurrent & cycleMask));
1026
+ assert(curr > newCurrent);
1027
+ if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
1028
+ /* Loose bound, should be around 1<<29 (see above) */
1029
+ assert(correction > 1<<28);
1030
+ }
667
1031
 
668
1032
  window->base += correction;
669
1033
  window->dictBase += correction;
670
- window->lowLimit -= correction;
671
- window->dictLimit -= correction;
1034
+ if (window->lowLimit <= correction) window->lowLimit = 1;
1035
+ else window->lowLimit -= correction;
1036
+ if (window->dictLimit <= correction) window->dictLimit = 1;
1037
+ else window->dictLimit -= correction;
1038
+
1039
+ /* Ensure we can still reference the full window. */
1040
+ assert(newCurrent >= maxDist);
1041
+ assert(newCurrent - maxDist >= 1);
1042
+ /* Ensure that lowLimit and dictLimit didn't underflow. */
1043
+ assert(window->lowLimit <= newCurrent);
1044
+ assert(window->dictLimit <= newCurrent);
1045
+
1046
+ ++window->nbOverflowCorrections;
672
1047
 
673
1048
  DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
674
1049
  window->lowLimit);
@@ -739,24 +1114,47 @@ ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
739
1114
 
740
1115
  /* Similar to ZSTD_window_enforceMaxDist(),
741
1116
  * but only invalidates dictionary
742
- * when input progresses beyond window size. */
1117
+ * when input progresses beyond window size.
1118
+ * assumption : loadedDictEndPtr and dictMatchStatePtr are valid (non NULL)
1119
+ * loadedDictEnd uses same referential as window->base
1120
+ * maxDist is the window size */
743
1121
  MEM_STATIC void
744
- ZSTD_checkDictValidity(ZSTD_window_t* window,
1122
+ ZSTD_checkDictValidity(const ZSTD_window_t* window,
745
1123
  const void* blockEnd,
746
1124
  U32 maxDist,
747
1125
  U32* loadedDictEndPtr,
748
1126
  const ZSTD_matchState_t** dictMatchStatePtr)
749
1127
  {
750
- U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
751
- U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
752
- DEBUGLOG(5, "ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
753
- (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
1128
+ assert(loadedDictEndPtr != NULL);
1129
+ assert(dictMatchStatePtr != NULL);
1130
+ { U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
1131
+ U32 const loadedDictEnd = *loadedDictEndPtr;
1132
+ DEBUGLOG(5, "ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
1133
+ (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
1134
+ assert(blockEndIdx >= loadedDictEnd);
1135
+
1136
+ if (blockEndIdx > loadedDictEnd + maxDist) {
1137
+ /* On reaching window size, dictionaries are invalidated.
1138
+ * For simplification, if window size is reached anywhere within next block,
1139
+ * the dictionary is invalidated for the full block.
1140
+ */
1141
+ DEBUGLOG(6, "invalidating dictionary for current block (distance > windowSize)");
1142
+ *loadedDictEndPtr = 0;
1143
+ *dictMatchStatePtr = NULL;
1144
+ } else {
1145
+ if (*loadedDictEndPtr != 0) {
1146
+ DEBUGLOG(6, "dictionary considered valid for current block");
1147
+ } } }
1148
+ }
754
1149
 
755
- if (loadedDictEnd && (blockEndIdx > maxDist + loadedDictEnd)) {
756
- /* On reaching window size, dictionaries are invalidated */
757
- if (loadedDictEndPtr) *loadedDictEndPtr = 0;
758
- if (dictMatchStatePtr) *dictMatchStatePtr = NULL;
759
- }
1150
+ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
1151
+ ZSTD_memset(window, 0, sizeof(*window));
1152
+ window->base = (BYTE const*)"";
1153
+ window->dictBase = (BYTE const*)"";
1154
+ window->dictLimit = 1; /* start from 1, so that 1st position is valid */
1155
+ window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
1156
+ window->nextSrc = window->base + 1; /* see issue #1241 */
1157
+ window->nbOverflowCorrections = 0;
760
1158
  }
761
1159
 
762
1160
  /**
@@ -767,13 +1165,18 @@ ZSTD_checkDictValidity(ZSTD_window_t* window,
767
1165
  * Returns non-zero if the segment is contiguous.
768
1166
  */
769
1167
  MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
770
- void const* src, size_t srcSize)
1168
+ void const* src, size_t srcSize,
1169
+ int forceNonContiguous)
771
1170
  {
772
1171
  BYTE const* const ip = (BYTE const*)src;
773
1172
  U32 contiguous = 1;
774
1173
  DEBUGLOG(5, "ZSTD_window_update");
1174
+ if (srcSize == 0)
1175
+ return contiguous;
1176
+ assert(window->base != NULL);
1177
+ assert(window->dictBase != NULL);
775
1178
  /* Check if blocks follow each other */
776
- if (src != window->nextSrc) {
1179
+ if (src != window->nextSrc || forceNonContiguous) {
777
1180
  /* not contiguous */
778
1181
  size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
779
1182
  DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
@@ -782,7 +1185,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
782
1185
  window->dictLimit = (U32)distanceFromBase;
783
1186
  window->dictBase = window->base;
784
1187
  window->base = ip - distanceFromBase;
785
- // ms->nextToUpdate = window->dictLimit;
1188
+ /* ms->nextToUpdate = window->dictLimit; */
786
1189
  if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit; /* too small extDict */
787
1190
  contiguous = 0;
788
1191
  }
@@ -798,6 +1201,40 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
798
1201
  return contiguous;
799
1202
  }
800
1203
 
1204
+ /**
1205
+ * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix.
1206
+ */
1207
+ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
1208
+ {
1209
+ U32 const maxDistance = 1U << windowLog;
1210
+ U32 const lowestValid = ms->window.lowLimit;
1211
+ U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
1212
+ U32 const isDictionary = (ms->loadedDictEnd != 0);
1213
+ /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary
1214
+ * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't
1215
+ * valid for the entire block. So this check is sufficient to find the lowest valid match index.
1216
+ */
1217
+ U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
1218
+ return matchLowest;
1219
+ }
1220
+
1221
+ /**
1222
+ * Returns the lowest allowed match index in the prefix.
1223
+ */
1224
+ MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
1225
+ {
1226
+ U32 const maxDistance = 1U << windowLog;
1227
+ U32 const lowestValid = ms->window.dictLimit;
1228
+ U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
1229
+ U32 const isDictionary = (ms->loadedDictEnd != 0);
1230
+ /* When computing the lowest prefix index we need to take the dictionary into account to handle
1231
+ * the edge case where the dictionary and the source are contiguous in memory.
1232
+ */
1233
+ U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
1234
+ return matchLowest;
1235
+ }
1236
+
1237
+
801
1238
 
802
1239
  /* debug functions */
803
1240
  #if (DEBUGLEVEL>=2)
@@ -835,6 +1272,20 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
835
1272
  }
836
1273
  #endif
837
1274
 
1275
+ /* ===============================================================
1276
+ * Shared internal declarations
1277
+ * These prototypes may be called from sources not in lib/compress
1278
+ * =============================================================== */
1279
+
1280
+ /* ZSTD_loadCEntropy() :
1281
+ * dict : must point at beginning of a valid zstd dictionary.
1282
+ * return : size of dictionary header (size of magic number + dict ID + entropy tables)
1283
+ * assumptions : magic number supposed already checked
1284
+ * and dictSize >= 8 */
1285
+ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
1286
+ const void* const dict, size_t dictSize);
1287
+
1288
+ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);
838
1289
 
839
1290
  /* ==============================================================
840
1291
  * Private declarations
@@ -844,9 +1295,10 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
844
1295
  /* ZSTD_getCParamsFromCCtxParams() :
845
1296
  * cParams are built depending on compressionLevel, src size hints,
846
1297
  * LDM and manually set compression parameters.
1298
+ * Note: srcSizeHint == 0 means 0!
847
1299
  */
848
1300
  ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
849
- const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize);
1301
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
850
1302
 
851
1303
  /*! ZSTD_initCStream_internal() :
852
1304
  * Private use only. Init streaming operation.
@@ -856,7 +1308,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
856
1308
  size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
857
1309
  const void* dict, size_t dictSize,
858
1310
  const ZSTD_CDict* cdict,
859
- ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
1311
+ const ZSTD_CCtx_params* params, unsigned long long pledgedSrcSize);
860
1312
 
861
1313
  void ZSTD_resetSeqStore(seqStore_t* ssPtr);
862
1314
 
@@ -871,7 +1323,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
871
1323
  ZSTD_dictContentType_e dictContentType,
872
1324
  ZSTD_dictTableLoadMethod_e dtlm,
873
1325
  const ZSTD_CDict* cdict,
874
- ZSTD_CCtx_params params,
1326
+ const ZSTD_CCtx_params* params,
875
1327
  unsigned long long pledgedSrcSize);
876
1328
 
877
1329
  /* ZSTD_compress_advanced_internal() :
@@ -880,7 +1332,7 @@ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
880
1332
  void* dst, size_t dstCapacity,
881
1333
  const void* src, size_t srcSize,
882
1334
  const void* dict,size_t dictSize,
883
- ZSTD_CCtx_params params);
1335
+ const ZSTD_CCtx_params* params);
884
1336
 
885
1337
 
886
1338
  /* ZSTD_writeLastEmptyBlock() :
@@ -903,5 +1355,13 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
903
1355
  */
904
1356
  size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);
905
1357
 
1358
+ /** ZSTD_cycleLog() :
1359
+ * condition for correct operation : hashLog > 1 */
1360
+ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
1361
+
1362
+ /** ZSTD_CCtx_trace() :
1363
+ * Trace the end of a compression call.
1364
+ */
1365
+ void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);
906
1366
 
907
1367
  #endif /* ZSTD_COMPRESS_H */