zstd-ruby 1.3.8.0 → 1.4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -5
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/Makefile +133 -61
- data/ext/zstdruby/libzstd/README.md +51 -18
- data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
- data/ext/zstdruby/libzstd/common/compiler.h +41 -6
- data/ext/zstdruby/libzstd/common/cpu.h +1 -1
- data/ext/zstdruby/libzstd/common/debug.c +11 -31
- data/ext/zstdruby/libzstd/common/debug.h +11 -31
- data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
- data/ext/zstdruby/libzstd/common/error_private.c +2 -1
- data/ext/zstdruby/libzstd/common/error_private.h +6 -2
- data/ext/zstdruby/libzstd/common/fse.h +13 -33
- data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
- data/ext/zstdruby/libzstd/common/huf.h +15 -33
- data/ext/zstdruby/libzstd/common/mem.h +75 -2
- data/ext/zstdruby/libzstd/common/pool.c +8 -4
- data/ext/zstdruby/libzstd/common/pool.h +2 -2
- data/ext/zstdruby/libzstd/common/threading.c +52 -6
- data/ext/zstdruby/libzstd/common/threading.h +36 -4
- data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
- data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
- data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
- data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
- data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
- data/ext/zstdruby/libzstd/compress/hist.c +15 -35
- data/ext/zstdruby/libzstd/compress/hist.h +12 -32
- data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +419 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +220 -65
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
- data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
- data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
- data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
- data/ext/zstdruby/libzstd/zstd.h +921 -597
- data/lib/zstd-ruby/version.rb +1 -1
- data/zstd-ruby.gemspec +2 -2
- metadata +19 -14
- data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
@@ -1,10 +1,11 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2016-
|
2
|
+
* Copyright (c) 2016-2020, 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
|
6
6
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
7
7
|
* in the COPYING file in the root directory of this source tree).
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
8
9
|
*/
|
9
10
|
|
10
11
|
#ifndef ZSTD_LDM_H
|
@@ -15,7 +16,7 @@ extern "C" {
|
|
15
16
|
#endif
|
16
17
|
|
17
18
|
#include "zstd_compress_internal.h" /* ldmParams_t, U32 */
|
18
|
-
#include "zstd.h" /* ZSTD_CCtx, size_t */
|
19
|
+
#include "../zstd.h" /* ZSTD_CCtx, size_t */
|
19
20
|
|
20
21
|
/*-*************************************
|
21
22
|
* Long distance matching
|
@@ -23,6 +24,10 @@ extern "C" {
|
|
23
24
|
|
24
25
|
#define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT
|
25
26
|
|
27
|
+
void ZSTD_ldm_fillHashTable(
|
28
|
+
ldmState_t* state, const BYTE* ip,
|
29
|
+
const BYTE* iend, ldmParams_t const* params);
|
30
|
+
|
26
31
|
/**
|
27
32
|
* ZSTD_ldm_generateSequences():
|
28
33
|
*
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2016-
|
2
|
+
* Copyright (c) 2016-2020, Przemyslaw Skibinski, 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
|
@@ -64,9 +64,15 @@ MEM_STATIC double ZSTD_fCost(U32 price)
|
|
64
64
|
}
|
65
65
|
#endif
|
66
66
|
|
67
|
+
static int ZSTD_compressedLiterals(optState_t const* const optPtr)
|
68
|
+
{
|
69
|
+
return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
|
70
|
+
}
|
71
|
+
|
67
72
|
static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
|
68
73
|
{
|
69
|
-
|
74
|
+
if (ZSTD_compressedLiterals(optPtr))
|
75
|
+
optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
|
70
76
|
optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
|
71
77
|
optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
|
72
78
|
optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);
|
@@ -99,6 +105,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|
99
105
|
const BYTE* const src, size_t const srcSize,
|
100
106
|
int const optLevel)
|
101
107
|
{
|
108
|
+
int const compressedLiterals = ZSTD_compressedLiterals(optPtr);
|
102
109
|
DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
|
103
110
|
optPtr->priceType = zop_dynamic;
|
104
111
|
|
@@ -113,9 +120,10 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|
113
120
|
/* huffman table presumed generated by dictionary */
|
114
121
|
optPtr->priceType = zop_dynamic;
|
115
122
|
|
116
|
-
|
117
|
-
|
118
|
-
|
123
|
+
if (compressedLiterals) {
|
124
|
+
unsigned lit;
|
125
|
+
assert(optPtr->litFreq != NULL);
|
126
|
+
optPtr->litSum = 0;
|
119
127
|
for (lit=0; lit<=MaxLit; lit++) {
|
120
128
|
U32 const scaleLog = 11; /* scale to 2K */
|
121
129
|
U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
|
@@ -163,10 +171,11 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|
163
171
|
} else { /* not a dictionary */
|
164
172
|
|
165
173
|
assert(optPtr->litFreq != NULL);
|
166
|
-
|
174
|
+
if (compressedLiterals) {
|
175
|
+
unsigned lit = MaxLit;
|
167
176
|
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
|
177
|
+
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
168
178
|
}
|
169
|
-
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
170
179
|
|
171
180
|
{ unsigned ll;
|
172
181
|
for (ll=0; ll<=MaxLL; ll++)
|
@@ -190,7 +199,8 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
|
190
199
|
|
191
200
|
} else { /* new block : re-use previous statistics, scaled down */
|
192
201
|
|
193
|
-
|
202
|
+
if (compressedLiterals)
|
203
|
+
optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
|
194
204
|
optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
195
205
|
optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
196
206
|
optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0);
|
@@ -207,6 +217,10 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
|
|
207
217
|
int optLevel)
|
208
218
|
{
|
209
219
|
if (litLength == 0) return 0;
|
220
|
+
|
221
|
+
if (!ZSTD_compressedLiterals(optPtr))
|
222
|
+
return (litLength << 3) * BITCOST_MULTIPLIER; /* Uncompressed - 8 bytes per literal. */
|
223
|
+
|
210
224
|
if (optPtr->priceType == zop_predef)
|
211
225
|
return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
|
212
226
|
|
@@ -235,40 +249,6 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
|
|
235
249
|
}
|
236
250
|
}
|
237
251
|
|
238
|
-
/* ZSTD_litLengthContribution() :
|
239
|
-
* @return ( cost(litlength) - cost(0) )
|
240
|
-
* this value can then be added to rawLiteralsCost()
|
241
|
-
* to provide a cost which is directly comparable to a match ending at same position */
|
242
|
-
static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
|
243
|
-
{
|
244
|
-
if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
|
245
|
-
|
246
|
-
/* dynamic statistics */
|
247
|
-
{ U32 const llCode = ZSTD_LLcode(litLength);
|
248
|
-
int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
|
249
|
-
+ WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
|
250
|
-
- WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
|
251
|
-
#if 1
|
252
|
-
return contribution;
|
253
|
-
#else
|
254
|
-
return MAX(0, contribution); /* sometimes better, sometimes not ... */
|
255
|
-
#endif
|
256
|
-
}
|
257
|
-
}
|
258
|
-
|
259
|
-
/* ZSTD_literalsContribution() :
|
260
|
-
* creates a fake cost for the literals part of a sequence
|
261
|
-
* which can be compared to the ending cost of a match
|
262
|
-
* should a new match start at this position */
|
263
|
-
static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength,
|
264
|
-
const optState_t* const optPtr,
|
265
|
-
int optLevel)
|
266
|
-
{
|
267
|
-
int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
|
268
|
-
+ ZSTD_litLengthContribution(litLength, optPtr, optLevel);
|
269
|
-
return contribution;
|
270
|
-
}
|
271
|
-
|
272
252
|
/* ZSTD_getMatchPrice() :
|
273
253
|
* Provides the cost of the match part (offset + matchLength) of a sequence
|
274
254
|
* Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
|
@@ -310,7 +290,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
|
|
310
290
|
U32 offsetCode, U32 matchLength)
|
311
291
|
{
|
312
292
|
/* literals */
|
313
|
-
{
|
293
|
+
if (ZSTD_compressedLiterals(optPtr)) {
|
294
|
+
U32 u;
|
314
295
|
for (u=0; u < litLength; u++)
|
315
296
|
optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
|
316
297
|
optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
|
@@ -357,13 +338,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
|
|
357
338
|
|
358
339
|
/* Update hashTable3 up to ip (excluded)
|
359
340
|
Assumption : always within prefix (i.e. not within extDict) */
|
360
|
-
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
|
341
|
+
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
|
342
|
+
U32* nextToUpdate3,
|
343
|
+
const BYTE* const ip)
|
361
344
|
{
|
362
345
|
U32* const hashTable3 = ms->hashTable3;
|
363
346
|
U32 const hashLog3 = ms->hashLog3;
|
364
347
|
const BYTE* const base = ms->window.base;
|
365
|
-
U32 idx =
|
366
|
-
U32 const target =
|
348
|
+
U32 idx = *nextToUpdate3;
|
349
|
+
U32 const target = (U32)(ip - base);
|
367
350
|
size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
|
368
351
|
assert(hashLog3 > 0);
|
369
352
|
|
@@ -372,6 +355,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
|
|
372
355
|
idx++;
|
373
356
|
}
|
374
357
|
|
358
|
+
*nextToUpdate3 = target;
|
375
359
|
return hashTable3[hash3];
|
376
360
|
}
|
377
361
|
|
@@ -488,9 +472,11 @@ static U32 ZSTD_insertBt1(
|
|
488
472
|
} }
|
489
473
|
|
490
474
|
*smallerPtr = *largerPtr = 0;
|
491
|
-
|
492
|
-
|
493
|
-
|
475
|
+
{ U32 positions = 0;
|
476
|
+
if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */
|
477
|
+
assert(matchEndIdx > current + 8);
|
478
|
+
return MAX(positions, matchEndIdx - (current + 8));
|
479
|
+
}
|
494
480
|
}
|
495
481
|
|
496
482
|
FORCE_INLINE_TEMPLATE
|
@@ -505,8 +491,13 @@ void ZSTD_updateTree_internal(
|
|
505
491
|
DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
|
506
492
|
idx, target, dictMode);
|
507
493
|
|
508
|
-
while(idx < target)
|
509
|
-
|
494
|
+
while(idx < target) {
|
495
|
+
U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
|
496
|
+
assert(idx < (U32)(idx + forward));
|
497
|
+
idx += forward;
|
498
|
+
}
|
499
|
+
assert((size_t)(ip - base) <= (size_t)(U32)(-1));
|
500
|
+
assert((size_t)(iend - base) <= (size_t)(U32)(-1));
|
510
501
|
ms->nextToUpdate = target;
|
511
502
|
}
|
512
503
|
|
@@ -516,11 +507,12 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
|
|
516
507
|
|
517
508
|
FORCE_INLINE_TEMPLATE
|
518
509
|
U32 ZSTD_insertBtAndGetAllMatches (
|
510
|
+
ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
|
519
511
|
ZSTD_matchState_t* ms,
|
512
|
+
U32* nextToUpdate3,
|
520
513
|
const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
|
521
|
-
U32 rep[ZSTD_REP_NUM],
|
514
|
+
const U32 rep[ZSTD_REP_NUM],
|
522
515
|
U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
|
523
|
-
ZSTD_match_t* matches,
|
524
516
|
const U32 lengthToBeat,
|
525
517
|
U32 const mls /* template */)
|
526
518
|
{
|
@@ -541,8 +533,8 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
541
533
|
U32 const dictLimit = ms->window.dictLimit;
|
542
534
|
const BYTE* const dictEnd = dictBase + dictLimit;
|
543
535
|
const BYTE* const prefixStart = base + dictLimit;
|
544
|
-
U32 const btLow = btMask >= current ? 0 : current - btMask;
|
545
|
-
U32 const windowLow = ms->
|
536
|
+
U32 const btLow = (btMask >= current) ? 0 : current - btMask;
|
537
|
+
U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog);
|
546
538
|
U32 const matchLow = windowLow ? windowLow : 1;
|
547
539
|
U32* smallerPtr = bt + 2*(current&btMask);
|
548
540
|
U32* largerPtr = bt + 2*(current&btMask) + 1;
|
@@ -577,7 +569,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
577
569
|
U32 repLen = 0;
|
578
570
|
assert(current >= dictLimit);
|
579
571
|
if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */
|
580
|
-
|
572
|
+
/* We must validate the repcode offset because when we're using a dictionary the
|
573
|
+
* valid offset range shrinks when the dictionary goes out of bounds.
|
574
|
+
*/
|
575
|
+
if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) {
|
581
576
|
repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
|
582
577
|
}
|
583
578
|
} else { /* repIndex < dictLimit || repIndex >= current */
|
@@ -612,7 +607,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
612
607
|
|
613
608
|
/* HC3 match finder */
|
614
609
|
if ((mls == 3) /*static*/ && (bestLength < mls)) {
|
615
|
-
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
|
610
|
+
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
|
616
611
|
if ((matchIndex3 >= matchLow)
|
617
612
|
& (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
|
618
613
|
size_t mlen;
|
@@ -638,9 +633,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
638
633
|
(ip+mlen == iLimit) ) { /* best possible length */
|
639
634
|
ms->nextToUpdate = current+1; /* skip insertion */
|
640
635
|
return 1;
|
641
|
-
|
642
|
-
}
|
643
|
-
}
|
636
|
+
} } }
|
644
637
|
/* no dictMatchState lookup: dicts don't have a populated HC3 table */
|
645
638
|
}
|
646
639
|
|
@@ -648,19 +641,21 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
648
641
|
|
649
642
|
while (nbCompares-- && (matchIndex >= matchLow)) {
|
650
643
|
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
651
|
-
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
652
644
|
const BYTE* match;
|
645
|
+
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
653
646
|
assert(current > matchIndex);
|
654
647
|
|
655
648
|
if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
|
656
649
|
assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
|
657
650
|
match = base + matchIndex;
|
651
|
+
if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
|
658
652
|
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);
|
659
653
|
} else {
|
660
654
|
match = dictBase + matchIndex;
|
655
|
+
assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
|
661
656
|
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
|
662
657
|
if (matchIndex+matchLength >= dictLimit)
|
663
|
-
match = base + matchIndex; /* prepare for match[matchLength] */
|
658
|
+
match = base + matchIndex; /* prepare for match[matchLength] read */
|
664
659
|
}
|
665
660
|
|
666
661
|
if (matchLength > bestLength) {
|
@@ -745,10 +740,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
745
740
|
|
746
741
|
|
747
742
|
FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
743
|
+
ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
|
748
744
|
ZSTD_matchState_t* ms,
|
745
|
+
U32* nextToUpdate3,
|
749
746
|
const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
|
750
|
-
U32 rep[ZSTD_REP_NUM],
|
751
|
-
|
747
|
+
const U32 rep[ZSTD_REP_NUM],
|
748
|
+
U32 const ll0,
|
749
|
+
U32 const lengthToBeat)
|
752
750
|
{
|
753
751
|
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
754
752
|
U32 const matchLengthSearch = cParams->minMatch;
|
@@ -757,12 +755,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
|
757
755
|
ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
|
758
756
|
switch(matchLengthSearch)
|
759
757
|
{
|
760
|
-
case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0,
|
758
|
+
case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3);
|
761
759
|
default :
|
762
|
-
case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0,
|
763
|
-
case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0,
|
760
|
+
case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4);
|
761
|
+
case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5);
|
764
762
|
case 7 :
|
765
|
-
case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0,
|
763
|
+
case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6);
|
766
764
|
}
|
767
765
|
}
|
768
766
|
|
@@ -770,30 +768,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
|
770
768
|
/*-*******************************
|
771
769
|
* Optimal parser
|
772
770
|
*********************************/
|
773
|
-
typedef struct repcodes_s {
|
774
|
-
U32 rep[3];
|
775
|
-
} repcodes_t;
|
776
|
-
|
777
|
-
static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
|
778
|
-
{
|
779
|
-
repcodes_t newReps;
|
780
|
-
if (offset >= ZSTD_REP_NUM) { /* full offset */
|
781
|
-
newReps.rep[2] = rep[1];
|
782
|
-
newReps.rep[1] = rep[0];
|
783
|
-
newReps.rep[0] = offset - ZSTD_REP_MOVE;
|
784
|
-
} else { /* repcode */
|
785
|
-
U32 const repCode = offset + ll0;
|
786
|
-
if (repCode > 0) { /* note : if repCode==0, no change */
|
787
|
-
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
788
|
-
newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
|
789
|
-
newReps.rep[1] = rep[0];
|
790
|
-
newReps.rep[0] = currentOffset;
|
791
|
-
} else { /* repCode == 0 */
|
792
|
-
memcpy(&newReps, rep, sizeof(newReps));
|
793
|
-
}
|
794
|
-
}
|
795
|
-
return newReps;
|
796
|
-
}
|
797
771
|
|
798
772
|
|
799
773
|
static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
|
@@ -810,7 +784,7 @@ listStats(const U32* table, int lastEltID)
|
|
810
784
|
int enb;
|
811
785
|
for (enb=0; enb < nbElts; enb++) {
|
812
786
|
(void)table;
|
813
|
-
|
787
|
+
/* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */
|
814
788
|
RAWLOG(2, "%4i,", table[enb]);
|
815
789
|
}
|
816
790
|
RAWLOG(2, " \n");
|
@@ -838,6 +812,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
838
812
|
|
839
813
|
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
|
840
814
|
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
|
815
|
+
U32 nextToUpdate3 = ms->nextToUpdate;
|
841
816
|
|
842
817
|
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
|
843
818
|
ZSTD_match_t* const matches = optStatePtr->matchTable;
|
@@ -847,7 +822,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
847
822
|
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
|
848
823
|
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
|
849
824
|
assert(optLevel <= 2);
|
850
|
-
ms->nextToUpdate3 = ms->nextToUpdate;
|
851
825
|
ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
|
852
826
|
ip += (ip==prefixStart);
|
853
827
|
|
@@ -858,19 +832,24 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
858
832
|
/* find first match */
|
859
833
|
{ U32 const litlen = (U32)(ip - anchor);
|
860
834
|
U32 const ll0 = !litlen;
|
861
|
-
U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0,
|
835
|
+
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
|
862
836
|
if (!nbMatches) { ip++; continue; }
|
863
837
|
|
864
838
|
/* initialize opt[0] */
|
865
839
|
{ U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
|
866
840
|
opt[0].mlen = 0; /* means is_a_literal */
|
867
841
|
opt[0].litlen = litlen;
|
868
|
-
|
842
|
+
/* We don't need to include the actual price of the literals because
|
843
|
+
* it is static for the duration of the forward pass, and is included
|
844
|
+
* in every price. We include the literal length to avoid negative
|
845
|
+
* prices when we subtract the previous literal length.
|
846
|
+
*/
|
847
|
+
opt[0].price = ZSTD_litLengthPrice(litlen, optStatePtr, optLevel);
|
869
848
|
|
870
849
|
/* large match -> immediate encoding */
|
871
850
|
{ U32 const maxML = matches[nbMatches-1].len;
|
872
851
|
U32 const maxOffset = matches[nbMatches-1].off;
|
873
|
-
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new
|
852
|
+
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
|
874
853
|
nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
|
875
854
|
|
876
855
|
if (maxML > sufficient_len) {
|
@@ -894,7 +873,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
894
873
|
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
|
895
874
|
U32 const offset = matches[matchNb].off;
|
896
875
|
U32 const end = matches[matchNb].len;
|
897
|
-
repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
|
898
876
|
for ( ; pos <= end ; pos++ ) {
|
899
877
|
U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
|
900
878
|
U32 const sequencePrice = literalsPrice + matchPrice;
|
@@ -904,8 +882,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
904
882
|
opt[pos].off = offset;
|
905
883
|
opt[pos].litlen = litlen;
|
906
884
|
opt[pos].price = sequencePrice;
|
907
|
-
ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
|
908
|
-
memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
|
909
885
|
} }
|
910
886
|
last_pos = pos-1;
|
911
887
|
}
|
@@ -932,7 +908,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
932
908
|
opt[cur].off = 0;
|
933
909
|
opt[cur].litlen = litlen;
|
934
910
|
opt[cur].price = price;
|
935
|
-
memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
|
936
911
|
} else {
|
937
912
|
DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
|
938
913
|
inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
|
@@ -940,6 +915,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
940
915
|
}
|
941
916
|
}
|
942
917
|
|
918
|
+
/* Set the repcodes of the current position. We must do it here
|
919
|
+
* because we rely on the repcodes of the 2nd to last sequence being
|
920
|
+
* correct to set the next chunks repcodes during the backward
|
921
|
+
* traversal.
|
922
|
+
*/
|
923
|
+
ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t));
|
924
|
+
assert(cur >= opt[cur].mlen);
|
925
|
+
if (opt[cur].mlen != 0) {
|
926
|
+
U32 const prev = cur - opt[cur].mlen;
|
927
|
+
repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
|
928
|
+
memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
|
929
|
+
} else {
|
930
|
+
memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
|
931
|
+
}
|
932
|
+
|
943
933
|
/* last match must start at a minimum distance of 8 from oend */
|
944
934
|
if (inr > ilimit) continue;
|
945
935
|
|
@@ -955,7 +945,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
955
945
|
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
|
956
946
|
U32 const previousPrice = opt[cur].price;
|
957
947
|
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
|
958
|
-
U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0,
|
948
|
+
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
|
959
949
|
U32 matchNb;
|
960
950
|
if (!nbMatches) {
|
961
951
|
DEBUGLOG(7, "rPos:%u : no match found", cur);
|
@@ -980,7 +970,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
980
970
|
/* set prices using matches found at position == cur */
|
981
971
|
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
|
982
972
|
U32 const offset = matches[matchNb].off;
|
983
|
-
repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0);
|
984
973
|
U32 const lastML = matches[matchNb].len;
|
985
974
|
U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
|
986
975
|
U32 mlen;
|
@@ -1000,8 +989,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
1000
989
|
opt[pos].off = offset;
|
1001
990
|
opt[pos].litlen = litlen;
|
1002
991
|
opt[pos].price = price;
|
1003
|
-
ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
|
1004
|
-
memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
|
1005
992
|
} else {
|
1006
993
|
DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
|
1007
994
|
pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
|
@@ -1017,6 +1004,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
1017
1004
|
_shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
1018
1005
|
assert(opt[0].mlen == 0);
|
1019
1006
|
|
1007
|
+
/* Set the next chunk's repcodes based on the repcodes of the beginning
|
1008
|
+
* of the last match, and the last sequence. This avoids us having to
|
1009
|
+
* update them while traversing the sequences.
|
1010
|
+
*/
|
1011
|
+
if (lastSequence.mlen != 0) {
|
1012
|
+
repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
|
1013
|
+
memcpy(rep, &reps, sizeof(reps));
|
1014
|
+
} else {
|
1015
|
+
memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
|
1016
|
+
}
|
1017
|
+
|
1020
1018
|
{ U32 const storeEnd = cur + 1;
|
1021
1019
|
U32 storeStart = storeEnd;
|
1022
1020
|
U32 seqPos = cur;
|
@@ -1053,33 +1051,18 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
|
1053
1051
|
continue; /* will finish */
|
1054
1052
|
}
|
1055
1053
|
|
1056
|
-
/* repcodes update : like ZSTD_updateRep(), but update in place */
|
1057
|
-
if (offCode >= ZSTD_REP_NUM) { /* full offset */
|
1058
|
-
rep[2] = rep[1];
|
1059
|
-
rep[1] = rep[0];
|
1060
|
-
rep[0] = offCode - ZSTD_REP_MOVE;
|
1061
|
-
} else { /* repcode */
|
1062
|
-
U32 const repCode = offCode + (llen==0);
|
1063
|
-
if (repCode) { /* note : if repCode==0, no change */
|
1064
|
-
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
1065
|
-
if (repCode >= 2) rep[2] = rep[1];
|
1066
|
-
rep[1] = rep[0];
|
1067
|
-
rep[0] = currentOffset;
|
1068
|
-
} }
|
1069
|
-
|
1070
1054
|
assert(anchor + llen <= iend);
|
1071
1055
|
ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
|
1072
|
-
ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
|
1056
|
+
ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
|
1073
1057
|
anchor += advance;
|
1074
1058
|
ip = anchor;
|
1075
1059
|
} }
|
1076
1060
|
ZSTD_setBasePrices(optStatePtr, optLevel);
|
1077
1061
|
}
|
1078
|
-
|
1079
1062
|
} /* while (ip < ilimit) */
|
1080
1063
|
|
1081
1064
|
/* Return the last literals size */
|
1082
|
-
return iend - anchor;
|
1065
|
+
return (size_t)(iend - anchor);
|
1083
1066
|
}
|
1084
1067
|
|
1085
1068
|
|
@@ -1108,7 +1091,8 @@ static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
|
|
1108
1091
|
/* used in 2-pass strategy */
|
1109
1092
|
MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
|
1110
1093
|
{
|
1111
|
-
|
1094
|
+
if (ZSTD_compressedLiterals(optPtr))
|
1095
|
+
optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
|
1112
1096
|
optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
|
1113
1097
|
optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
|
1114
1098
|
optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0);
|
@@ -1117,7 +1101,7 @@ MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
|
|
1117
1101
|
/* ZSTD_initStats_ultra():
|
1118
1102
|
* make a first compression pass, just to seed stats with more accurate starting values.
|
1119
1103
|
* only works on first block, with no dictionary and no ldm.
|
1120
|
-
* this function cannot error, hence its
|
1104
|
+
* this function cannot error, hence its contract must be respected.
|
1121
1105
|
*/
|
1122
1106
|
static void
|
1123
1107
|
ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
@@ -1142,7 +1126,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
|
1142
1126
|
ms->window.dictLimit += (U32)srcSize;
|
1143
1127
|
ms->window.lowLimit = ms->window.dictLimit;
|
1144
1128
|
ms->nextToUpdate = ms->window.dictLimit;
|
1145
|
-
ms->nextToUpdate3 = ms->window.dictLimit;
|
1146
1129
|
|
1147
1130
|
/* re-inforce weight of collected statistics */
|
1148
1131
|
ZSTD_upscaleStats(&ms->opt);
|