extzstd 0.3.2 → 0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -3
- data/contrib/zstd/CHANGELOG +225 -1
- data/contrib/zstd/CONTRIBUTING.md +158 -75
- data/contrib/zstd/LICENSE +4 -4
- data/contrib/zstd/Makefile +106 -69
- data/contrib/zstd/Package.swift +36 -0
- data/contrib/zstd/README.md +64 -36
- data/contrib/zstd/SECURITY.md +15 -0
- data/contrib/zstd/TESTING.md +2 -3
- data/contrib/zstd/lib/BUCK +5 -7
- data/contrib/zstd/lib/Makefile +117 -199
- data/contrib/zstd/lib/README.md +37 -7
- data/contrib/zstd/lib/common/allocations.h +55 -0
- data/contrib/zstd/lib/common/bits.h +200 -0
- data/contrib/zstd/lib/common/bitstream.h +80 -86
- data/contrib/zstd/lib/common/compiler.h +225 -63
- data/contrib/zstd/lib/common/cpu.h +37 -1
- data/contrib/zstd/lib/common/debug.c +7 -1
- data/contrib/zstd/lib/common/debug.h +21 -12
- data/contrib/zstd/lib/common/entropy_common.c +15 -37
- data/contrib/zstd/lib/common/error_private.c +9 -2
- data/contrib/zstd/lib/common/error_private.h +93 -5
- data/contrib/zstd/lib/common/fse.h +12 -87
- data/contrib/zstd/lib/common/fse_decompress.c +37 -117
- data/contrib/zstd/lib/common/huf.h +97 -172
- data/contrib/zstd/lib/common/mem.h +58 -58
- data/contrib/zstd/lib/common/pool.c +38 -17
- data/contrib/zstd/lib/common/pool.h +10 -4
- data/contrib/zstd/lib/common/portability_macros.h +158 -0
- data/contrib/zstd/lib/common/threading.c +74 -14
- data/contrib/zstd/lib/common/threading.h +5 -10
- data/contrib/zstd/lib/common/xxhash.c +6 -814
- data/contrib/zstd/lib/common/xxhash.h +6930 -195
- data/contrib/zstd/lib/common/zstd_common.c +1 -36
- data/contrib/zstd/lib/common/zstd_deps.h +1 -1
- data/contrib/zstd/lib/common/zstd_internal.h +68 -154
- data/contrib/zstd/lib/common/zstd_trace.h +163 -0
- data/contrib/zstd/lib/compress/clevels.h +134 -0
- data/contrib/zstd/lib/compress/fse_compress.c +75 -155
- data/contrib/zstd/lib/compress/hist.c +1 -1
- data/contrib/zstd/lib/compress/hist.h +1 -1
- data/contrib/zstd/lib/compress/huf_compress.c +810 -259
- data/contrib/zstd/lib/compress/zstd_compress.c +2864 -919
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +523 -192
- data/contrib/zstd/lib/compress/zstd_compress_literals.c +117 -40
- data/contrib/zstd/lib/compress/zstd_compress_literals.h +16 -6
- data/contrib/zstd/lib/compress/zstd_compress_sequences.c +28 -19
- data/contrib/zstd/lib/compress/zstd_compress_sequences.h +1 -1
- data/contrib/zstd/lib/compress/zstd_compress_superblock.c +251 -412
- data/contrib/zstd/lib/compress/zstd_compress_superblock.h +1 -1
- data/contrib/zstd/lib/compress/zstd_cwksp.h +284 -97
- data/contrib/zstd/lib/compress/zstd_double_fast.c +382 -133
- data/contrib/zstd/lib/compress/zstd_double_fast.h +14 -2
- data/contrib/zstd/lib/compress/zstd_fast.c +732 -260
- data/contrib/zstd/lib/compress/zstd_fast.h +3 -2
- data/contrib/zstd/lib/compress/zstd_lazy.c +1177 -390
- data/contrib/zstd/lib/compress/zstd_lazy.h +129 -14
- data/contrib/zstd/lib/compress/zstd_ldm.c +280 -210
- data/contrib/zstd/lib/compress/zstd_ldm.h +3 -2
- data/contrib/zstd/lib/compress/zstd_ldm_geartab.h +106 -0
- data/contrib/zstd/lib/compress/zstd_opt.c +516 -285
- data/contrib/zstd/lib/compress/zstd_opt.h +32 -8
- data/contrib/zstd/lib/compress/zstdmt_compress.c +202 -131
- data/contrib/zstd/lib/compress/zstdmt_compress.h +9 -6
- data/contrib/zstd/lib/decompress/huf_decompress.c +1149 -555
- data/contrib/zstd/lib/decompress/huf_decompress_amd64.S +595 -0
- data/contrib/zstd/lib/decompress/zstd_ddict.c +4 -4
- data/contrib/zstd/lib/decompress/zstd_ddict.h +1 -1
- data/contrib/zstd/lib/decompress/zstd_decompress.c +583 -106
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1054 -379
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +14 -3
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +56 -6
- data/contrib/zstd/lib/deprecated/zbuff.h +1 -1
- data/contrib/zstd/lib/deprecated/zbuff_common.c +1 -1
- data/contrib/zstd/lib/deprecated/zbuff_compress.c +24 -4
- data/contrib/zstd/lib/deprecated/zbuff_decompress.c +3 -1
- data/contrib/zstd/lib/dictBuilder/cover.c +60 -44
- data/contrib/zstd/lib/dictBuilder/cover.h +6 -11
- data/contrib/zstd/lib/dictBuilder/divsufsort.c +1 -1
- data/contrib/zstd/lib/dictBuilder/fastcover.c +26 -18
- data/contrib/zstd/lib/dictBuilder/zdict.c +100 -101
- data/contrib/zstd/lib/legacy/zstd_legacy.h +38 -1
- data/contrib/zstd/lib/legacy/zstd_v01.c +18 -53
- data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v02.c +28 -85
- data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v03.c +29 -88
- data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v04.c +27 -80
- data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v05.c +36 -85
- data/contrib/zstd/lib/legacy/zstd_v05.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v06.c +44 -96
- data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v07.c +37 -92
- data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
- data/contrib/zstd/lib/libzstd.mk +237 -0
- data/contrib/zstd/lib/libzstd.pc.in +4 -3
- data/contrib/zstd/lib/module.modulemap +35 -0
- data/contrib/zstd/lib/{dictBuilder/zdict.h → zdict.h} +202 -33
- data/contrib/zstd/lib/zstd.h +1030 -332
- data/contrib/zstd/lib/{common/zstd_errors.h → zstd_errors.h} +27 -8
- data/ext/extconf.rb +26 -7
- data/ext/extzstd.c +51 -24
- data/ext/extzstd.h +33 -6
- data/ext/extzstd_stream.c +74 -31
- data/ext/libzstd_conf.h +0 -1
- data/ext/zstd_decompress_asm.S +1 -0
- metadata +17 -7
- data/contrib/zstd/appveyor.yml +0 -292
- data/ext/depend +0 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
#ifdef ZSTD_MULTITHREAD
|
|
24
24
|
# include "zstdmt_compress.h"
|
|
25
25
|
#endif
|
|
26
|
+
#include "../common/bits.h" /* ZSTD_highbit32, ZSTD_NbCommonBytes */
|
|
26
27
|
|
|
27
28
|
#if defined (__cplusplus)
|
|
28
29
|
extern "C" {
|
|
@@ -38,7 +39,7 @@ extern "C" {
|
|
|
38
39
|
It's not a big deal though : candidate will just be sorted again.
|
|
39
40
|
Additionally, candidate position 1 will be lost.
|
|
40
41
|
But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
|
|
41
|
-
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table
|
|
42
|
+
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table reuse with a different strategy.
|
|
42
43
|
This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
|
43
44
|
|
|
44
45
|
|
|
@@ -63,7 +64,7 @@ typedef struct {
|
|
|
63
64
|
} ZSTD_localDict;
|
|
64
65
|
|
|
65
66
|
typedef struct {
|
|
66
|
-
HUF_CElt CTable[
|
|
67
|
+
HUF_CElt CTable[HUF_CTABLE_SIZE_ST(255)];
|
|
67
68
|
HUF_repeat repeatMode;
|
|
68
69
|
} ZSTD_hufCTables_t;
|
|
69
70
|
|
|
@@ -81,8 +82,56 @@ typedef struct {
|
|
|
81
82
|
ZSTD_fseCTables_t fse;
|
|
82
83
|
} ZSTD_entropyCTables_t;
|
|
83
84
|
|
|
85
|
+
/***********************************************
|
|
86
|
+
* Entropy buffer statistics structs and funcs *
|
|
87
|
+
***********************************************/
|
|
88
|
+
/** ZSTD_hufCTablesMetadata_t :
|
|
89
|
+
* Stores Literals Block Type for a super-block in hType, and
|
|
90
|
+
* huffman tree description in hufDesBuffer.
|
|
91
|
+
* hufDesSize refers to the size of huffman tree description in bytes.
|
|
92
|
+
* This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */
|
|
84
93
|
typedef struct {
|
|
85
|
-
|
|
94
|
+
symbolEncodingType_e hType;
|
|
95
|
+
BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
|
|
96
|
+
size_t hufDesSize;
|
|
97
|
+
} ZSTD_hufCTablesMetadata_t;
|
|
98
|
+
|
|
99
|
+
/** ZSTD_fseCTablesMetadata_t :
|
|
100
|
+
* Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
|
|
101
|
+
* fse tables in fseTablesBuffer.
|
|
102
|
+
* fseTablesSize refers to the size of fse tables in bytes.
|
|
103
|
+
* This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */
|
|
104
|
+
typedef struct {
|
|
105
|
+
symbolEncodingType_e llType;
|
|
106
|
+
symbolEncodingType_e ofType;
|
|
107
|
+
symbolEncodingType_e mlType;
|
|
108
|
+
BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
|
|
109
|
+
size_t fseTablesSize;
|
|
110
|
+
size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */
|
|
111
|
+
} ZSTD_fseCTablesMetadata_t;
|
|
112
|
+
|
|
113
|
+
typedef struct {
|
|
114
|
+
ZSTD_hufCTablesMetadata_t hufMetadata;
|
|
115
|
+
ZSTD_fseCTablesMetadata_t fseMetadata;
|
|
116
|
+
} ZSTD_entropyCTablesMetadata_t;
|
|
117
|
+
|
|
118
|
+
/** ZSTD_buildBlockEntropyStats() :
|
|
119
|
+
* Builds entropy for the block.
|
|
120
|
+
* @return : 0 on success or error code */
|
|
121
|
+
size_t ZSTD_buildBlockEntropyStats(
|
|
122
|
+
const seqStore_t* seqStorePtr,
|
|
123
|
+
const ZSTD_entropyCTables_t* prevEntropy,
|
|
124
|
+
ZSTD_entropyCTables_t* nextEntropy,
|
|
125
|
+
const ZSTD_CCtx_params* cctxParams,
|
|
126
|
+
ZSTD_entropyCTablesMetadata_t* entropyMetadata,
|
|
127
|
+
void* workspace, size_t wkspSize);
|
|
128
|
+
|
|
129
|
+
/*********************************
|
|
130
|
+
* Compression internals structs *
|
|
131
|
+
*********************************/
|
|
132
|
+
|
|
133
|
+
typedef struct {
|
|
134
|
+
U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */
|
|
86
135
|
U32 len; /* Raw length of match */
|
|
87
136
|
} ZSTD_match_t;
|
|
88
137
|
|
|
@@ -101,26 +150,33 @@ typedef struct {
|
|
|
101
150
|
size_t capacity; /* The capacity starting from `seq` pointer */
|
|
102
151
|
} rawSeqStore_t;
|
|
103
152
|
|
|
153
|
+
typedef struct {
|
|
154
|
+
U32 idx; /* Index in array of ZSTD_Sequence */
|
|
155
|
+
U32 posInSequence; /* Position within sequence at idx */
|
|
156
|
+
size_t posInSrc; /* Number of bytes given by sequences provided so far */
|
|
157
|
+
} ZSTD_sequencePosition;
|
|
158
|
+
|
|
104
159
|
UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
|
|
105
160
|
|
|
106
161
|
typedef struct {
|
|
107
|
-
int price;
|
|
108
|
-
U32 off;
|
|
109
|
-
U32 mlen;
|
|
110
|
-
U32 litlen;
|
|
111
|
-
U32 rep[ZSTD_REP_NUM];
|
|
162
|
+
int price; /* price from beginning of segment to this position */
|
|
163
|
+
U32 off; /* offset of previous match */
|
|
164
|
+
U32 mlen; /* length of previous match */
|
|
165
|
+
U32 litlen; /* nb of literals since previous match */
|
|
166
|
+
U32 rep[ZSTD_REP_NUM]; /* offset history after previous match */
|
|
112
167
|
} ZSTD_optimal_t;
|
|
113
168
|
|
|
114
169
|
typedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;
|
|
115
170
|
|
|
171
|
+
#define ZSTD_OPT_SIZE (ZSTD_OPT_NUM+3)
|
|
116
172
|
typedef struct {
|
|
117
173
|
/* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */
|
|
118
174
|
unsigned* litFreq; /* table of literals statistics, of size 256 */
|
|
119
175
|
unsigned* litLengthFreq; /* table of litLength statistics, of size (MaxLL+1) */
|
|
120
176
|
unsigned* matchLengthFreq; /* table of matchLength statistics, of size (MaxML+1) */
|
|
121
177
|
unsigned* offCodeFreq; /* table of offCode statistics, of size (MaxOff+1) */
|
|
122
|
-
ZSTD_match_t* matchTable; /* list of found matches, of size
|
|
123
|
-
ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size
|
|
178
|
+
ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_SIZE */
|
|
179
|
+
ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_SIZE */
|
|
124
180
|
|
|
125
181
|
U32 litSum; /* nb of literals */
|
|
126
182
|
U32 litLengthSum; /* nb of litLength codes */
|
|
@@ -132,7 +188,7 @@ typedef struct {
|
|
|
132
188
|
U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
|
|
133
189
|
ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
|
|
134
190
|
const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
|
|
135
|
-
|
|
191
|
+
ZSTD_paramSwitch_e literalCompressionMode;
|
|
136
192
|
} optState_t;
|
|
137
193
|
|
|
138
194
|
typedef struct {
|
|
@@ -141,14 +197,23 @@ typedef struct {
|
|
|
141
197
|
} ZSTD_compressedBlockState_t;
|
|
142
198
|
|
|
143
199
|
typedef struct {
|
|
144
|
-
BYTE const* nextSrc;
|
|
145
|
-
BYTE const* base;
|
|
146
|
-
BYTE const* dictBase;
|
|
147
|
-
U32 dictLimit;
|
|
148
|
-
U32 lowLimit;
|
|
200
|
+
BYTE const* nextSrc; /* next block here to continue on current prefix */
|
|
201
|
+
BYTE const* base; /* All regular indexes relative to this position */
|
|
202
|
+
BYTE const* dictBase; /* extDict indexes relative to this position */
|
|
203
|
+
U32 dictLimit; /* below that point, need extDict */
|
|
204
|
+
U32 lowLimit; /* below that point, no more valid data */
|
|
205
|
+
U32 nbOverflowCorrections; /* Number of times overflow correction has run since
|
|
206
|
+
* ZSTD_window_init(). Useful for debugging coredumps
|
|
207
|
+
* and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY.
|
|
208
|
+
*/
|
|
149
209
|
} ZSTD_window_t;
|
|
150
210
|
|
|
211
|
+
#define ZSTD_WINDOW_START_INDEX 2
|
|
212
|
+
|
|
151
213
|
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
|
|
214
|
+
|
|
215
|
+
#define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */
|
|
216
|
+
|
|
152
217
|
struct ZSTD_matchState_t {
|
|
153
218
|
ZSTD_window_t window; /* State for window round buffer management */
|
|
154
219
|
U32 loadedDictEnd; /* index of end of dictionary, within context's referential.
|
|
@@ -160,9 +225,19 @@ struct ZSTD_matchState_t {
|
|
|
160
225
|
*/
|
|
161
226
|
U32 nextToUpdate; /* index from which to continue table update */
|
|
162
227
|
U32 hashLog3; /* dispatch table for matches of len==3 : larger == faster, more memory */
|
|
228
|
+
|
|
229
|
+
U32 rowHashLog; /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/
|
|
230
|
+
BYTE* tagTable; /* For row-based matchFinder: A row-based table containing the hashes and head index. */
|
|
231
|
+
U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */
|
|
232
|
+
U64 hashSalt; /* For row-based matchFinder: salts the hash for reuse of tag table */
|
|
233
|
+
U32 hashSaltEntropy; /* For row-based matchFinder: collects entropy for salt generation */
|
|
234
|
+
|
|
163
235
|
U32* hashTable;
|
|
164
236
|
U32* hashTable3;
|
|
165
237
|
U32* chainTable;
|
|
238
|
+
|
|
239
|
+
U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */
|
|
240
|
+
|
|
166
241
|
int dedicatedDictSearch; /* Indicates whether this matchState is using the
|
|
167
242
|
* dedicated dictionary search structure.
|
|
168
243
|
*/
|
|
@@ -170,6 +245,18 @@ struct ZSTD_matchState_t {
|
|
|
170
245
|
const ZSTD_matchState_t* dictMatchState;
|
|
171
246
|
ZSTD_compressionParameters cParams;
|
|
172
247
|
const rawSeqStore_t* ldmSeqStore;
|
|
248
|
+
|
|
249
|
+
/* Controls prefetching in some dictMatchState matchfinders.
|
|
250
|
+
* This behavior is controlled from the cctx ms.
|
|
251
|
+
* This parameter has no effect in the cdict ms. */
|
|
252
|
+
int prefetchCDictTables;
|
|
253
|
+
|
|
254
|
+
/* When == 0, lazy match finders insert every position.
|
|
255
|
+
* When != 0, lazy match finders only insert positions they search.
|
|
256
|
+
* This allows them to skip much faster over incompressible data,
|
|
257
|
+
* at a small cost to compression ratio.
|
|
258
|
+
*/
|
|
259
|
+
int lazySkipping;
|
|
173
260
|
};
|
|
174
261
|
|
|
175
262
|
typedef struct {
|
|
@@ -183,17 +270,26 @@ typedef struct {
|
|
|
183
270
|
U32 checksum;
|
|
184
271
|
} ldmEntry_t;
|
|
185
272
|
|
|
273
|
+
typedef struct {
|
|
274
|
+
BYTE const* split;
|
|
275
|
+
U32 hash;
|
|
276
|
+
U32 checksum;
|
|
277
|
+
ldmEntry_t* bucket;
|
|
278
|
+
} ldmMatchCandidate_t;
|
|
279
|
+
|
|
280
|
+
#define LDM_BATCH_SIZE 64
|
|
281
|
+
|
|
186
282
|
typedef struct {
|
|
187
283
|
ZSTD_window_t window; /* State for the window round buffer management */
|
|
188
284
|
ldmEntry_t* hashTable;
|
|
189
285
|
U32 loadedDictEnd;
|
|
190
286
|
BYTE* bucketOffsets; /* Next position in bucket to insert entry */
|
|
191
|
-
|
|
192
|
-
|
|
287
|
+
size_t splitIndices[LDM_BATCH_SIZE];
|
|
288
|
+
ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE];
|
|
193
289
|
} ldmState_t;
|
|
194
290
|
|
|
195
291
|
typedef struct {
|
|
196
|
-
|
|
292
|
+
ZSTD_paramSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */
|
|
197
293
|
U32 hashLog; /* Log size of hashTable */
|
|
198
294
|
U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
|
|
199
295
|
U32 minMatchLength; /* Minimum match length */
|
|
@@ -224,7 +320,7 @@ struct ZSTD_CCtx_params_s {
|
|
|
224
320
|
* There is no guarantee that hint is close to actual source size */
|
|
225
321
|
|
|
226
322
|
ZSTD_dictAttachPref_e attachDictPref;
|
|
227
|
-
|
|
323
|
+
ZSTD_paramSwitch_e literalCompressionMode;
|
|
228
324
|
|
|
229
325
|
/* Multithreading: used to pass parameters to mtctx */
|
|
230
326
|
int nbWorkers;
|
|
@@ -246,8 +342,36 @@ struct ZSTD_CCtx_params_s {
|
|
|
246
342
|
ZSTD_sequenceFormat_e blockDelimiters;
|
|
247
343
|
int validateSequences;
|
|
248
344
|
|
|
345
|
+
/* Block splitting */
|
|
346
|
+
ZSTD_paramSwitch_e useBlockSplitter;
|
|
347
|
+
|
|
348
|
+
/* Param for deciding whether to use row-based matchfinder */
|
|
349
|
+
ZSTD_paramSwitch_e useRowMatchFinder;
|
|
350
|
+
|
|
351
|
+
/* Always load a dictionary in ext-dict mode (not prefix mode)? */
|
|
352
|
+
int deterministicRefPrefix;
|
|
353
|
+
|
|
249
354
|
/* Internal use, for createCCtxParams() and freeCCtxParams() only */
|
|
250
355
|
ZSTD_customMem customMem;
|
|
356
|
+
|
|
357
|
+
/* Controls prefetching in some dictMatchState matchfinders */
|
|
358
|
+
ZSTD_paramSwitch_e prefetchCDictTables;
|
|
359
|
+
|
|
360
|
+
/* Controls whether zstd will fall back to an internal matchfinder
|
|
361
|
+
* if the external matchfinder returns an error code. */
|
|
362
|
+
int enableMatchFinderFallback;
|
|
363
|
+
|
|
364
|
+
/* Parameters for the external sequence producer API.
|
|
365
|
+
* Users set these parameters through ZSTD_registerSequenceProducer().
|
|
366
|
+
* It is not possible to set these parameters individually through the public API. */
|
|
367
|
+
void* extSeqProdState;
|
|
368
|
+
ZSTD_sequenceProducer_F extSeqProdFunc;
|
|
369
|
+
|
|
370
|
+
/* Adjust the max block size*/
|
|
371
|
+
size_t maxBlockSize;
|
|
372
|
+
|
|
373
|
+
/* Controls repcode search in external sequence parsing */
|
|
374
|
+
ZSTD_paramSwitch_e searchForExternalRepcodes;
|
|
251
375
|
}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
|
|
252
376
|
|
|
253
377
|
#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))
|
|
@@ -263,13 +387,31 @@ typedef enum {
|
|
|
263
387
|
ZSTDb_buffered
|
|
264
388
|
} ZSTD_buffered_policy_e;
|
|
265
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Struct that contains all elements of block splitter that should be allocated
|
|
392
|
+
* in a wksp.
|
|
393
|
+
*/
|
|
394
|
+
#define ZSTD_MAX_NB_BLOCK_SPLITS 196
|
|
395
|
+
typedef struct {
|
|
396
|
+
seqStore_t fullSeqStoreChunk;
|
|
397
|
+
seqStore_t firstHalfSeqStore;
|
|
398
|
+
seqStore_t secondHalfSeqStore;
|
|
399
|
+
seqStore_t currSeqStore;
|
|
400
|
+
seqStore_t nextSeqStore;
|
|
401
|
+
|
|
402
|
+
U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS];
|
|
403
|
+
ZSTD_entropyCTablesMetadata_t entropyMetadata;
|
|
404
|
+
} ZSTD_blockSplitCtx;
|
|
405
|
+
|
|
266
406
|
struct ZSTD_CCtx_s {
|
|
267
407
|
ZSTD_compressionStage_e stage;
|
|
268
408
|
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. */
|
|
269
409
|
int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
|
|
270
410
|
ZSTD_CCtx_params requestedParams;
|
|
271
411
|
ZSTD_CCtx_params appliedParams;
|
|
412
|
+
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. */
|
|
272
413
|
U32 dictID;
|
|
414
|
+
size_t dictContentSize;
|
|
273
415
|
|
|
274
416
|
ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */
|
|
275
417
|
size_t blockSize;
|
|
@@ -292,7 +434,7 @@ struct ZSTD_CCtx_s {
|
|
|
292
434
|
ZSTD_blockState_t blockState;
|
|
293
435
|
U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */
|
|
294
436
|
|
|
295
|
-
/*
|
|
437
|
+
/* Whether we are streaming or not */
|
|
296
438
|
ZSTD_buffered_policy_e bufferedPolicy;
|
|
297
439
|
|
|
298
440
|
/* streaming */
|
|
@@ -310,6 +452,7 @@ struct ZSTD_CCtx_s {
|
|
|
310
452
|
|
|
311
453
|
/* Stable in/out buffer verification */
|
|
312
454
|
ZSTD_inBuffer expectedInBuffer;
|
|
455
|
+
size_t stableIn_notConsumed; /* nb bytes within stable input buffer that are said to be consumed but are not */
|
|
313
456
|
size_t expectedOutBufferSize;
|
|
314
457
|
|
|
315
458
|
/* Dictionary */
|
|
@@ -321,9 +464,22 @@ struct ZSTD_CCtx_s {
|
|
|
321
464
|
#ifdef ZSTD_MULTITHREAD
|
|
322
465
|
ZSTDMT_CCtx* mtctx;
|
|
323
466
|
#endif
|
|
467
|
+
|
|
468
|
+
/* Tracing */
|
|
469
|
+
#if ZSTD_TRACE
|
|
470
|
+
ZSTD_TraceCtx traceCtx;
|
|
471
|
+
#endif
|
|
472
|
+
|
|
473
|
+
/* Workspace for block splitter */
|
|
474
|
+
ZSTD_blockSplitCtx blockSplitCtx;
|
|
475
|
+
|
|
476
|
+
/* Buffer for output from external sequence producer */
|
|
477
|
+
ZSTD_Sequence* extSeqBuf;
|
|
478
|
+
size_t extSeqBufCapacity;
|
|
324
479
|
};
|
|
325
480
|
|
|
326
481
|
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
|
|
482
|
+
typedef enum { ZSTD_tfp_forCCtx, ZSTD_tfp_forCDict } ZSTD_tableFillPurpose_e;
|
|
327
483
|
|
|
328
484
|
typedef enum {
|
|
329
485
|
ZSTD_noDict = 0,
|
|
@@ -345,7 +501,7 @@ typedef enum {
|
|
|
345
501
|
* In this mode we take both the source size and the dictionary size
|
|
346
502
|
* into account when selecting and adjusting the parameters.
|
|
347
503
|
*/
|
|
348
|
-
ZSTD_cpm_unknown = 3
|
|
504
|
+
ZSTD_cpm_unknown = 3 /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.
|
|
349
505
|
* We don't know what these parameters are for. We default to the legacy
|
|
350
506
|
* behavior of taking both the source size and the dict size into account
|
|
351
507
|
* when selecting and adjusting parameters.
|
|
@@ -355,7 +511,7 @@ typedef enum {
|
|
|
355
511
|
typedef size_t (*ZSTD_blockCompressor) (
|
|
356
512
|
ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
357
513
|
void const* src, size_t srcSize);
|
|
358
|
-
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode);
|
|
514
|
+
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
|
|
359
515
|
|
|
360
516
|
|
|
361
517
|
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
|
|
@@ -389,31 +545,6 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
|
|
|
389
545
|
return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];
|
|
390
546
|
}
|
|
391
547
|
|
|
392
|
-
typedef struct repcodes_s {
|
|
393
|
-
U32 rep[3];
|
|
394
|
-
} repcodes_t;
|
|
395
|
-
|
|
396
|
-
MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
|
|
397
|
-
{
|
|
398
|
-
repcodes_t newReps;
|
|
399
|
-
if (offset >= ZSTD_REP_NUM) { /* full offset */
|
|
400
|
-
newReps.rep[2] = rep[1];
|
|
401
|
-
newReps.rep[1] = rep[0];
|
|
402
|
-
newReps.rep[0] = offset - ZSTD_REP_MOVE;
|
|
403
|
-
} else { /* repcode */
|
|
404
|
-
U32 const repCode = offset + ll0;
|
|
405
|
-
if (repCode > 0) { /* note : if repCode==0, no change */
|
|
406
|
-
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
|
407
|
-
newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
|
|
408
|
-
newReps.rep[1] = rep[0];
|
|
409
|
-
newReps.rep[0] = currentOffset;
|
|
410
|
-
} else { /* repCode == 0 */
|
|
411
|
-
ZSTD_memcpy(&newReps, rep, sizeof(newReps));
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
return newReps;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
548
|
/* ZSTD_cParam_withinBounds:
|
|
418
549
|
* @return 1 if value is within cParam bounds,
|
|
419
550
|
* 0 otherwise */
|
|
@@ -429,9 +560,11 @@ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
|
|
|
429
560
|
/* ZSTD_noCompressBlock() :
|
|
430
561
|
* Writes uncompressed block to dst buffer from given src.
|
|
431
562
|
* Returns the size of the block */
|
|
432
|
-
MEM_STATIC size_t
|
|
563
|
+
MEM_STATIC size_t
|
|
564
|
+
ZSTD_noCompressBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
|
|
433
565
|
{
|
|
434
566
|
U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
|
|
567
|
+
DEBUGLOG(5, "ZSTD_noCompressBlock (srcSize=%zu, dstCapacity=%zu)", srcSize, dstCapacity);
|
|
435
568
|
RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
|
|
436
569
|
dstSize_tooSmall, "dst buf too small for uncompressed block");
|
|
437
570
|
MEM_writeLE24(dst, cBlockHeader24);
|
|
@@ -439,7 +572,8 @@ MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const voi
|
|
|
439
572
|
return ZSTD_blockHeaderSize + srcSize;
|
|
440
573
|
}
|
|
441
574
|
|
|
442
|
-
MEM_STATIC size_t
|
|
575
|
+
MEM_STATIC size_t
|
|
576
|
+
ZSTD_rleCompressBlock(void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock)
|
|
443
577
|
{
|
|
444
578
|
BYTE* const op = (BYTE*)dst;
|
|
445
579
|
U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3);
|
|
@@ -458,21 +592,21 @@ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
|
|
|
458
592
|
{
|
|
459
593
|
U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
|
|
460
594
|
ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
|
|
461
|
-
assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
|
|
595
|
+
assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat));
|
|
462
596
|
return (srcSize >> minlog) + 2;
|
|
463
597
|
}
|
|
464
598
|
|
|
465
|
-
MEM_STATIC int
|
|
599
|
+
MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams)
|
|
466
600
|
{
|
|
467
601
|
switch (cctxParams->literalCompressionMode) {
|
|
468
|
-
case
|
|
602
|
+
case ZSTD_ps_enable:
|
|
469
603
|
return 0;
|
|
470
|
-
case
|
|
604
|
+
case ZSTD_ps_disable:
|
|
471
605
|
return 1;
|
|
472
606
|
default:
|
|
473
607
|
assert(0 /* impossible: pre-validated */);
|
|
474
|
-
|
|
475
|
-
case
|
|
608
|
+
ZSTD_FALLTHROUGH;
|
|
609
|
+
case ZSTD_ps_auto:
|
|
476
610
|
return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
|
|
477
611
|
}
|
|
478
612
|
}
|
|
@@ -482,7 +616,9 @@ MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParam
|
|
|
482
616
|
* Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single
|
|
483
617
|
* large copies.
|
|
484
618
|
*/
|
|
485
|
-
static void
|
|
619
|
+
static void
|
|
620
|
+
ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w)
|
|
621
|
+
{
|
|
486
622
|
assert(iend > ilimit_w);
|
|
487
623
|
if (ip <= ilimit_w) {
|
|
488
624
|
ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
|
|
@@ -492,14 +628,28 @@ static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const ie
|
|
|
492
628
|
while (ip < iend) *op++ = *ip++;
|
|
493
629
|
}
|
|
494
630
|
|
|
631
|
+
|
|
632
|
+
#define REPCODE1_TO_OFFBASE REPCODE_TO_OFFBASE(1)
|
|
633
|
+
#define REPCODE2_TO_OFFBASE REPCODE_TO_OFFBASE(2)
|
|
634
|
+
#define REPCODE3_TO_OFFBASE REPCODE_TO_OFFBASE(3)
|
|
635
|
+
#define REPCODE_TO_OFFBASE(r) (assert((r)>=1), assert((r)<=ZSTD_REP_NUM), (r)) /* accepts IDs 1,2,3 */
|
|
636
|
+
#define OFFSET_TO_OFFBASE(o) (assert((o)>0), o + ZSTD_REP_NUM)
|
|
637
|
+
#define OFFBASE_IS_OFFSET(o) ((o) > ZSTD_REP_NUM)
|
|
638
|
+
#define OFFBASE_IS_REPCODE(o) ( 1 <= (o) && (o) <= ZSTD_REP_NUM)
|
|
639
|
+
#define OFFBASE_TO_OFFSET(o) (assert(OFFBASE_IS_OFFSET(o)), (o) - ZSTD_REP_NUM)
|
|
640
|
+
#define OFFBASE_TO_REPCODE(o) (assert(OFFBASE_IS_REPCODE(o)), (o)) /* returns ID 1,2,3 */
|
|
641
|
+
|
|
495
642
|
/*! ZSTD_storeSeq() :
|
|
496
|
-
* Store a sequence (litlen, litPtr,
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* Allowed to
|
|
643
|
+
* Store a sequence (litlen, litPtr, offBase and matchLength) into seqStore_t.
|
|
644
|
+
* @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE().
|
|
645
|
+
* @matchLength : must be >= MINMATCH
|
|
646
|
+
* Allowed to over-read literals up to litLimit.
|
|
500
647
|
*/
|
|
501
|
-
HINT_INLINE UNUSED_ATTR
|
|
502
|
-
|
|
648
|
+
HINT_INLINE UNUSED_ATTR void
|
|
649
|
+
ZSTD_storeSeq(seqStore_t* seqStorePtr,
|
|
650
|
+
size_t litLength, const BYTE* literals, const BYTE* litLimit,
|
|
651
|
+
U32 offBase,
|
|
652
|
+
size_t matchLength)
|
|
503
653
|
{
|
|
504
654
|
BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;
|
|
505
655
|
BYTE const* const litEnd = literals + litLength;
|
|
@@ -507,8 +657,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
|
|
|
507
657
|
static const BYTE* g_start = NULL;
|
|
508
658
|
if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */
|
|
509
659
|
{ U32 const pos = (U32)((const BYTE*)literals - g_start);
|
|
510
|
-
DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at
|
|
511
|
-
pos, (U32)litLength, (U32)
|
|
660
|
+
DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offBase%7u",
|
|
661
|
+
pos, (U32)litLength, (U32)matchLength, (U32)offBase);
|
|
512
662
|
}
|
|
513
663
|
#endif
|
|
514
664
|
assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
|
|
@@ -518,9 +668,9 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
|
|
|
518
668
|
assert(literals + litLength <= litLimit);
|
|
519
669
|
if (litEnd <= litLimit_w) {
|
|
520
670
|
/* Common case we can use wildcopy.
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
671
|
+
* First copy 16 bytes, because literals are likely short.
|
|
672
|
+
*/
|
|
673
|
+
ZSTD_STATIC_ASSERT(WILDCOPY_OVERLENGTH >= 16);
|
|
524
674
|
ZSTD_copy16(seqStorePtr->lit, literals);
|
|
525
675
|
if (litLength > 16) {
|
|
526
676
|
ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, (ptrdiff_t)litLength-16, ZSTD_no_overlap);
|
|
@@ -532,103 +682,70 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
|
|
|
532
682
|
|
|
533
683
|
/* literal Length */
|
|
534
684
|
if (litLength>0xFFFF) {
|
|
535
|
-
assert(seqStorePtr->
|
|
536
|
-
seqStorePtr->
|
|
685
|
+
assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
|
|
686
|
+
seqStorePtr->longLengthType = ZSTD_llt_literalLength;
|
|
537
687
|
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
|
538
688
|
}
|
|
539
689
|
seqStorePtr->sequences[0].litLength = (U16)litLength;
|
|
540
690
|
|
|
541
691
|
/* match offset */
|
|
542
|
-
seqStorePtr->sequences[0].
|
|
692
|
+
seqStorePtr->sequences[0].offBase = offBase;
|
|
543
693
|
|
|
544
694
|
/* match Length */
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
695
|
+
assert(matchLength >= MINMATCH);
|
|
696
|
+
{ size_t const mlBase = matchLength - MINMATCH;
|
|
697
|
+
if (mlBase>0xFFFF) {
|
|
698
|
+
assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
|
|
699
|
+
seqStorePtr->longLengthType = ZSTD_llt_matchLength;
|
|
700
|
+
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
|
701
|
+
}
|
|
702
|
+
seqStorePtr->sequences[0].mlBase = (U16)mlBase;
|
|
549
703
|
}
|
|
550
|
-
seqStorePtr->sequences[0].matchLength = (U16)mlBase;
|
|
551
704
|
|
|
552
705
|
seqStorePtr->sequences++;
|
|
553
706
|
}
|
|
554
707
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
*
|
|
558
|
-
|
|
559
|
-
|
|
708
|
+
/* ZSTD_updateRep() :
|
|
709
|
+
* updates in-place @rep (array of repeat offsets)
|
|
710
|
+
* @offBase : sum-type, using numeric representation of ZSTD_storeSeq()
|
|
711
|
+
*/
|
|
712
|
+
MEM_STATIC void
|
|
713
|
+
ZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0)
|
|
560
714
|
{
|
|
561
|
-
if (
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
0, 3, 1, 3, 1, 4, 2, 7,
|
|
575
|
-
0, 2, 3, 6, 1, 5, 3, 5,
|
|
576
|
-
1, 3, 4, 4, 2, 5, 6, 7,
|
|
577
|
-
7, 0, 1, 2, 3, 3, 4, 6,
|
|
578
|
-
2, 6, 5, 5, 3, 4, 5, 6,
|
|
579
|
-
7, 1, 2, 4, 6, 4, 4, 5,
|
|
580
|
-
7, 2, 6, 5, 7, 6, 7, 7 };
|
|
581
|
-
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
|
|
582
|
-
# endif
|
|
583
|
-
} else { /* 32 bits */
|
|
584
|
-
# if defined(_MSC_VER)
|
|
585
|
-
unsigned long r=0;
|
|
586
|
-
return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0;
|
|
587
|
-
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
|
588
|
-
return (__builtin_ctz((U32)val) >> 3);
|
|
589
|
-
# else
|
|
590
|
-
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
|
|
591
|
-
3, 2, 2, 1, 3, 2, 0, 1,
|
|
592
|
-
3, 3, 1, 2, 2, 2, 2, 0,
|
|
593
|
-
3, 1, 2, 0, 1, 0, 1, 1 };
|
|
594
|
-
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
|
|
595
|
-
# endif
|
|
715
|
+
if (OFFBASE_IS_OFFSET(offBase)) { /* full offset */
|
|
716
|
+
rep[2] = rep[1];
|
|
717
|
+
rep[1] = rep[0];
|
|
718
|
+
rep[0] = OFFBASE_TO_OFFSET(offBase);
|
|
719
|
+
} else { /* repcode */
|
|
720
|
+
U32 const repCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0;
|
|
721
|
+
if (repCode > 0) { /* note : if repCode==0, no change */
|
|
722
|
+
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
|
723
|
+
rep[2] = (repCode >= 2) ? rep[1] : rep[2];
|
|
724
|
+
rep[1] = rep[0];
|
|
725
|
+
rep[0] = currentOffset;
|
|
726
|
+
} else { /* repCode == 0 */
|
|
727
|
+
/* nothing to do */
|
|
596
728
|
}
|
|
597
|
-
}
|
|
598
|
-
if (MEM_64bits()) {
|
|
599
|
-
# if defined(_MSC_VER) && defined(_WIN64)
|
|
600
|
-
# if STATIC_BMI2
|
|
601
|
-
return _lzcnt_u64(val) >> 3;
|
|
602
|
-
# else
|
|
603
|
-
unsigned long r = 0;
|
|
604
|
-
return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0;
|
|
605
|
-
# endif
|
|
606
|
-
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
|
607
|
-
return (__builtin_clzll(val) >> 3);
|
|
608
|
-
# else
|
|
609
|
-
unsigned r;
|
|
610
|
-
const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
|
|
611
|
-
if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
|
|
612
|
-
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
|
613
|
-
r += (!val);
|
|
614
|
-
return r;
|
|
615
|
-
# endif
|
|
616
|
-
} else { /* 32 bits */
|
|
617
|
-
# if defined(_MSC_VER)
|
|
618
|
-
unsigned long r = 0;
|
|
619
|
-
return _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0;
|
|
620
|
-
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
|
621
|
-
return (__builtin_clz((U32)val) >> 3);
|
|
622
|
-
# else
|
|
623
|
-
unsigned r;
|
|
624
|
-
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
|
|
625
|
-
r += (!val);
|
|
626
|
-
return r;
|
|
627
|
-
# endif
|
|
628
|
-
} }
|
|
729
|
+
}
|
|
629
730
|
}
|
|
630
731
|
|
|
732
|
+
typedef struct repcodes_s {
|
|
733
|
+
U32 rep[3];
|
|
734
|
+
} repcodes_t;
|
|
631
735
|
|
|
736
|
+
MEM_STATIC repcodes_t
|
|
737
|
+
ZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0)
|
|
738
|
+
{
|
|
739
|
+
repcodes_t newReps;
|
|
740
|
+
ZSTD_memcpy(&newReps, rep, sizeof(newReps));
|
|
741
|
+
ZSTD_updateRep(newReps.rep, offBase, ll0);
|
|
742
|
+
return newReps;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
/*-*************************************
|
|
747
|
+
* Match length counter
|
|
748
|
+
***************************************/
|
|
632
749
|
MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
|
|
633
750
|
{
|
|
634
751
|
const BYTE* const pStart = pIn;
|
|
@@ -674,32 +791,43 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match,
|
|
|
674
791
|
* Hashes
|
|
675
792
|
***************************************/
|
|
676
793
|
static const U32 prime3bytes = 506832829U;
|
|
677
|
-
static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
|
|
678
|
-
MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
|
|
794
|
+
static U32 ZSTD_hash3(U32 u, U32 h, U32 s) { assert(h <= 32); return (((u << (32-24)) * prime3bytes) ^ s) >> (32-h) ; }
|
|
795
|
+
MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h, 0); } /* only in zstd_opt.h */
|
|
796
|
+
MEM_STATIC size_t ZSTD_hash3PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash3(MEM_readLE32(ptr), h, s); }
|
|
679
797
|
|
|
680
798
|
static const U32 prime4bytes = 2654435761U;
|
|
681
|
-
static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
|
|
682
|
-
static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(
|
|
799
|
+
static U32 ZSTD_hash4(U32 u, U32 h, U32 s) { assert(h <= 32); return ((u * prime4bytes) ^ s) >> (32-h) ; }
|
|
800
|
+
static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_readLE32(ptr), h, 0); }
|
|
801
|
+
static size_t ZSTD_hash4PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash4(MEM_readLE32(ptr), h, s); }
|
|
683
802
|
|
|
684
803
|
static const U64 prime5bytes = 889523592379ULL;
|
|
685
|
-
static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
|
|
686
|
-
static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
|
|
804
|
+
static size_t ZSTD_hash5(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u << (64-40)) * prime5bytes) ^ s) >> (64-h)) ; }
|
|
805
|
+
static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h, 0); }
|
|
806
|
+
static size_t ZSTD_hash5PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash5(MEM_readLE64(p), h, s); }
|
|
687
807
|
|
|
688
808
|
static const U64 prime6bytes = 227718039650203ULL;
|
|
689
|
-
static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
|
|
690
|
-
static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
|
|
809
|
+
static size_t ZSTD_hash6(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u << (64-48)) * prime6bytes) ^ s) >> (64-h)) ; }
|
|
810
|
+
static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h, 0); }
|
|
811
|
+
static size_t ZSTD_hash6PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash6(MEM_readLE64(p), h, s); }
|
|
691
812
|
|
|
692
813
|
static const U64 prime7bytes = 58295818150454627ULL;
|
|
693
|
-
static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
|
|
694
|
-
static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
|
|
814
|
+
static size_t ZSTD_hash7(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u << (64-56)) * prime7bytes) ^ s) >> (64-h)) ; }
|
|
815
|
+
static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h, 0); }
|
|
816
|
+
static size_t ZSTD_hash7PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash7(MEM_readLE64(p), h, s); }
|
|
695
817
|
|
|
696
818
|
static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
|
|
697
|
-
static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
|
|
698
|
-
static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
|
|
819
|
+
static size_t ZSTD_hash8(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u) * prime8bytes) ^ s) >> (64-h)) ; }
|
|
820
|
+
static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h, 0); }
|
|
821
|
+
static size_t ZSTD_hash8PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash8(MEM_readLE64(p), h, s); }
|
|
822
|
+
|
|
699
823
|
|
|
700
824
|
MEM_STATIC FORCE_INLINE_ATTR
|
|
701
825
|
size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
|
|
702
826
|
{
|
|
827
|
+
/* Although some of these hashes do support hBits up to 64, some do not.
|
|
828
|
+
* To be on the safe side, always avoid hBits > 32. */
|
|
829
|
+
assert(hBits <= 32);
|
|
830
|
+
|
|
703
831
|
switch(mls)
|
|
704
832
|
{
|
|
705
833
|
default:
|
|
@@ -711,6 +839,24 @@ size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
|
|
|
711
839
|
}
|
|
712
840
|
}
|
|
713
841
|
|
|
842
|
+
MEM_STATIC FORCE_INLINE_ATTR
|
|
843
|
+
size_t ZSTD_hashPtrSalted(const void* p, U32 hBits, U32 mls, const U64 hashSalt) {
|
|
844
|
+
/* Although some of these hashes do support hBits up to 64, some do not.
|
|
845
|
+
* To be on the safe side, always avoid hBits > 32. */
|
|
846
|
+
assert(hBits <= 32);
|
|
847
|
+
|
|
848
|
+
switch(mls)
|
|
849
|
+
{
|
|
850
|
+
default:
|
|
851
|
+
case 4: return ZSTD_hash4PtrS(p, hBits, (U32)hashSalt);
|
|
852
|
+
case 5: return ZSTD_hash5PtrS(p, hBits, hashSalt);
|
|
853
|
+
case 6: return ZSTD_hash6PtrS(p, hBits, hashSalt);
|
|
854
|
+
case 7: return ZSTD_hash7PtrS(p, hBits, hashSalt);
|
|
855
|
+
case 8: return ZSTD_hash8PtrS(p, hBits, hashSalt);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
|
|
714
860
|
/** ZSTD_ipow() :
|
|
715
861
|
* Return base^exponent.
|
|
716
862
|
*/
|
|
@@ -795,6 +941,13 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
|
|
|
795
941
|
window->dictLimit = end;
|
|
796
942
|
}
|
|
797
943
|
|
|
944
|
+
MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)
|
|
945
|
+
{
|
|
946
|
+
return window.dictLimit == ZSTD_WINDOW_START_INDEX &&
|
|
947
|
+
window.lowLimit == ZSTD_WINDOW_START_INDEX &&
|
|
948
|
+
(window.nextSrc - window.base) == ZSTD_WINDOW_START_INDEX;
|
|
949
|
+
}
|
|
950
|
+
|
|
798
951
|
/**
|
|
799
952
|
* ZSTD_window_hasExtDict():
|
|
800
953
|
* Returns non-zero if the window has a non-empty extDict.
|
|
@@ -818,15 +971,71 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
|
|
|
818
971
|
ZSTD_noDict;
|
|
819
972
|
}
|
|
820
973
|
|
|
974
|
+
/* Defining this macro to non-zero tells zstd to run the overflow correction
|
|
975
|
+
* code much more frequently. This is very inefficient, and should only be
|
|
976
|
+
* used for tests and fuzzers.
|
|
977
|
+
*/
|
|
978
|
+
#ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY
|
|
979
|
+
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
980
|
+
# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1
|
|
981
|
+
# else
|
|
982
|
+
# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0
|
|
983
|
+
# endif
|
|
984
|
+
#endif
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* ZSTD_window_canOverflowCorrect():
|
|
988
|
+
* Returns non-zero if the indices are large enough for overflow correction
|
|
989
|
+
* to work correctly without impacting compression ratio.
|
|
990
|
+
*/
|
|
991
|
+
MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,
|
|
992
|
+
U32 cycleLog,
|
|
993
|
+
U32 maxDist,
|
|
994
|
+
U32 loadedDictEnd,
|
|
995
|
+
void const* src)
|
|
996
|
+
{
|
|
997
|
+
U32 const cycleSize = 1u << cycleLog;
|
|
998
|
+
U32 const curr = (U32)((BYTE const*)src - window.base);
|
|
999
|
+
U32 const minIndexToOverflowCorrect = cycleSize
|
|
1000
|
+
+ MAX(maxDist, cycleSize)
|
|
1001
|
+
+ ZSTD_WINDOW_START_INDEX;
|
|
1002
|
+
|
|
1003
|
+
/* Adjust the min index to backoff the overflow correction frequency,
|
|
1004
|
+
* so we don't waste too much CPU in overflow correction. If this
|
|
1005
|
+
* computation overflows we don't really care, we just need to make
|
|
1006
|
+
* sure it is at least minIndexToOverflowCorrect.
|
|
1007
|
+
*/
|
|
1008
|
+
U32 const adjustment = window.nbOverflowCorrections + 1;
|
|
1009
|
+
U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment,
|
|
1010
|
+
minIndexToOverflowCorrect);
|
|
1011
|
+
U32 const indexLargeEnough = curr > adjustedIndex;
|
|
1012
|
+
|
|
1013
|
+
/* Only overflow correct early if the dictionary is invalidated already,
|
|
1014
|
+
* so we don't hurt compression ratio.
|
|
1015
|
+
*/
|
|
1016
|
+
U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd;
|
|
1017
|
+
|
|
1018
|
+
return indexLargeEnough && dictionaryInvalidated;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
821
1021
|
/**
|
|
822
1022
|
* ZSTD_window_needOverflowCorrection():
|
|
823
1023
|
* Returns non-zero if the indices are getting too large and need overflow
|
|
824
1024
|
* protection.
|
|
825
1025
|
*/
|
|
826
1026
|
MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
|
|
1027
|
+
U32 cycleLog,
|
|
1028
|
+
U32 maxDist,
|
|
1029
|
+
U32 loadedDictEnd,
|
|
1030
|
+
void const* src,
|
|
827
1031
|
void const* srcEnd)
|
|
828
1032
|
{
|
|
829
1033
|
U32 const curr = (U32)((BYTE const*)srcEnd - window.base);
|
|
1034
|
+
if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
|
|
1035
|
+
if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) {
|
|
1036
|
+
return 1;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
830
1039
|
return curr > ZSTD_CURRENT_MAX;
|
|
831
1040
|
}
|
|
832
1041
|
|
|
@@ -838,9 +1047,10 @@ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
|
|
|
838
1047
|
*
|
|
839
1048
|
* The least significant cycleLog bits of the indices must remain the same,
|
|
840
1049
|
* which may be 0. Every index up to maxDist in the past must be valid.
|
|
841
|
-
* NOTE: (maxDist & cycleMask) must be zero.
|
|
842
1050
|
*/
|
|
843
|
-
MEM_STATIC
|
|
1051
|
+
MEM_STATIC
|
|
1052
|
+
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
|
1053
|
+
U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
|
844
1054
|
U32 maxDist, void const* src)
|
|
845
1055
|
{
|
|
846
1056
|
/* preemptive overflow correction:
|
|
@@ -862,32 +1072,52 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
|
|
862
1072
|
* 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
|
|
863
1073
|
* windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
|
|
864
1074
|
*/
|
|
865
|
-
U32 const
|
|
1075
|
+
U32 const cycleSize = 1u << cycleLog;
|
|
1076
|
+
U32 const cycleMask = cycleSize - 1;
|
|
866
1077
|
U32 const curr = (U32)((BYTE const*)src - window->base);
|
|
867
|
-
U32 const
|
|
868
|
-
/*
|
|
869
|
-
U32 const
|
|
870
|
-
|
|
1078
|
+
U32 const currentCycle = curr & cycleMask;
|
|
1079
|
+
/* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */
|
|
1080
|
+
U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX
|
|
1081
|
+
? MAX(cycleSize, ZSTD_WINDOW_START_INDEX)
|
|
1082
|
+
: 0;
|
|
1083
|
+
U32 const newCurrent = currentCycle
|
|
1084
|
+
+ currentCycleCorrection
|
|
1085
|
+
+ MAX(maxDist, cycleSize);
|
|
871
1086
|
U32 const correction = curr - newCurrent;
|
|
872
|
-
|
|
1087
|
+
/* maxDist must be a power of two so that:
|
|
1088
|
+
* (newCurrent & cycleMask) == (curr & cycleMask)
|
|
1089
|
+
* This is required to not corrupt the chains / binary tree.
|
|
1090
|
+
*/
|
|
1091
|
+
assert((maxDist & (maxDist - 1)) == 0);
|
|
1092
|
+
assert((curr & cycleMask) == (newCurrent & cycleMask));
|
|
873
1093
|
assert(curr > newCurrent);
|
|
874
|
-
|
|
875
|
-
|
|
1094
|
+
if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
|
|
1095
|
+
/* Loose bound, should be around 1<<29 (see above) */
|
|
1096
|
+
assert(correction > 1<<28);
|
|
1097
|
+
}
|
|
876
1098
|
|
|
877
1099
|
window->base += correction;
|
|
878
1100
|
window->dictBase += correction;
|
|
879
|
-
if (window->lowLimit
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
1101
|
+
if (window->lowLimit < correction + ZSTD_WINDOW_START_INDEX) {
|
|
1102
|
+
window->lowLimit = ZSTD_WINDOW_START_INDEX;
|
|
1103
|
+
} else {
|
|
1104
|
+
window->lowLimit -= correction;
|
|
1105
|
+
}
|
|
1106
|
+
if (window->dictLimit < correction + ZSTD_WINDOW_START_INDEX) {
|
|
1107
|
+
window->dictLimit = ZSTD_WINDOW_START_INDEX;
|
|
1108
|
+
} else {
|
|
1109
|
+
window->dictLimit -= correction;
|
|
1110
|
+
}
|
|
883
1111
|
|
|
884
1112
|
/* Ensure we can still reference the full window. */
|
|
885
1113
|
assert(newCurrent >= maxDist);
|
|
886
|
-
assert(newCurrent - maxDist >=
|
|
1114
|
+
assert(newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX);
|
|
887
1115
|
/* Ensure that lowLimit and dictLimit didn't underflow. */
|
|
888
1116
|
assert(window->lowLimit <= newCurrent);
|
|
889
1117
|
assert(window->dictLimit <= newCurrent);
|
|
890
1118
|
|
|
1119
|
+
++window->nbOverflowCorrections;
|
|
1120
|
+
|
|
891
1121
|
DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
|
|
892
1122
|
window->lowLimit);
|
|
893
1123
|
return correction;
|
|
@@ -976,10 +1206,15 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window,
|
|
|
976
1206
|
(unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
|
|
977
1207
|
assert(blockEndIdx >= loadedDictEnd);
|
|
978
1208
|
|
|
979
|
-
if (blockEndIdx > loadedDictEnd + maxDist) {
|
|
1209
|
+
if (blockEndIdx > loadedDictEnd + maxDist || loadedDictEnd != window->dictLimit) {
|
|
980
1210
|
/* On reaching window size, dictionaries are invalidated.
|
|
981
1211
|
* For simplification, if window size is reached anywhere within next block,
|
|
982
1212
|
* the dictionary is invalidated for the full block.
|
|
1213
|
+
*
|
|
1214
|
+
* We also have to invalidate the dictionary if ZSTD_window_update() has detected
|
|
1215
|
+
* non-contiguous segments, which means that loadedDictEnd != window->dictLimit.
|
|
1216
|
+
* loadedDictEnd may be 0, if forceWindow is true, but in that case we never use
|
|
1217
|
+
* dictMatchState, so setting it to NULL is not a problem.
|
|
983
1218
|
*/
|
|
984
1219
|
DEBUGLOG(6, "invalidating dictionary for current block (distance > windowSize)");
|
|
985
1220
|
*loadedDictEndPtr = 0;
|
|
@@ -992,11 +1227,13 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window,
|
|
|
992
1227
|
|
|
993
1228
|
MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
|
|
994
1229
|
ZSTD_memset(window, 0, sizeof(*window));
|
|
995
|
-
window->base = (BYTE const*)"";
|
|
996
|
-
window->dictBase = (BYTE const*)"";
|
|
997
|
-
|
|
998
|
-
window->
|
|
999
|
-
window->
|
|
1230
|
+
window->base = (BYTE const*)" ";
|
|
1231
|
+
window->dictBase = (BYTE const*)" ";
|
|
1232
|
+
ZSTD_STATIC_ASSERT(ZSTD_DUBT_UNSORTED_MARK < ZSTD_WINDOW_START_INDEX); /* Start above ZSTD_DUBT_UNSORTED_MARK */
|
|
1233
|
+
window->dictLimit = ZSTD_WINDOW_START_INDEX; /* start from >0, so that 1st position is valid */
|
|
1234
|
+
window->lowLimit = ZSTD_WINDOW_START_INDEX; /* it ensures first and later CCtx usages compress the same */
|
|
1235
|
+
window->nextSrc = window->base + ZSTD_WINDOW_START_INDEX; /* see issue #1241 */
|
|
1236
|
+
window->nbOverflowCorrections = 0;
|
|
1000
1237
|
}
|
|
1001
1238
|
|
|
1002
1239
|
/**
|
|
@@ -1006,8 +1243,11 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
|
|
|
1006
1243
|
* forget about the extDict. Handles overlap of the prefix and extDict.
|
|
1007
1244
|
* Returns non-zero if the segment is contiguous.
|
|
1008
1245
|
*/
|
|
1009
|
-
MEM_STATIC
|
|
1010
|
-
|
|
1246
|
+
MEM_STATIC
|
|
1247
|
+
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
|
1248
|
+
U32 ZSTD_window_update(ZSTD_window_t* window,
|
|
1249
|
+
void const* src, size_t srcSize,
|
|
1250
|
+
int forceNonContiguous)
|
|
1011
1251
|
{
|
|
1012
1252
|
BYTE const* const ip = (BYTE const*)src;
|
|
1013
1253
|
U32 contiguous = 1;
|
|
@@ -1017,7 +1257,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
|
|
1017
1257
|
assert(window->base != NULL);
|
|
1018
1258
|
assert(window->dictBase != NULL);
|
|
1019
1259
|
/* Check if blocks follow each other */
|
|
1020
|
-
if (src != window->nextSrc) {
|
|
1260
|
+
if (src != window->nextSrc || forceNonContiguous) {
|
|
1021
1261
|
/* not contiguous */
|
|
1022
1262
|
size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
|
|
1023
1263
|
DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
|
|
@@ -1047,15 +1287,15 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
|
|
1047
1287
|
*/
|
|
1048
1288
|
MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
|
|
1049
1289
|
{
|
|
1050
|
-
U32
|
|
1051
|
-
U32
|
|
1052
|
-
U32
|
|
1053
|
-
U32
|
|
1290
|
+
U32 const maxDistance = 1U << windowLog;
|
|
1291
|
+
U32 const lowestValid = ms->window.lowLimit;
|
|
1292
|
+
U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
|
|
1293
|
+
U32 const isDictionary = (ms->loadedDictEnd != 0);
|
|
1054
1294
|
/* When using a dictionary the entire dictionary is valid if a single byte of the dictionary
|
|
1055
1295
|
* is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't
|
|
1056
1296
|
* valid for the entire block. So this check is sufficient to find the lowest valid match index.
|
|
1057
1297
|
*/
|
|
1058
|
-
U32
|
|
1298
|
+
U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
|
|
1059
1299
|
return matchLowest;
|
|
1060
1300
|
}
|
|
1061
1301
|
|
|
@@ -1108,6 +1348,42 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
|
|
|
1108
1348
|
|
|
1109
1349
|
#endif
|
|
1110
1350
|
|
|
1351
|
+
/* Short Cache */
|
|
1352
|
+
|
|
1353
|
+
/* Normally, zstd matchfinders follow this flow:
|
|
1354
|
+
* 1. Compute hash at ip
|
|
1355
|
+
* 2. Load index from hashTable[hash]
|
|
1356
|
+
* 3. Check if *ip == *(base + index)
|
|
1357
|
+
* In dictionary compression, loading *(base + index) is often an L2 or even L3 miss.
|
|
1358
|
+
*
|
|
1359
|
+
* Short cache is an optimization which allows us to avoid step 3 most of the time
|
|
1360
|
+
* when the data doesn't actually match. With short cache, the flow becomes:
|
|
1361
|
+
* 1. Compute (hash, currentTag) at ip. currentTag is an 8-bit independent hash at ip.
|
|
1362
|
+
* 2. Load (index, matchTag) from hashTable[hash]. See ZSTD_writeTaggedIndex to understand how this works.
|
|
1363
|
+
* 3. Only if currentTag == matchTag, check *ip == *(base + index). Otherwise, continue.
|
|
1364
|
+
*
|
|
1365
|
+
* Currently, short cache is only implemented in CDict hashtables. Thus, its use is limited to
|
|
1366
|
+
* dictMatchState matchfinders.
|
|
1367
|
+
*/
|
|
1368
|
+
#define ZSTD_SHORT_CACHE_TAG_BITS 8
|
|
1369
|
+
#define ZSTD_SHORT_CACHE_TAG_MASK ((1u << ZSTD_SHORT_CACHE_TAG_BITS) - 1)
|
|
1370
|
+
|
|
1371
|
+
/* Helper function for ZSTD_fillHashTable and ZSTD_fillDoubleHashTable.
|
|
1372
|
+
* Unpacks hashAndTag into (hash, tag), then packs (index, tag) into hashTable[hash]. */
|
|
1373
|
+
MEM_STATIC void ZSTD_writeTaggedIndex(U32* const hashTable, size_t hashAndTag, U32 index) {
|
|
1374
|
+
size_t const hash = hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS;
|
|
1375
|
+
U32 const tag = (U32)(hashAndTag & ZSTD_SHORT_CACHE_TAG_MASK);
|
|
1376
|
+
assert(index >> (32 - ZSTD_SHORT_CACHE_TAG_BITS) == 0);
|
|
1377
|
+
hashTable[hash] = (index << ZSTD_SHORT_CACHE_TAG_BITS) | tag;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
/* Helper function for short cache matchfinders.
|
|
1381
|
+
* Unpacks tag1 and tag2 from lower bits of packedTag1 and packedTag2, then checks if the tags match. */
|
|
1382
|
+
MEM_STATIC int ZSTD_comparePackedTags(size_t packedTag1, size_t packedTag2) {
|
|
1383
|
+
U32 const tag1 = packedTag1 & ZSTD_SHORT_CACHE_TAG_MASK;
|
|
1384
|
+
U32 const tag2 = packedTag2 & ZSTD_SHORT_CACHE_TAG_MASK;
|
|
1385
|
+
return tag1 == tag2;
|
|
1386
|
+
}
|
|
1111
1387
|
|
|
1112
1388
|
#if defined (__cplusplus)
|
|
1113
1389
|
}
|
|
@@ -1190,14 +1466,69 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
|
|
|
1190
1466
|
* This cannot be used when long range matching is enabled.
|
|
1191
1467
|
* Zstd will use these sequences, and pass the literals to a secondary block
|
|
1192
1468
|
* compressor.
|
|
1193
|
-
* @return : An error code on failure.
|
|
1194
1469
|
* NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory
|
|
1195
1470
|
* access and data corruption.
|
|
1196
1471
|
*/
|
|
1197
|
-
|
|
1472
|
+
void ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);
|
|
1198
1473
|
|
|
1199
1474
|
/** ZSTD_cycleLog() :
|
|
1200
1475
|
* condition for correct operation : hashLog > 1 */
|
|
1201
1476
|
U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
|
|
1202
1477
|
|
|
1478
|
+
/** ZSTD_CCtx_trace() :
|
|
1479
|
+
* Trace the end of a compression call.
|
|
1480
|
+
*/
|
|
1481
|
+
void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);
|
|
1482
|
+
|
|
1483
|
+
/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
|
|
1484
|
+
* ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
|
|
1485
|
+
* Note that the block delimiter must include the last literals of the block.
|
|
1486
|
+
*/
|
|
1487
|
+
size_t
|
|
1488
|
+
ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
|
|
1489
|
+
ZSTD_sequencePosition* seqPos,
|
|
1490
|
+
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
|
1491
|
+
const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch);
|
|
1492
|
+
|
|
1493
|
+
/* Returns the number of bytes to move the current read position back by.
|
|
1494
|
+
* Only non-zero if we ended up splitting a sequence.
|
|
1495
|
+
* Otherwise, it may return a ZSTD error if something went wrong.
|
|
1496
|
+
*
|
|
1497
|
+
* This function will attempt to scan through blockSize bytes
|
|
1498
|
+
* represented by the sequences in @inSeqs,
|
|
1499
|
+
* storing any (partial) sequences.
|
|
1500
|
+
*
|
|
1501
|
+
* Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to
|
|
1502
|
+
* avoid splitting a match, or to avoid splitting a match such that it would produce a match
|
|
1503
|
+
* smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
|
|
1504
|
+
*/
|
|
1505
|
+
size_t
|
|
1506
|
+
ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
|
1507
|
+
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
|
1508
|
+
const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch);
|
|
1509
|
+
|
|
1510
|
+
/* Returns 1 if an external sequence producer is registered, otherwise returns 0. */
|
|
1511
|
+
MEM_STATIC int ZSTD_hasExtSeqProd(const ZSTD_CCtx_params* params) {
|
|
1512
|
+
return params->extSeqProdFunc != NULL;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
/* ===============================================================
|
|
1516
|
+
* Deprecated definitions that are still used internally to avoid
|
|
1517
|
+
* deprecation warnings. These functions are exactly equivalent to
|
|
1518
|
+
* their public variants, but avoid the deprecation warnings.
|
|
1519
|
+
* =============================================================== */
|
|
1520
|
+
|
|
1521
|
+
size_t ZSTD_compressBegin_usingCDict_deprecated(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
|
1522
|
+
|
|
1523
|
+
size_t ZSTD_compressContinue_public(ZSTD_CCtx* cctx,
|
|
1524
|
+
void* dst, size_t dstCapacity,
|
|
1525
|
+
const void* src, size_t srcSize);
|
|
1526
|
+
|
|
1527
|
+
size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx,
|
|
1528
|
+
void* dst, size_t dstCapacity,
|
|
1529
|
+
const void* src, size_t srcSize);
|
|
1530
|
+
|
|
1531
|
+
size_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
|
1532
|
+
|
|
1533
|
+
|
|
1203
1534
|
#endif /* ZSTD_COMPRESS_H */
|