zstd-ruby 1.4.0.0 → 1.4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/Makefile +5 -0
- data/ext/zstdruby/libzstd/common/compiler.h +7 -0
- data/ext/zstdruby/libzstd/common/zstd_internal.h +58 -6
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +175 -117
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +74 -30
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +56 -36
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +35 -14
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +10 -5
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +45 -32
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +18 -7
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +1 -0
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +12 -9
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +20 -9
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +154 -43
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +38 -3
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +46 -39
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +9 -9
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +5 -0
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +4 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +95 -101
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +11 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +11 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +11 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +88 -84
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +2 -4
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +2 -4
- data/ext/zstdruby/libzstd/zstd.h +53 -21
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +3 -4
@@ -33,13 +33,13 @@ extern "C" {
|
|
33
33
|
***************************************/
|
34
34
|
#define kSearchStrength 8
|
35
35
|
#define HASH_READ_SIZE 8
|
36
|
-
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1
|
36
|
+
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index ZSTD_DUBT_UNSORTED_MARK==1 means "unsorted".
|
37
37
|
It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
|
38
38
|
It's not a big deal though : candidate will just be sorted again.
|
39
39
|
Additionally, candidate position 1 will be lost.
|
40
40
|
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 re-use with a different strategy
|
42
|
-
|
41
|
+
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy.
|
42
|
+
This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
43
43
|
|
44
44
|
|
45
45
|
/*-*************************************
|
@@ -128,21 +128,20 @@ typedef struct {
|
|
128
128
|
BYTE const* base; /* All regular indexes relative to this position */
|
129
129
|
BYTE const* dictBase; /* extDict indexes relative to this position */
|
130
130
|
U32 dictLimit; /* below that point, need extDict */
|
131
|
-
U32 lowLimit; /* below that point, no more data */
|
131
|
+
U32 lowLimit; /* below that point, no more valid data */
|
132
132
|
} ZSTD_window_t;
|
133
133
|
|
134
134
|
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
|
135
135
|
struct ZSTD_matchState_t {
|
136
136
|
ZSTD_window_t window; /* State for window round buffer management */
|
137
|
-
U32 loadedDictEnd; /* index of end of dictionary */
|
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 */
|
138
138
|
U32 nextToUpdate; /* index from which to continue table update */
|
139
|
-
U32 nextToUpdate3; /* index from which to continue table update */
|
140
139
|
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
141
140
|
U32* hashTable;
|
142
141
|
U32* hashTable3;
|
143
142
|
U32* chainTable;
|
144
143
|
optState_t opt; /* optimal parser state */
|
145
|
-
const ZSTD_matchState_t
|
144
|
+
const ZSTD_matchState_t* dictMatchState;
|
146
145
|
ZSTD_compressionParameters cParams;
|
147
146
|
};
|
148
147
|
|
@@ -195,6 +194,9 @@ struct ZSTD_CCtx_params_s {
|
|
195
194
|
int compressionLevel;
|
196
195
|
int forceWindow; /* force back-references to respect limit of
|
197
196
|
* 1<<wLog, even for dictionary */
|
197
|
+
size_t targetCBlockSize; /* Tries to fit compressed block size to be around targetCBlockSize.
|
198
|
+
* No target when targetCBlockSize == 0.
|
199
|
+
* There is no guarantee on compressed block size */
|
198
200
|
|
199
201
|
ZSTD_dictAttachPref_e attachDictPref;
|
200
202
|
ZSTD_literalCompressionMode_e literalCompressionMode;
|
@@ -324,7 +326,7 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v
|
|
324
326
|
/* copy Literals */
|
325
327
|
assert(seqStorePtr->maxNbLit <= 128 KB);
|
326
328
|
assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);
|
327
|
-
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
|
329
|
+
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength, ZSTD_no_overlap);
|
328
330
|
seqStorePtr->lit += litLength;
|
329
331
|
|
330
332
|
/* literal Length */
|
@@ -564,6 +566,9 @@ MEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64
|
|
564
566
|
/*-*************************************
|
565
567
|
* Round buffer management
|
566
568
|
***************************************/
|
569
|
+
#if (ZSTD_WINDOWLOG_MAX_64 > 31)
|
570
|
+
# error "ZSTD_WINDOWLOG_MAX is too large : would overflow ZSTD_CURRENT_MAX"
|
571
|
+
#endif
|
567
572
|
/* Max current allowed */
|
568
573
|
#define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX))
|
569
574
|
/* Maximum chunk size before overflow correction needs to be called again */
|
@@ -675,31 +680,49 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
|
675
680
|
* Updates lowLimit so that:
|
676
681
|
* (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
|
677
682
|
*
|
678
|
-
*
|
679
|
-
* This must be called before a block compression call
|
680
|
-
*
|
683
|
+
* It ensures index is valid as long as index >= lowLimit.
|
684
|
+
* This must be called before a block compression call.
|
685
|
+
*
|
686
|
+
* loadedDictEnd is only defined if a dictionary is in use for current compression.
|
687
|
+
* As the name implies, loadedDictEnd represents the index at end of dictionary.
|
688
|
+
* The value lies within context's referential, it can be directly compared to blockEndIdx.
|
681
689
|
*
|
682
|
-
* If loadedDictEndPtr is
|
683
|
-
*
|
684
|
-
*
|
685
|
-
*
|
686
|
-
*
|
690
|
+
* If loadedDictEndPtr is NULL, no dictionary is in use, and we use loadedDictEnd == 0.
|
691
|
+
* If loadedDictEndPtr is not NULL, we set it to zero after updating lowLimit.
|
692
|
+
* This is because dictionaries are allowed to be referenced fully
|
693
|
+
* as long as the last byte of the dictionary is in the window.
|
694
|
+
* Once input has progressed beyond window size, dictionary cannot be referenced anymore.
|
687
695
|
*
|
688
|
-
* In normal dict mode, the
|
689
|
-
* dictMatchState mode, lowLimit and dictLimit are the same,
|
690
|
-
* is below them.
|
696
|
+
* In normal dict mode, the dictionary lies between lowLimit and dictLimit.
|
697
|
+
* In dictMatchState mode, lowLimit and dictLimit are the same,
|
698
|
+
* and the dictionary is below them.
|
699
|
+
* forceWindow and dictMatchState are therefore incompatible.
|
691
700
|
*/
|
692
701
|
MEM_STATIC void
|
693
702
|
ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
|
694
|
-
|
695
|
-
U32
|
696
|
-
U32*
|
703
|
+
const void* blockEnd,
|
704
|
+
U32 maxDist,
|
705
|
+
U32* loadedDictEndPtr,
|
697
706
|
const ZSTD_matchState_t** dictMatchStatePtr)
|
698
707
|
{
|
699
|
-
U32 const blockEndIdx = (U32)((BYTE const*)
|
700
|
-
U32 loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
|
701
|
-
DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u",
|
702
|
-
(unsigned)blockEndIdx, (unsigned)maxDist);
|
708
|
+
U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
|
709
|
+
U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
|
710
|
+
DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
|
711
|
+
(unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
|
712
|
+
|
713
|
+
/* - When there is no dictionary : loadedDictEnd == 0.
|
714
|
+
In which case, the test (blockEndIdx > maxDist) is merely to avoid
|
715
|
+
overflowing next operation `newLowLimit = blockEndIdx - maxDist`.
|
716
|
+
- When there is a standard dictionary :
|
717
|
+
Index referential is copied from the dictionary,
|
718
|
+
which means it starts from 0.
|
719
|
+
In which case, loadedDictEnd == dictSize,
|
720
|
+
and it makes sense to compare `blockEndIdx > maxDist + dictSize`
|
721
|
+
since `blockEndIdx` also starts from zero.
|
722
|
+
- When there is an attached dictionary :
|
723
|
+
loadedDictEnd is expressed within the referential of the context,
|
724
|
+
so it can be directly compared against blockEndIdx.
|
725
|
+
*/
|
703
726
|
if (blockEndIdx > maxDist + loadedDictEnd) {
|
704
727
|
U32 const newLowLimit = blockEndIdx - maxDist;
|
705
728
|
if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
|
@@ -708,10 +731,31 @@ ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
|
|
708
731
|
(unsigned)window->dictLimit, (unsigned)window->lowLimit);
|
709
732
|
window->dictLimit = window->lowLimit;
|
710
733
|
}
|
711
|
-
|
712
|
-
|
713
|
-
if (dictMatchStatePtr)
|
714
|
-
|
734
|
+
/* On reaching window size, dictionaries are invalidated */
|
735
|
+
if (loadedDictEndPtr) *loadedDictEndPtr = 0;
|
736
|
+
if (dictMatchStatePtr) *dictMatchStatePtr = NULL;
|
737
|
+
}
|
738
|
+
}
|
739
|
+
|
740
|
+
/* Similar to ZSTD_window_enforceMaxDist(),
|
741
|
+
* but only invalidates dictionary
|
742
|
+
* when input progresses beyond window size. */
|
743
|
+
MEM_STATIC void
|
744
|
+
ZSTD_checkDictValidity(ZSTD_window_t* window,
|
745
|
+
const void* blockEnd,
|
746
|
+
U32 maxDist,
|
747
|
+
U32* loadedDictEndPtr,
|
748
|
+
const ZSTD_matchState_t** dictMatchStatePtr)
|
749
|
+
{
|
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);
|
754
|
+
|
755
|
+
if (loadedDictEnd && (blockEndIdx > maxDist + loadedDictEnd)) {
|
756
|
+
/* On reaching window size, dictionaries are invalidated */
|
757
|
+
if (loadedDictEndPtr) *loadedDictEndPtr = 0;
|
758
|
+
if (dictMatchStatePtr) *dictMatchStatePtr = NULL;
|
715
759
|
}
|
716
760
|
}
|
717
761
|
|
@@ -43,8 +43,7 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
|
|
43
43
|
/* Only load extra positions for ZSTD_dtlm_full */
|
44
44
|
if (dtlm == ZSTD_dtlm_fast)
|
45
45
|
break;
|
46
|
-
|
47
|
-
}
|
46
|
+
} }
|
48
47
|
}
|
49
48
|
|
50
49
|
|
@@ -63,7 +62,10 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
63
62
|
const BYTE* const istart = (const BYTE*)src;
|
64
63
|
const BYTE* ip = istart;
|
65
64
|
const BYTE* anchor = istart;
|
66
|
-
const U32
|
65
|
+
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
66
|
+
const U32 lowestValid = ms->window.dictLimit;
|
67
|
+
const U32 maxDistance = 1U << cParams->windowLog;
|
68
|
+
const U32 prefixLowestIndex = (endIndex - lowestValid > maxDistance) ? endIndex - maxDistance : lowestValid;
|
67
69
|
const BYTE* const prefixLowest = base + prefixLowestIndex;
|
68
70
|
const BYTE* const iend = istart + srcSize;
|
69
71
|
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
@@ -95,8 +97,15 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
95
97
|
dictCParams->chainLog : hBitsS;
|
96
98
|
const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictStart);
|
97
99
|
|
100
|
+
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic");
|
101
|
+
|
98
102
|
assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
|
99
103
|
|
104
|
+
/* if a dictionary is attached, it must be within window range */
|
105
|
+
if (dictMode == ZSTD_dictMatchState) {
|
106
|
+
assert(lowestValid + maxDistance >= endIndex);
|
107
|
+
}
|
108
|
+
|
100
109
|
/* init */
|
101
110
|
ip += (dictAndPrefixLength == 0);
|
102
111
|
if (dictMode == ZSTD_noDict) {
|
@@ -138,7 +147,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
138
147
|
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
139
148
|
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
140
149
|
ip++;
|
141
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
150
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
142
151
|
goto _match_stored;
|
143
152
|
}
|
144
153
|
|
@@ -147,7 +156,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
147
156
|
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
|
148
157
|
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
149
158
|
ip++;
|
150
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
159
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
151
160
|
goto _match_stored;
|
152
161
|
}
|
153
162
|
|
@@ -170,8 +179,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
170
179
|
offset = (U32)(current - dictMatchIndexL - dictIndexDelta);
|
171
180
|
while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */
|
172
181
|
goto _match_found;
|
173
|
-
|
174
|
-
}
|
182
|
+
} }
|
175
183
|
|
176
184
|
if (matchIndexS > prefixLowestIndex) {
|
177
185
|
/* check prefix short match */
|
@@ -186,16 +194,14 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
186
194
|
|
187
195
|
if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) {
|
188
196
|
goto _search_next_long;
|
189
|
-
|
190
|
-
}
|
197
|
+
} }
|
191
198
|
|
192
199
|
ip += ((ip-anchor) >> kSearchStrength) + 1;
|
193
200
|
continue;
|
194
201
|
|
195
202
|
_search_next_long:
|
196
203
|
|
197
|
-
{
|
198
|
-
size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
204
|
+
{ size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
199
205
|
size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8);
|
200
206
|
U32 const matchIndexL3 = hashLong[hl3];
|
201
207
|
const BYTE* matchL3 = base + matchIndexL3;
|
@@ -221,9 +227,7 @@ _search_next_long:
|
|
221
227
|
offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta);
|
222
228
|
while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */
|
223
229
|
goto _match_found;
|
224
|
-
|
225
|
-
}
|
226
|
-
}
|
230
|
+
} } }
|
227
231
|
|
228
232
|
/* if no long +1 match, explore the short match we found */
|
229
233
|
if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
|
@@ -242,7 +246,7 @@ _match_found:
|
|
242
246
|
offset_2 = offset_1;
|
243
247
|
offset_1 = offset;
|
244
248
|
|
245
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
249
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
246
250
|
|
247
251
|
_match_stored:
|
248
252
|
/* match found */
|
@@ -250,11 +254,14 @@ _match_stored:
|
|
250
254
|
anchor = ip;
|
251
255
|
|
252
256
|
if (ip <= ilimit) {
|
253
|
-
/*
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
257
|
+
/* Complementary insertion */
|
258
|
+
/* done after iLimit test, as candidates could be > iend-8 */
|
259
|
+
{ U32 const indexToInsert = current+2;
|
260
|
+
hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
|
261
|
+
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
|
262
|
+
hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
|
263
|
+
hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);
|
264
|
+
}
|
258
265
|
|
259
266
|
/* check immediate repcode */
|
260
267
|
if (dictMode == ZSTD_dictMatchState) {
|
@@ -278,8 +285,7 @@ _match_stored:
|
|
278
285
|
continue;
|
279
286
|
}
|
280
287
|
break;
|
281
|
-
|
282
|
-
}
|
288
|
+
} }
|
283
289
|
|
284
290
|
if (dictMode == ZSTD_noDict) {
|
285
291
|
while ( (ip <= ilimit)
|
@@ -294,14 +300,15 @@ _match_stored:
|
|
294
300
|
ip += rLength;
|
295
301
|
anchor = ip;
|
296
302
|
continue; /* faster when present ... (?) */
|
297
|
-
|
303
|
+
} } }
|
304
|
+
} /* while (ip < ilimit) */
|
298
305
|
|
299
306
|
/* save reps for next block */
|
300
307
|
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
301
308
|
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
302
309
|
|
303
310
|
/* Return the last literals size */
|
304
|
-
return iend - anchor;
|
311
|
+
return (size_t)(iend - anchor);
|
305
312
|
}
|
306
313
|
|
307
314
|
|
@@ -360,10 +367,15 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
360
367
|
const BYTE* anchor = istart;
|
361
368
|
const BYTE* const iend = istart + srcSize;
|
362
369
|
const BYTE* const ilimit = iend - 8;
|
363
|
-
const U32 prefixStartIndex = ms->window.dictLimit;
|
364
370
|
const BYTE* const base = ms->window.base;
|
371
|
+
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
372
|
+
const U32 maxDistance = 1U << cParams->windowLog;
|
373
|
+
const U32 lowestValid = ms->window.lowLimit;
|
374
|
+
const U32 lowLimit = (endIndex - lowestValid > maxDistance) ? endIndex - maxDistance : lowestValid;
|
375
|
+
const U32 dictStartIndex = lowLimit;
|
376
|
+
const U32 dictLimit = ms->window.dictLimit;
|
377
|
+
const U32 prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit;
|
365
378
|
const BYTE* const prefixStart = base + prefixStartIndex;
|
366
|
-
const U32 dictStartIndex = ms->window.lowLimit;
|
367
379
|
const BYTE* const dictBase = ms->window.dictBase;
|
368
380
|
const BYTE* const dictStart = dictBase + dictStartIndex;
|
369
381
|
const BYTE* const dictEnd = dictBase + prefixStartIndex;
|
@@ -371,6 +383,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
371
383
|
|
372
384
|
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)", srcSize);
|
373
385
|
|
386
|
+
/* if extDict is invalidated due to maxDistance, switch to "regular" variant */
|
387
|
+
if (prefixStartIndex == dictStartIndex)
|
388
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_noDict);
|
389
|
+
|
374
390
|
/* Search Loop */
|
375
391
|
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
376
392
|
const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
|
@@ -396,7 +412,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
396
412
|
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
397
413
|
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
398
414
|
ip++;
|
399
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
415
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
400
416
|
} else {
|
401
417
|
if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
|
402
418
|
const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
|
@@ -407,7 +423,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
407
423
|
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
408
424
|
offset_2 = offset_1;
|
409
425
|
offset_1 = offset;
|
410
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
426
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
411
427
|
|
412
428
|
} else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
|
413
429
|
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
@@ -432,23 +448,27 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
432
448
|
}
|
433
449
|
offset_2 = offset_1;
|
434
450
|
offset_1 = offset;
|
435
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
451
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
436
452
|
|
437
453
|
} else {
|
438
454
|
ip += ((ip-anchor) >> kSearchStrength) + 1;
|
439
455
|
continue;
|
440
456
|
} }
|
441
457
|
|
442
|
-
/*
|
458
|
+
/* move to next sequence start */
|
443
459
|
ip += mLength;
|
444
460
|
anchor = ip;
|
445
461
|
|
446
462
|
if (ip <= ilimit) {
|
447
|
-
/*
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
463
|
+
/* Complementary insertion */
|
464
|
+
/* done after iLimit test, as candidates could be > iend-8 */
|
465
|
+
{ U32 const indexToInsert = current+2;
|
466
|
+
hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
|
467
|
+
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
|
468
|
+
hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
|
469
|
+
hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);
|
470
|
+
}
|
471
|
+
|
452
472
|
/* check immediate repcode */
|
453
473
|
while (ip <= ilimit) {
|
454
474
|
U32 const current2 = (U32)(ip-base);
|
@@ -475,7 +495,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
475
495
|
rep[1] = offset_2;
|
476
496
|
|
477
497
|
/* Return the last literals size */
|
478
|
-
return iend - anchor;
|
498
|
+
return (size_t)(iend - anchor);
|
479
499
|
}
|
480
500
|
|
481
501
|
|
@@ -13,7 +13,8 @@
|
|
13
13
|
|
14
14
|
|
15
15
|
void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
|
16
|
-
void const
|
16
|
+
const void* const end,
|
17
|
+
ZSTD_dictTableLoadMethod_e dtlm)
|
17
18
|
{
|
18
19
|
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
19
20
|
U32* const hashTable = ms->hashTable;
|
@@ -41,6 +42,7 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
|
|
41
42
|
} } } }
|
42
43
|
}
|
43
44
|
|
45
|
+
|
44
46
|
FORCE_INLINE_TEMPLATE
|
45
47
|
size_t ZSTD_compressBlock_fast_generic(
|
46
48
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
@@ -58,7 +60,10 @@ size_t ZSTD_compressBlock_fast_generic(
|
|
58
60
|
const BYTE* ip0 = istart;
|
59
61
|
const BYTE* ip1;
|
60
62
|
const BYTE* anchor = istart;
|
61
|
-
const U32
|
63
|
+
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
64
|
+
const U32 maxDistance = 1U << cParams->windowLog;
|
65
|
+
const U32 validStartIndex = ms->window.dictLimit;
|
66
|
+
const U32 prefixStartIndex = (endIndex - validStartIndex > maxDistance) ? endIndex - maxDistance : validStartIndex;
|
62
67
|
const BYTE* const prefixStart = base + prefixStartIndex;
|
63
68
|
const BYTE* const iend = istart + srcSize;
|
64
69
|
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
@@ -165,7 +170,7 @@ _match: /* Requires: ip0, match0, offcode */
|
|
165
170
|
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
166
171
|
|
167
172
|
/* Return the last literals size */
|
168
|
-
return iend - anchor;
|
173
|
+
return (size_t)(iend - anchor);
|
169
174
|
}
|
170
175
|
|
171
176
|
|
@@ -222,8 +227,15 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
|
222
227
|
const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart);
|
223
228
|
const U32 dictHLog = dictCParams->hashLog;
|
224
229
|
|
225
|
-
/*
|
226
|
-
*
|
230
|
+
/* if a dictionary is still attached, it necessarily means that
|
231
|
+
* it is within window size. So we just check it. */
|
232
|
+
const U32 maxDistance = 1U << cParams->windowLog;
|
233
|
+
const U32 endIndex = (U32)((size_t)(ip - base) + srcSize);
|
234
|
+
assert(endIndex - prefixStartIndex <= maxDistance);
|
235
|
+
(void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */
|
236
|
+
|
237
|
+
/* ensure there will be no no underflow
|
238
|
+
* when translating a dict index into a local index */
|
227
239
|
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
|
228
240
|
|
229
241
|
/* init */
|
@@ -251,7 +263,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
|
251
263
|
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
252
264
|
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
253
265
|
ip++;
|
254
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
266
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
255
267
|
} else if ( (matchIndex <= prefixStartIndex) ) {
|
256
268
|
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
|
257
269
|
U32 const dictMatchIndex = dictHashTable[dictHash];
|
@@ -271,7 +283,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
|
271
283
|
} /* catch up */
|
272
284
|
offset_2 = offset_1;
|
273
285
|
offset_1 = offset;
|
274
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
286
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
275
287
|
}
|
276
288
|
} else if (MEM_read32(match) != MEM_read32(ip)) {
|
277
289
|
/* it's not a match, and we're not going to check the dictionary */
|
@@ -286,7 +298,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
|
286
298
|
&& (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
287
299
|
offset_2 = offset_1;
|
288
300
|
offset_1 = offset;
|
289
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
301
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
290
302
|
}
|
291
303
|
|
292
304
|
/* match found */
|
@@ -327,7 +339,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
|
327
339
|
rep[1] = offset_2 ? offset_2 : offsetSaved;
|
328
340
|
|
329
341
|
/* Return the last literals size */
|
330
|
-
return iend - anchor;
|
342
|
+
return (size_t)(iend - anchor);
|
331
343
|
}
|
332
344
|
|
333
345
|
size_t ZSTD_compressBlock_fast_dictMatchState(
|
@@ -366,15 +378,24 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
|
366
378
|
const BYTE* const istart = (const BYTE*)src;
|
367
379
|
const BYTE* ip = istart;
|
368
380
|
const BYTE* anchor = istart;
|
369
|
-
const U32
|
381
|
+
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
|
382
|
+
const U32 maxDistance = 1U << cParams->windowLog;
|
383
|
+
const U32 validLow = ms->window.lowLimit;
|
384
|
+
const U32 lowLimit = (endIndex - validLow > maxDistance) ? endIndex - maxDistance : validLow;
|
385
|
+
const U32 dictStartIndex = lowLimit;
|
370
386
|
const BYTE* const dictStart = dictBase + dictStartIndex;
|
371
|
-
const U32
|
387
|
+
const U32 dictLimit = ms->window.dictLimit;
|
388
|
+
const U32 prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit;
|
372
389
|
const BYTE* const prefixStart = base + prefixStartIndex;
|
373
390
|
const BYTE* const dictEnd = dictBase + prefixStartIndex;
|
374
391
|
const BYTE* const iend = istart + srcSize;
|
375
392
|
const BYTE* const ilimit = iend - 8;
|
376
393
|
U32 offset_1=rep[0], offset_2=rep[1];
|
377
394
|
|
395
|
+
/* switch to "regular" variant if extDict is invalidated due to maxDistance */
|
396
|
+
if (prefixStartIndex == dictStartIndex)
|
397
|
+
return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, mls);
|
398
|
+
|
378
399
|
/* Search Loop */
|
379
400
|
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
380
401
|
const size_t h = ZSTD_hashPtr(ip, hlog, mls);
|
@@ -394,7 +415,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
|
394
415
|
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
395
416
|
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
396
417
|
ip++;
|
397
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
418
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH);
|
398
419
|
} else {
|
399
420
|
if ( (matchIndex < dictStartIndex) ||
|
400
421
|
(MEM_read32(match) != MEM_read32(ip)) ) {
|
@@ -410,7 +431,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
|
410
431
|
offset = current - matchIndex;
|
411
432
|
offset_2 = offset_1;
|
412
433
|
offset_1 = offset;
|
413
|
-
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
434
|
+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
414
435
|
} }
|
415
436
|
|
416
437
|
/* found a match : store it */
|
@@ -445,7 +466,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
|
445
466
|
rep[1] = offset_2;
|
446
467
|
|
447
468
|
/* Return the last literals size */
|
448
|
-
return iend - anchor;
|
469
|
+
return (size_t)(iend - anchor);
|
449
470
|
}
|
450
471
|
|
451
472
|
|