extzstd 0.3 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.ja.md +8 -0
- data/README.md +1 -1
- data/contrib/zstd/CHANGELOG +94 -0
- data/contrib/zstd/CONTRIBUTING.md +351 -1
- data/contrib/zstd/Makefile +32 -10
- data/contrib/zstd/README.md +33 -10
- data/contrib/zstd/TESTING.md +2 -2
- data/contrib/zstd/appveyor.yml +42 -4
- data/contrib/zstd/lib/Makefile +128 -60
- data/contrib/zstd/lib/README.md +47 -16
- data/contrib/zstd/lib/common/bitstream.h +38 -39
- data/contrib/zstd/lib/common/compiler.h +40 -5
- data/contrib/zstd/lib/common/cpu.h +1 -1
- data/contrib/zstd/lib/common/debug.c +11 -31
- data/contrib/zstd/lib/common/debug.h +11 -31
- data/contrib/zstd/lib/common/entropy_common.c +13 -33
- data/contrib/zstd/lib/common/error_private.c +2 -1
- data/contrib/zstd/lib/common/error_private.h +6 -2
- data/contrib/zstd/lib/common/fse.h +12 -32
- data/contrib/zstd/lib/common/fse_decompress.c +12 -35
- data/contrib/zstd/lib/common/huf.h +15 -33
- data/contrib/zstd/lib/common/mem.h +75 -2
- data/contrib/zstd/lib/common/pool.c +8 -4
- data/contrib/zstd/lib/common/pool.h +2 -2
- data/contrib/zstd/lib/common/threading.c +50 -4
- data/contrib/zstd/lib/common/threading.h +36 -4
- data/contrib/zstd/lib/common/xxhash.c +23 -35
- data/contrib/zstd/lib/common/xxhash.h +11 -31
- data/contrib/zstd/lib/common/zstd_common.c +1 -1
- data/contrib/zstd/lib/common/zstd_errors.h +2 -1
- data/contrib/zstd/lib/common/zstd_internal.h +154 -26
- data/contrib/zstd/lib/compress/fse_compress.c +17 -40
- data/contrib/zstd/lib/compress/hist.c +15 -35
- data/contrib/zstd/lib/compress/hist.h +12 -32
- data/contrib/zstd/lib/compress/huf_compress.c +92 -92
- data/contrib/zstd/lib/compress/zstd_compress.c +1191 -1330
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +317 -55
- data/contrib/zstd/lib/compress/zstd_compress_literals.c +158 -0
- data/contrib/zstd/lib/compress/zstd_compress_literals.h +29 -0
- data/contrib/zstd/lib/compress/zstd_compress_sequences.c +419 -0
- data/contrib/zstd/lib/compress/zstd_compress_sequences.h +54 -0
- data/contrib/zstd/lib/compress/zstd_compress_superblock.c +845 -0
- data/contrib/zstd/lib/compress/zstd_compress_superblock.h +32 -0
- data/contrib/zstd/lib/compress/zstd_cwksp.h +525 -0
- data/contrib/zstd/lib/compress/zstd_double_fast.c +65 -43
- data/contrib/zstd/lib/compress/zstd_double_fast.h +2 -2
- data/contrib/zstd/lib/compress/zstd_fast.c +92 -66
- data/contrib/zstd/lib/compress/zstd_fast.h +2 -2
- data/contrib/zstd/lib/compress/zstd_lazy.c +74 -42
- data/contrib/zstd/lib/compress/zstd_lazy.h +1 -1
- data/contrib/zstd/lib/compress/zstd_ldm.c +32 -10
- data/contrib/zstd/lib/compress/zstd_ldm.h +7 -2
- data/contrib/zstd/lib/compress/zstd_opt.c +81 -114
- data/contrib/zstd/lib/compress/zstd_opt.h +1 -1
- data/contrib/zstd/lib/compress/zstdmt_compress.c +95 -51
- data/contrib/zstd/lib/compress/zstdmt_compress.h +3 -2
- data/contrib/zstd/lib/decompress/huf_decompress.c +76 -60
- data/contrib/zstd/lib/decompress/zstd_ddict.c +12 -8
- data/contrib/zstd/lib/decompress/zstd_ddict.h +2 -2
- data/contrib/zstd/lib/decompress/zstd_decompress.c +292 -172
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +459 -338
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +3 -3
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +18 -4
- data/contrib/zstd/lib/deprecated/zbuff.h +9 -8
- data/contrib/zstd/lib/deprecated/zbuff_common.c +2 -2
- data/contrib/zstd/lib/deprecated/zbuff_compress.c +1 -1
- data/contrib/zstd/lib/deprecated/zbuff_decompress.c +1 -1
- data/contrib/zstd/lib/dictBuilder/cover.c +164 -54
- data/contrib/zstd/lib/dictBuilder/cover.h +52 -7
- data/contrib/zstd/lib/dictBuilder/fastcover.c +60 -43
- data/contrib/zstd/lib/dictBuilder/zdict.c +43 -19
- data/contrib/zstd/lib/dictBuilder/zdict.h +56 -28
- data/contrib/zstd/lib/legacy/zstd_legacy.h +8 -4
- data/contrib/zstd/lib/legacy/zstd_v01.c +110 -110
- data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v02.c +23 -13
- data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v03.c +23 -13
- data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v04.c +30 -17
- data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v05.c +113 -102
- data/contrib/zstd/lib/legacy/zstd_v05.h +2 -2
- data/contrib/zstd/lib/legacy/zstd_v06.c +20 -18
- data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v07.c +25 -19
- data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
- data/contrib/zstd/lib/libzstd.pc.in +3 -2
- data/contrib/zstd/lib/zstd.h +265 -88
- data/ext/extzstd.h +1 -1
- data/ext/libzstd_conf.h +8 -0
- data/ext/zstd_common.c +1 -3
- data/ext/zstd_compress.c +3 -3
- data/ext/zstd_decompress.c +1 -5
- data/ext/zstd_dictbuilder.c +2 -3
- data/ext/zstd_dictbuilder_fastcover.c +1 -3
- data/ext/zstd_legacy_v01.c +2 -0
- data/ext/zstd_legacy_v02.c +2 -0
- data/ext/zstd_legacy_v03.c +2 -0
- data/ext/zstd_legacy_v04.c +2 -0
- data/ext/zstd_legacy_v05.c +2 -0
- data/ext/zstd_legacy_v06.c +2 -0
- data/ext/zstd_legacy_v07.c +2 -0
- data/lib/extzstd.rb +18 -10
- data/lib/extzstd/version.rb +1 -1
- metadata +15 -6
@@ -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
|
@@ -249,40 +249,6 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
|
|
249
249
|
}
|
250
250
|
}
|
251
251
|
|
252
|
-
/* ZSTD_litLengthContribution() :
|
253
|
-
* @return ( cost(litlength) - cost(0) )
|
254
|
-
* this value can then be added to rawLiteralsCost()
|
255
|
-
* to provide a cost which is directly comparable to a match ending at same position */
|
256
|
-
static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
|
257
|
-
{
|
258
|
-
if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
|
259
|
-
|
260
|
-
/* dynamic statistics */
|
261
|
-
{ U32 const llCode = ZSTD_LLcode(litLength);
|
262
|
-
int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
|
263
|
-
+ WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
|
264
|
-
- WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
|
265
|
-
#if 1
|
266
|
-
return contribution;
|
267
|
-
#else
|
268
|
-
return MAX(0, contribution); /* sometimes better, sometimes not ... */
|
269
|
-
#endif
|
270
|
-
}
|
271
|
-
}
|
272
|
-
|
273
|
-
/* ZSTD_literalsContribution() :
|
274
|
-
* creates a fake cost for the literals part of a sequence
|
275
|
-
* which can be compared to the ending cost of a match
|
276
|
-
* should a new match start at this position */
|
277
|
-
static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength,
|
278
|
-
const optState_t* const optPtr,
|
279
|
-
int optLevel)
|
280
|
-
{
|
281
|
-
int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
|
282
|
-
+ ZSTD_litLengthContribution(litLength, optPtr, optLevel);
|
283
|
-
return contribution;
|
284
|
-
}
|
285
|
-
|
286
252
|
/* ZSTD_getMatchPrice() :
|
287
253
|
* Provides the cost of the match part (offset + matchLength) of a sequence
|
288
254
|
* Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
|
@@ -372,13 +338,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
|
|
372
338
|
|
373
339
|
/* Update hashTable3 up to ip (excluded)
|
374
340
|
Assumption : always within prefix (i.e. not within extDict) */
|
375
|
-
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)
|
376
344
|
{
|
377
345
|
U32* const hashTable3 = ms->hashTable3;
|
378
346
|
U32 const hashLog3 = ms->hashLog3;
|
379
347
|
const BYTE* const base = ms->window.base;
|
380
|
-
U32 idx =
|
381
|
-
U32 const target =
|
348
|
+
U32 idx = *nextToUpdate3;
|
349
|
+
U32 const target = (U32)(ip - base);
|
382
350
|
size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
|
383
351
|
assert(hashLog3 > 0);
|
384
352
|
|
@@ -387,6 +355,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
|
|
387
355
|
idx++;
|
388
356
|
}
|
389
357
|
|
358
|
+
*nextToUpdate3 = target;
|
390
359
|
return hashTable3[hash3];
|
391
360
|
}
|
392
361
|
|
@@ -503,9 +472,11 @@ static U32 ZSTD_insertBt1(
|
|
503
472
|
} }
|
504
473
|
|
505
474
|
*smallerPtr = *largerPtr = 0;
|
506
|
-
|
507
|
-
|
508
|
-
|
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
|
+
}
|
509
480
|
}
|
510
481
|
|
511
482
|
FORCE_INLINE_TEMPLATE
|
@@ -520,8 +491,13 @@ void ZSTD_updateTree_internal(
|
|
520
491
|
DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
|
521
492
|
idx, target, dictMode);
|
522
493
|
|
523
|
-
while(idx < target)
|
524
|
-
|
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));
|
525
501
|
ms->nextToUpdate = target;
|
526
502
|
}
|
527
503
|
|
@@ -531,11 +507,12 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
|
|
531
507
|
|
532
508
|
FORCE_INLINE_TEMPLATE
|
533
509
|
U32 ZSTD_insertBtAndGetAllMatches (
|
510
|
+
ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
|
534
511
|
ZSTD_matchState_t* ms,
|
512
|
+
U32* nextToUpdate3,
|
535
513
|
const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
|
536
|
-
U32 rep[ZSTD_REP_NUM],
|
514
|
+
const U32 rep[ZSTD_REP_NUM],
|
537
515
|
U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
|
538
|
-
ZSTD_match_t* matches,
|
539
516
|
const U32 lengthToBeat,
|
540
517
|
U32 const mls /* template */)
|
541
518
|
{
|
@@ -556,8 +533,8 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
556
533
|
U32 const dictLimit = ms->window.dictLimit;
|
557
534
|
const BYTE* const dictEnd = dictBase + dictLimit;
|
558
535
|
const BYTE* const prefixStart = base + dictLimit;
|
559
|
-
U32 const btLow = btMask >= current ? 0 : current - btMask;
|
560
|
-
U32 const windowLow = ms->
|
536
|
+
U32 const btLow = (btMask >= current) ? 0 : current - btMask;
|
537
|
+
U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog);
|
561
538
|
U32 const matchLow = windowLow ? windowLow : 1;
|
562
539
|
U32* smallerPtr = bt + 2*(current&btMask);
|
563
540
|
U32* largerPtr = bt + 2*(current&btMask) + 1;
|
@@ -592,7 +569,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
592
569
|
U32 repLen = 0;
|
593
570
|
assert(current >= dictLimit);
|
594
571
|
if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */
|
595
|
-
|
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))) {
|
596
576
|
repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
|
597
577
|
}
|
598
578
|
} else { /* repIndex < dictLimit || repIndex >= current */
|
@@ -627,7 +607,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
627
607
|
|
628
608
|
/* HC3 match finder */
|
629
609
|
if ((mls == 3) /*static*/ && (bestLength < mls)) {
|
630
|
-
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
|
610
|
+
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
|
631
611
|
if ((matchIndex3 >= matchLow)
|
632
612
|
& (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
|
633
613
|
size_t mlen;
|
@@ -653,9 +633,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
653
633
|
(ip+mlen == iLimit) ) { /* best possible length */
|
654
634
|
ms->nextToUpdate = current+1; /* skip insertion */
|
655
635
|
return 1;
|
656
|
-
|
657
|
-
}
|
658
|
-
}
|
636
|
+
} } }
|
659
637
|
/* no dictMatchState lookup: dicts don't have a populated HC3 table */
|
660
638
|
}
|
661
639
|
|
@@ -663,19 +641,21 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
663
641
|
|
664
642
|
while (nbCompares-- && (matchIndex >= matchLow)) {
|
665
643
|
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
666
|
-
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
667
644
|
const BYTE* match;
|
645
|
+
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
668
646
|
assert(current > matchIndex);
|
669
647
|
|
670
648
|
if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
|
671
649
|
assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
|
672
650
|
match = base + matchIndex;
|
651
|
+
if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
|
673
652
|
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);
|
674
653
|
} else {
|
675
654
|
match = dictBase + matchIndex;
|
655
|
+
assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
|
676
656
|
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
|
677
657
|
if (matchIndex+matchLength >= dictLimit)
|
678
|
-
match = base + matchIndex; /* prepare for match[matchLength] */
|
658
|
+
match = base + matchIndex; /* prepare for match[matchLength] read */
|
679
659
|
}
|
680
660
|
|
681
661
|
if (matchLength > bestLength) {
|
@@ -760,10 +740,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
760
740
|
|
761
741
|
|
762
742
|
FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
743
|
+
ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
|
763
744
|
ZSTD_matchState_t* ms,
|
745
|
+
U32* nextToUpdate3,
|
764
746
|
const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
|
765
|
-
U32 rep[ZSTD_REP_NUM],
|
766
|
-
|
747
|
+
const U32 rep[ZSTD_REP_NUM],
|
748
|
+
U32 const ll0,
|
749
|
+
U32 const lengthToBeat)
|
767
750
|
{
|
768
751
|
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
769
752
|
U32 const matchLengthSearch = cParams->minMatch;
|
@@ -772,12 +755,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
|
772
755
|
ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
|
773
756
|
switch(matchLengthSearch)
|
774
757
|
{
|
775
|
-
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);
|
776
759
|
default :
|
777
|
-
case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0,
|
778
|
-
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);
|
779
762
|
case 7 :
|
780
|
-
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);
|
781
764
|
}
|
782
765
|
}
|
783
766
|
|
@@ -785,30 +768,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
|
785
768
|
/*-*******************************
|
786
769
|
* Optimal parser
|
787
770
|
*********************************/
|
788
|
-
typedef struct repcodes_s {
|
789
|
-
U32 rep[3];
|
790
|
-
} repcodes_t;
|
791
|
-
|
792
|
-
static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
|
793
|
-
{
|
794
|
-
repcodes_t newReps;
|
795
|
-
if (offset >= ZSTD_REP_NUM) { /* full offset */
|
796
|
-
newReps.rep[2] = rep[1];
|
797
|
-
newReps.rep[1] = rep[0];
|
798
|
-
newReps.rep[0] = offset - ZSTD_REP_MOVE;
|
799
|
-
} else { /* repcode */
|
800
|
-
U32 const repCode = offset + ll0;
|
801
|
-
if (repCode > 0) { /* note : if repCode==0, no change */
|
802
|
-
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
803
|
-
newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
|
804
|
-
newReps.rep[1] = rep[0];
|
805
|
-
newReps.rep[0] = currentOffset;
|
806
|
-
} else { /* repCode == 0 */
|
807
|
-
memcpy(&newReps, rep, sizeof(newReps));
|
808
|
-
}
|
809
|
-
}
|
810
|
-
return newReps;
|
811
|
-
}
|
812
771
|
|
813
772
|
|
814
773
|
static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
|
@@ -825,7 +784,7 @@ listStats(const U32* table, int lastEltID)
|
|
825
784
|
int enb;
|
826
785
|
for (enb=0; enb < nbElts; enb++) {
|
827
786
|
(void)table;
|
828
|
-
|
787
|
+
/* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */
|
829
788
|
RAWLOG(2, "%4i,", table[enb]);
|
830
789
|
}
|
831
790
|
RAWLOG(2, " \n");
|
@@ -853,6 +812,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
853
812
|
|
854
813
|
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
|
855
814
|
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
|
815
|
+
U32 nextToUpdate3 = ms->nextToUpdate;
|
856
816
|
|
857
817
|
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
|
858
818
|
ZSTD_match_t* const matches = optStatePtr->matchTable;
|
@@ -862,7 +822,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
862
822
|
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
|
863
823
|
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
|
864
824
|
assert(optLevel <= 2);
|
865
|
-
ms->nextToUpdate3 = ms->nextToUpdate;
|
866
825
|
ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
|
867
826
|
ip += (ip==prefixStart);
|
868
827
|
|
@@ -873,14 +832,19 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
873
832
|
/* find first match */
|
874
833
|
{ U32 const litlen = (U32)(ip - anchor);
|
875
834
|
U32 const ll0 = !litlen;
|
876
|
-
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);
|
877
836
|
if (!nbMatches) { ip++; continue; }
|
878
837
|
|
879
838
|
/* initialize opt[0] */
|
880
839
|
{ U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
|
881
840
|
opt[0].mlen = 0; /* means is_a_literal */
|
882
841
|
opt[0].litlen = litlen;
|
883
|
-
|
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);
|
884
848
|
|
885
849
|
/* large match -> immediate encoding */
|
886
850
|
{ U32 const maxML = matches[nbMatches-1].len;
|
@@ -909,7 +873,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
909
873
|
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
|
910
874
|
U32 const offset = matches[matchNb].off;
|
911
875
|
U32 const end = matches[matchNb].len;
|
912
|
-
repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
|
913
876
|
for ( ; pos <= end ; pos++ ) {
|
914
877
|
U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
|
915
878
|
U32 const sequencePrice = literalsPrice + matchPrice;
|
@@ -919,8 +882,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
919
882
|
opt[pos].off = offset;
|
920
883
|
opt[pos].litlen = litlen;
|
921
884
|
opt[pos].price = sequencePrice;
|
922
|
-
ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
|
923
|
-
memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
|
924
885
|
} }
|
925
886
|
last_pos = pos-1;
|
926
887
|
}
|
@@ -947,7 +908,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
947
908
|
opt[cur].off = 0;
|
948
909
|
opt[cur].litlen = litlen;
|
949
910
|
opt[cur].price = price;
|
950
|
-
memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
|
951
911
|
} else {
|
952
912
|
DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
|
953
913
|
inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
|
@@ -955,6 +915,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
955
915
|
}
|
956
916
|
}
|
957
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
|
+
|
958
933
|
/* last match must start at a minimum distance of 8 from oend */
|
959
934
|
if (inr > ilimit) continue;
|
960
935
|
|
@@ -970,7 +945,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
970
945
|
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
|
971
946
|
U32 const previousPrice = opt[cur].price;
|
972
947
|
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
|
973
|
-
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);
|
974
949
|
U32 matchNb;
|
975
950
|
if (!nbMatches) {
|
976
951
|
DEBUGLOG(7, "rPos:%u : no match found", cur);
|
@@ -995,7 +970,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
995
970
|
/* set prices using matches found at position == cur */
|
996
971
|
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
|
997
972
|
U32 const offset = matches[matchNb].off;
|
998
|
-
repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0);
|
999
973
|
U32 const lastML = matches[matchNb].len;
|
1000
974
|
U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
|
1001
975
|
U32 mlen;
|
@@ -1015,8 +989,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
1015
989
|
opt[pos].off = offset;
|
1016
990
|
opt[pos].litlen = litlen;
|
1017
991
|
opt[pos].price = price;
|
1018
|
-
ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
|
1019
|
-
memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
|
1020
992
|
} else {
|
1021
993
|
DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
|
1022
994
|
pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
|
@@ -1032,6 +1004,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
1032
1004
|
_shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
1033
1005
|
assert(opt[0].mlen == 0);
|
1034
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
|
+
|
1035
1018
|
{ U32 const storeEnd = cur + 1;
|
1036
1019
|
U32 storeStart = storeEnd;
|
1037
1020
|
U32 seqPos = cur;
|
@@ -1068,33 +1051,18 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
|
1068
1051
|
continue; /* will finish */
|
1069
1052
|
}
|
1070
1053
|
|
1071
|
-
/* repcodes update : like ZSTD_updateRep(), but update in place */
|
1072
|
-
if (offCode >= ZSTD_REP_NUM) { /* full offset */
|
1073
|
-
rep[2] = rep[1];
|
1074
|
-
rep[1] = rep[0];
|
1075
|
-
rep[0] = offCode - ZSTD_REP_MOVE;
|
1076
|
-
} else { /* repcode */
|
1077
|
-
U32 const repCode = offCode + (llen==0);
|
1078
|
-
if (repCode) { /* note : if repCode==0, no change */
|
1079
|
-
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
|
1080
|
-
if (repCode >= 2) rep[2] = rep[1];
|
1081
|
-
rep[1] = rep[0];
|
1082
|
-
rep[0] = currentOffset;
|
1083
|
-
} }
|
1084
|
-
|
1085
1054
|
assert(anchor + llen <= iend);
|
1086
1055
|
ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
|
1087
|
-
ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
|
1056
|
+
ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
|
1088
1057
|
anchor += advance;
|
1089
1058
|
ip = anchor;
|
1090
1059
|
} }
|
1091
1060
|
ZSTD_setBasePrices(optStatePtr, optLevel);
|
1092
1061
|
}
|
1093
|
-
|
1094
1062
|
} /* while (ip < ilimit) */
|
1095
1063
|
|
1096
1064
|
/* Return the last literals size */
|
1097
|
-
return iend - anchor;
|
1065
|
+
return (size_t)(iend - anchor);
|
1098
1066
|
}
|
1099
1067
|
|
1100
1068
|
|
@@ -1158,7 +1126,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
|
1158
1126
|
ms->window.dictLimit += (U32)srcSize;
|
1159
1127
|
ms->window.lowLimit = ms->window.dictLimit;
|
1160
1128
|
ms->nextToUpdate = ms->window.dictLimit;
|
1161
|
-
ms->nextToUpdate3 = ms->window.dictLimit;
|
1162
1129
|
|
1163
1130
|
/* re-inforce weight of collected statistics */
|
1164
1131
|
ZSTD_upscaleStats(&ms->opt);
|