zstd-ruby 1.3.4.0 → 1.3.5.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 +56 -10
- data/ext/zstdruby/libzstd/README.md +4 -0
- data/ext/zstdruby/libzstd/common/bitstream.h +6 -19
- data/ext/zstdruby/libzstd/common/compiler.h +3 -3
- data/ext/zstdruby/libzstd/common/cpu.h +1 -2
- data/ext/zstdruby/libzstd/common/debug.c +44 -0
- data/ext/zstdruby/libzstd/common/debug.h +123 -0
- data/ext/zstdruby/libzstd/common/entropy_common.c +16 -1
- data/ext/zstdruby/libzstd/common/fse.h +45 -41
- data/ext/zstdruby/libzstd/common/fse_decompress.c +1 -1
- data/ext/zstdruby/libzstd/common/huf.h +34 -27
- data/ext/zstdruby/libzstd/common/pool.c +89 -32
- data/ext/zstdruby/libzstd/common/pool.h +29 -19
- data/ext/zstdruby/libzstd/common/zstd_common.c +0 -5
- data/ext/zstdruby/libzstd/common/zstd_internal.h +3 -37
- data/ext/zstdruby/libzstd/compress/fse_compress.c +28 -163
- data/ext/zstdruby/libzstd/compress/hist.c +195 -0
- data/ext/zstdruby/libzstd/compress/hist.h +92 -0
- data/ext/zstdruby/libzstd/compress/huf_compress.c +14 -6
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +798 -350
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +120 -34
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +247 -87
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +4 -1
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +177 -56
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +4 -1
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +331 -65
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +13 -0
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +15 -20
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +1 -2
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +503 -300
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +7 -0
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +122 -47
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +5 -5
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +325 -325
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +80 -43
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +9 -2
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +5 -5
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +12 -61
- data/ext/zstdruby/libzstd/zstd.h +137 -69
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +7 -3
@@ -27,6 +27,7 @@
|
|
27
27
|
extern "C" {
|
28
28
|
#endif
|
29
29
|
|
30
|
+
|
30
31
|
/*-*************************************
|
31
32
|
* Constants
|
32
33
|
***************************************/
|
@@ -37,7 +38,8 @@ extern "C" {
|
|
37
38
|
It's not a big deal though : candidate will just be sorted again.
|
38
39
|
Additionnally, candidate position 1 will be lost.
|
39
40
|
But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
|
40
|
-
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy
|
41
|
+
The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy
|
42
|
+
Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
|
41
43
|
|
42
44
|
|
43
45
|
/*-*************************************
|
@@ -46,6 +48,12 @@ extern "C" {
|
|
46
48
|
typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
|
47
49
|
typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
|
48
50
|
|
51
|
+
typedef enum {
|
52
|
+
ZSTD_dictDefaultAttach = 0,
|
53
|
+
ZSTD_dictForceAttach = 1,
|
54
|
+
ZSTD_dictForceCopy = -1,
|
55
|
+
} ZSTD_dictAttachPref_e;
|
56
|
+
|
49
57
|
typedef struct ZSTD_prefixDict_s {
|
50
58
|
const void* dict;
|
51
59
|
size_t dictSize;
|
@@ -53,14 +61,22 @@ typedef struct ZSTD_prefixDict_s {
|
|
53
61
|
} ZSTD_prefixDict;
|
54
62
|
|
55
63
|
typedef struct {
|
56
|
-
U32
|
64
|
+
U32 CTable[HUF_CTABLE_SIZE_U32(255)];
|
65
|
+
HUF_repeat repeatMode;
|
66
|
+
} ZSTD_hufCTables_t;
|
67
|
+
|
68
|
+
typedef struct {
|
57
69
|
FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
|
58
70
|
FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
|
59
71
|
FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
|
60
|
-
HUF_repeat hufCTable_repeatMode;
|
61
72
|
FSE_repeat offcode_repeatMode;
|
62
73
|
FSE_repeat matchlength_repeatMode;
|
63
74
|
FSE_repeat litlength_repeatMode;
|
75
|
+
} ZSTD_fseCTables_t;
|
76
|
+
|
77
|
+
typedef struct {
|
78
|
+
ZSTD_hufCTables_t huf;
|
79
|
+
ZSTD_fseCTables_t fse;
|
64
80
|
} ZSTD_entropyCTables_t;
|
65
81
|
|
66
82
|
typedef struct {
|
@@ -76,26 +92,27 @@ typedef struct {
|
|
76
92
|
U32 rep[ZSTD_REP_NUM];
|
77
93
|
} ZSTD_optimal_t;
|
78
94
|
|
95
|
+
typedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;
|
96
|
+
|
79
97
|
typedef struct {
|
80
98
|
/* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */
|
81
|
-
U32* litFreq;
|
82
|
-
U32* litLengthFreq;
|
83
|
-
U32* matchLengthFreq;
|
84
|
-
U32* offCodeFreq;
|
85
|
-
ZSTD_match_t* matchTable;
|
86
|
-
ZSTD_optimal_t* priceTable;
|
99
|
+
U32* litFreq; /* table of literals statistics, of size 256 */
|
100
|
+
U32* litLengthFreq; /* table of litLength statistics, of size (MaxLL+1) */
|
101
|
+
U32* matchLengthFreq; /* table of matchLength statistics, of size (MaxML+1) */
|
102
|
+
U32* offCodeFreq; /* table of offCode statistics, of size (MaxOff+1) */
|
103
|
+
ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_NUM+1 */
|
104
|
+
ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_NUM+1 */
|
87
105
|
|
88
106
|
U32 litSum; /* nb of literals */
|
89
107
|
U32 litLengthSum; /* nb of litLength codes */
|
90
108
|
U32 matchLengthSum; /* nb of matchLength codes */
|
91
109
|
U32 offCodeSum; /* nb of offset codes */
|
92
|
-
/*
|
93
|
-
U32
|
94
|
-
U32
|
95
|
-
U32
|
96
|
-
|
97
|
-
|
98
|
-
U32 staticPrices; /* prices follow a pre-defined cost structure, statistics are irrelevant */
|
110
|
+
U32 litSumBasePrice; /* to compare to log2(litfreq) */
|
111
|
+
U32 litLengthSumBasePrice; /* to compare to log2(llfreq) */
|
112
|
+
U32 matchLengthSumBasePrice;/* to compare to log2(mlfreq) */
|
113
|
+
U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
|
114
|
+
ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
|
115
|
+
const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
|
99
116
|
} optState_t;
|
100
117
|
|
101
118
|
typedef struct {
|
@@ -111,17 +128,19 @@ typedef struct {
|
|
111
128
|
U32 lowLimit; /* below that point, no more data */
|
112
129
|
} ZSTD_window_t;
|
113
130
|
|
114
|
-
typedef struct
|
115
|
-
|
116
|
-
|
117
|
-
U32
|
118
|
-
U32
|
119
|
-
U32
|
131
|
+
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
|
132
|
+
struct ZSTD_matchState_t {
|
133
|
+
ZSTD_window_t window; /* State for window round buffer management */
|
134
|
+
U32 loadedDictEnd; /* index of end of dictionary */
|
135
|
+
U32 nextToUpdate; /* index from which to continue table update */
|
136
|
+
U32 nextToUpdate3; /* index from which to continue table update */
|
137
|
+
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
120
138
|
U32* hashTable;
|
121
139
|
U32* hashTable3;
|
122
140
|
U32* chainTable;
|
123
141
|
optState_t opt; /* optimal parser state */
|
124
|
-
|
142
|
+
const ZSTD_matchState_t *dictMatchState;
|
143
|
+
};
|
125
144
|
|
126
145
|
typedef struct {
|
127
146
|
ZSTD_compressedBlockState_t* prevCBlock;
|
@@ -161,7 +180,7 @@ typedef struct {
|
|
161
180
|
rawSeq* seq; /* The start of the sequences */
|
162
181
|
size_t pos; /* The position where reading stopped. <= size. */
|
163
182
|
size_t size; /* The number of sequences. <= capacity. */
|
164
|
-
size_t capacity; /* The capacity
|
183
|
+
size_t capacity; /* The capacity starting from `seq` pointer */
|
165
184
|
} rawSeqStore_t;
|
166
185
|
|
167
186
|
struct ZSTD_CCtx_params_s {
|
@@ -170,10 +189,11 @@ struct ZSTD_CCtx_params_s {
|
|
170
189
|
ZSTD_frameParameters fParams;
|
171
190
|
|
172
191
|
int compressionLevel;
|
173
|
-
int disableLiteralCompression;
|
174
192
|
int forceWindow; /* force back-references to respect limit of
|
175
193
|
* 1<<wLog, even for dictionary */
|
176
194
|
|
195
|
+
ZSTD_dictAttachPref_e attachDictPref;
|
196
|
+
|
177
197
|
/* Multithreading: used to pass parameters to mtctx */
|
178
198
|
unsigned nbWorkers;
|
179
199
|
unsigned jobSize;
|
@@ -193,6 +213,8 @@ struct ZSTD_CCtx_s {
|
|
193
213
|
ZSTD_CCtx_params requestedParams;
|
194
214
|
ZSTD_CCtx_params appliedParams;
|
195
215
|
U32 dictID;
|
216
|
+
|
217
|
+
int workSpaceOversizedDuration;
|
196
218
|
void* workSpace;
|
197
219
|
size_t workSpaceSize;
|
198
220
|
size_t blockSize;
|
@@ -235,11 +257,15 @@ struct ZSTD_CCtx_s {
|
|
235
257
|
#endif
|
236
258
|
};
|
237
259
|
|
260
|
+
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
|
261
|
+
|
262
|
+
typedef enum { ZSTD_noDict = 0, ZSTD_extDict = 1, ZSTD_dictMatchState = 2 } ZSTD_dictMode_e;
|
263
|
+
|
238
264
|
|
239
265
|
typedef size_t (*ZSTD_blockCompressor) (
|
240
266
|
ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
241
267
|
ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
|
242
|
-
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat,
|
268
|
+
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode);
|
243
269
|
|
244
270
|
|
245
271
|
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
|
@@ -280,11 +306,11 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
|
|
280
306
|
*/
|
281
307
|
MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t mlBase)
|
282
308
|
{
|
283
|
-
#if defined(
|
309
|
+
#if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)
|
284
310
|
static const BYTE* g_start = NULL;
|
285
311
|
if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */
|
286
312
|
{ U32 const pos = (U32)((const BYTE*)literals - g_start);
|
287
|
-
DEBUGLOG(6, "Cpos%7u :%3u literals, match%
|
313
|
+
DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
|
288
314
|
pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offsetCode);
|
289
315
|
}
|
290
316
|
#endif
|
@@ -420,6 +446,11 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match,
|
|
420
446
|
const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
|
421
447
|
size_t const matchLength = ZSTD_count(ip, match, vEnd);
|
422
448
|
if (match + matchLength != mEnd) return matchLength;
|
449
|
+
DEBUGLOG(7, "ZSTD_count_2segments: found a 2-parts match (current length==%zu)", matchLength);
|
450
|
+
DEBUGLOG(7, "distance from match beginning to end dictionary = %zi", mEnd - match);
|
451
|
+
DEBUGLOG(7, "distance from current pos to end buffer = %zi", iEnd - ip);
|
452
|
+
DEBUGLOG(7, "next byte : ip==%02X, istart==%02X", ip[matchLength], *iStart);
|
453
|
+
DEBUGLOG(7, "final match length = %zu", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd));
|
423
454
|
return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
|
424
455
|
}
|
425
456
|
|
@@ -496,6 +527,20 @@ MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)
|
|
496
527
|
return window.lowLimit < window.dictLimit;
|
497
528
|
}
|
498
529
|
|
530
|
+
/**
|
531
|
+
* ZSTD_matchState_dictMode():
|
532
|
+
* Inspects the provided matchState and figures out what dictMode should be
|
533
|
+
* passed to the compressor.
|
534
|
+
*/
|
535
|
+
MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
|
536
|
+
{
|
537
|
+
return ZSTD_window_hasExtDict(ms->window) ?
|
538
|
+
ZSTD_extDict :
|
539
|
+
ms->dictMatchState != NULL ?
|
540
|
+
ZSTD_dictMatchState :
|
541
|
+
ZSTD_noDict;
|
542
|
+
}
|
543
|
+
|
499
544
|
/**
|
500
545
|
* ZSTD_window_needOverflowCorrection():
|
501
546
|
* Returns non-zero if the indices are getting too large and need overflow
|
@@ -563,31 +608,41 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
|
563
608
|
* ZSTD_window_enforceMaxDist():
|
564
609
|
* Updates lowLimit so that:
|
565
610
|
* (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
|
611
|
+
*
|
566
612
|
* This allows a simple check that index >= lowLimit to see if index is valid.
|
567
613
|
* This must be called before a block compression call, with srcEnd as the block
|
568
614
|
* source end.
|
615
|
+
*
|
569
616
|
* If loadedDictEndPtr is not NULL, we set it to zero once we update lowLimit.
|
570
617
|
* This is because dictionaries are allowed to be referenced as long as the last
|
571
618
|
* byte of the dictionary is in the window, but once they are out of range,
|
572
619
|
* they cannot be referenced. If loadedDictEndPtr is NULL, we use
|
573
620
|
* loadedDictEnd == 0.
|
621
|
+
*
|
622
|
+
* In normal dict mode, the dict is between lowLimit and dictLimit. In
|
623
|
+
* dictMatchState mode, lowLimit and dictLimit are the same, and the dictionary
|
624
|
+
* is below them. forceWindow and dictMatchState are therefore incompatible.
|
574
625
|
*/
|
575
626
|
MEM_STATIC void ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
|
576
627
|
void const* srcEnd, U32 maxDist,
|
577
|
-
U32* loadedDictEndPtr
|
628
|
+
U32* loadedDictEndPtr,
|
629
|
+
const ZSTD_matchState_t** dictMatchStatePtr)
|
578
630
|
{
|
579
631
|
U32 const current = (U32)((BYTE const*)srcEnd - window->base);
|
580
632
|
U32 loadedDictEnd = loadedDictEndPtr != NULL ? *loadedDictEndPtr : 0;
|
633
|
+
DEBUGLOG(5, "ZSTD_window_enforceMaxDist: current=%u, maxDist=%u", current, maxDist);
|
581
634
|
if (current > maxDist + loadedDictEnd) {
|
582
635
|
U32 const newLowLimit = current - maxDist;
|
583
636
|
if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
|
584
637
|
if (window->dictLimit < window->lowLimit) {
|
585
|
-
DEBUGLOG(5, "Update dictLimit from %u to %u",
|
586
|
-
|
638
|
+
DEBUGLOG(5, "Update dictLimit to match lowLimit, from %u to %u",
|
639
|
+
window->dictLimit, window->lowLimit);
|
587
640
|
window->dictLimit = window->lowLimit;
|
588
641
|
}
|
589
642
|
if (loadedDictEndPtr)
|
590
643
|
*loadedDictEndPtr = 0;
|
644
|
+
if (dictMatchStatePtr)
|
645
|
+
*dictMatchStatePtr = NULL;
|
591
646
|
}
|
592
647
|
}
|
593
648
|
|
@@ -603,12 +658,12 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
|
603
658
|
{
|
604
659
|
BYTE const* const ip = (BYTE const*)src;
|
605
660
|
U32 contiguous = 1;
|
661
|
+
DEBUGLOG(5, "ZSTD_window_update");
|
606
662
|
/* Check if blocks follow each other */
|
607
663
|
if (src != window->nextSrc) {
|
608
664
|
/* not contiguous */
|
609
665
|
size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
|
610
|
-
DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u",
|
611
|
-
window->dictLimit);
|
666
|
+
DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
|
612
667
|
window->lowLimit = window->dictLimit;
|
613
668
|
assert(distanceFromBase == (size_t)(U32)distanceFromBase); /* should never overflow */
|
614
669
|
window->dictLimit = (U32)distanceFromBase;
|
@@ -625,10 +680,38 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
|
625
680
|
ptrdiff_t const highInputIdx = (ip + srcSize) - window->dictBase;
|
626
681
|
U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;
|
627
682
|
window->lowLimit = lowLimitMax;
|
683
|
+
DEBUGLOG(5, "Overlapping extDict and input : new lowLimit = %u", window->lowLimit);
|
628
684
|
}
|
629
685
|
return contiguous;
|
630
686
|
}
|
631
687
|
|
688
|
+
|
689
|
+
/* debug functions */
|
690
|
+
|
691
|
+
MEM_STATIC double ZSTD_fWeight(U32 rawStat)
|
692
|
+
{
|
693
|
+
U32 const fp_accuracy = 8;
|
694
|
+
U32 const fp_multiplier = (1 << fp_accuracy);
|
695
|
+
U32 const stat = rawStat + 1;
|
696
|
+
U32 const hb = ZSTD_highbit32(stat);
|
697
|
+
U32 const BWeight = hb * fp_multiplier;
|
698
|
+
U32 const FWeight = (stat << fp_accuracy) >> hb;
|
699
|
+
U32 const weight = BWeight + FWeight;
|
700
|
+
assert(hb + fp_accuracy < 31);
|
701
|
+
return (double)weight / fp_multiplier;
|
702
|
+
}
|
703
|
+
|
704
|
+
MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
|
705
|
+
{
|
706
|
+
unsigned u, sum;
|
707
|
+
for (u=0, sum=0; u<=max; u++) sum += table[u];
|
708
|
+
DEBUGLOG(2, "total nb elts: %u", sum);
|
709
|
+
for (u=0; u<=max; u++) {
|
710
|
+
DEBUGLOG(2, "%2u: %5u (%.2f)",
|
711
|
+
u, table[u], ZSTD_fWeight(sum) - ZSTD_fWeight(table[u]) );
|
712
|
+
}
|
713
|
+
}
|
714
|
+
|
632
715
|
#if defined (__cplusplus)
|
633
716
|
}
|
634
717
|
#endif
|
@@ -640,7 +723,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
|
640
723
|
* ============================================================== */
|
641
724
|
|
642
725
|
/* ZSTD_getCParamsFromCCtxParams() :
|
643
|
-
* cParams are built depending on compressionLevel, src size hints,
|
726
|
+
* cParams are built depending on compressionLevel, src size hints,
|
644
727
|
* LDM and manually set compression parameters.
|
645
728
|
*/
|
646
729
|
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
@@ -656,6 +739,8 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
|
656
739
|
const ZSTD_CDict* cdict,
|
657
740
|
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
|
658
741
|
|
742
|
+
void ZSTD_resetSeqStore(seqStore_t* ssPtr);
|
743
|
+
|
659
744
|
/*! ZSTD_compressStream_generic() :
|
660
745
|
* Private use only. To be called from zstdmt_compress.c in single-thread mode. */
|
661
746
|
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
@@ -672,6 +757,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
|
|
672
757
|
size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
|
673
758
|
const void* dict, size_t dictSize,
|
674
759
|
ZSTD_dictContentType_e dictContentType,
|
760
|
+
ZSTD_dictTableLoadMethod_e dtlm,
|
675
761
|
const ZSTD_CDict* cdict,
|
676
762
|
ZSTD_CCtx_params params,
|
677
763
|
unsigned long long pledgedSrcSize);
|
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
|
16
16
|
ZSTD_compressionParameters const* cParams,
|
17
|
-
void const* end)
|
17
|
+
void const* end, ZSTD_dictTableLoadMethod_e dtlm)
|
18
18
|
{
|
19
19
|
U32* const hashLarge = ms->hashTable;
|
20
20
|
U32 const hBitsL = cParams->hashLog;
|
@@ -40,6 +40,9 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
|
|
40
40
|
hashSmall[smHash] = current + i;
|
41
41
|
if (i == 0 || hashLarge[lgHash] == 0)
|
42
42
|
hashLarge[lgHash] = current + i;
|
43
|
+
/* Only load extra positions for ZSTD_dtlm_full */
|
44
|
+
if (dtlm == ZSTD_dtlm_fast)
|
45
|
+
break;
|
43
46
|
}
|
44
47
|
}
|
45
48
|
}
|
@@ -49,7 +52,7 @@ FORCE_INLINE_TEMPLATE
|
|
49
52
|
size_t ZSTD_compressBlock_doubleFast_generic(
|
50
53
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
51
54
|
ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
|
52
|
-
U32 const mls /* template
|
55
|
+
U32 const mls /* template */, ZSTD_dictMode_e const dictMode)
|
53
56
|
{
|
54
57
|
U32* const hashLong = ms->hashTable;
|
55
58
|
const U32 hBitsL = cParams->hashLog;
|
@@ -59,70 +62,178 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
59
62
|
const BYTE* const istart = (const BYTE*)src;
|
60
63
|
const BYTE* ip = istart;
|
61
64
|
const BYTE* anchor = istart;
|
62
|
-
const U32
|
63
|
-
const BYTE* const
|
65
|
+
const U32 prefixLowestIndex = ms->window.dictLimit;
|
66
|
+
const BYTE* const prefixLowest = base + prefixLowestIndex;
|
64
67
|
const BYTE* const iend = istart + srcSize;
|
65
68
|
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
66
69
|
U32 offset_1=rep[0], offset_2=rep[1];
|
67
70
|
U32 offsetSaved = 0;
|
68
71
|
|
72
|
+
const ZSTD_matchState_t* const dms = ms->dictMatchState;
|
73
|
+
const U32* const dictHashLong = dictMode == ZSTD_dictMatchState ?
|
74
|
+
dms->hashTable : NULL;
|
75
|
+
const U32* const dictHashSmall = dictMode == ZSTD_dictMatchState ?
|
76
|
+
dms->chainTable : NULL;
|
77
|
+
const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ?
|
78
|
+
dms->window.dictLimit : 0;
|
79
|
+
const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
|
80
|
+
dms->window.base : NULL;
|
81
|
+
const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
|
82
|
+
dictBase + dictStartIndex : NULL;
|
83
|
+
const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
|
84
|
+
dms->window.nextSrc : NULL;
|
85
|
+
const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
|
86
|
+
prefixLowestIndex - (U32)(dictEnd - dictBase) :
|
87
|
+
0;
|
88
|
+
const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictStart);
|
89
|
+
|
90
|
+
assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
|
91
|
+
|
69
92
|
/* init */
|
70
|
-
ip += (
|
71
|
-
|
93
|
+
ip += (dictAndPrefixLength == 0);
|
94
|
+
if (dictMode == ZSTD_noDict) {
|
95
|
+
U32 const maxRep = (U32)(ip - prefixLowest);
|
72
96
|
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
73
97
|
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
74
98
|
}
|
99
|
+
if (dictMode == ZSTD_dictMatchState) {
|
100
|
+
/* dictMatchState repCode checks don't currently handle repCode == 0
|
101
|
+
* disabling. */
|
102
|
+
assert(offset_1 <= dictAndPrefixLength);
|
103
|
+
assert(offset_2 <= dictAndPrefixLength);
|
104
|
+
}
|
75
105
|
|
76
106
|
/* Main Search Loop */
|
77
107
|
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
|
78
108
|
size_t mLength;
|
109
|
+
U32 offset;
|
79
110
|
size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
|
80
111
|
size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
|
81
112
|
U32 const current = (U32)(ip-base);
|
82
113
|
U32 const matchIndexL = hashLong[h2];
|
83
|
-
U32
|
114
|
+
U32 matchIndexS = hashSmall[h];
|
84
115
|
const BYTE* matchLong = base + matchIndexL;
|
85
116
|
const BYTE* match = base + matchIndexS;
|
117
|
+
const U32 repIndex = current + 1 - offset_1;
|
118
|
+
const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
|
119
|
+
&& repIndex < prefixLowestIndex) ?
|
120
|
+
dictBase + (repIndex - dictIndexDelta) :
|
121
|
+
base + repIndex;
|
86
122
|
hashLong[h2] = hashSmall[h] = current; /* update hash tables */
|
87
123
|
|
88
|
-
|
89
|
-
if (
|
90
|
-
/*
|
124
|
+
/* check dictMatchState repcode */
|
125
|
+
if (dictMode == ZSTD_dictMatchState
|
126
|
+
&& ((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
|
127
|
+
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
128
|
+
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
129
|
+
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
130
|
+
ip++;
|
131
|
+
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
132
|
+
goto _match_stored;
|
133
|
+
}
|
134
|
+
|
135
|
+
/* check noDict repcode */
|
136
|
+
if ( dictMode == ZSTD_noDict
|
137
|
+
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
|
91
138
|
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
92
139
|
ip++;
|
93
140
|
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
141
|
+
goto _match_stored;
|
142
|
+
}
|
143
|
+
|
144
|
+
/* check prefix long match */
|
145
|
+
if ( (matchIndexL > prefixLowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
|
146
|
+
mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;
|
147
|
+
offset = (U32)(ip-matchLong);
|
148
|
+
while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
149
|
+
goto _match_found;
|
150
|
+
}
|
151
|
+
|
152
|
+
/* check dictMatchState long match */
|
153
|
+
if (dictMode == ZSTD_dictMatchState) {
|
154
|
+
U32 const dictMatchIndexL = dictHashLong[h2];
|
155
|
+
const BYTE* dictMatchL = dictBase + dictMatchIndexL;
|
156
|
+
assert(dictMatchL < dictEnd);
|
157
|
+
|
158
|
+
if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) {
|
159
|
+
mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8;
|
160
|
+
offset = (U32)(current - dictMatchIndexL - dictIndexDelta);
|
161
|
+
while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */
|
162
|
+
goto _match_found;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
/* check prefix short match */
|
167
|
+
if ( (matchIndexS > prefixLowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
|
168
|
+
goto _search_next_long;
|
169
|
+
}
|
170
|
+
|
171
|
+
/* check dictMatchState short match */
|
172
|
+
if (dictMode == ZSTD_dictMatchState) {
|
173
|
+
U32 const dictMatchIndexS = dictHashSmall[h];
|
174
|
+
match = dictBase + dictMatchIndexS;
|
175
|
+
matchIndexS = dictMatchIndexS + dictIndexDelta;
|
176
|
+
|
177
|
+
if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) {
|
178
|
+
goto _search_next_long;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
ip += ((ip-anchor) >> kSearchStrength) + 1;
|
183
|
+
continue;
|
184
|
+
|
185
|
+
_search_next_long:
|
186
|
+
|
187
|
+
{
|
188
|
+
size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
189
|
+
U32 const matchIndexL3 = hashLong[hl3];
|
190
|
+
const BYTE* matchL3 = base + matchIndexL3;
|
191
|
+
hashLong[hl3] = current + 1;
|
192
|
+
|
193
|
+
/* check prefix long +1 match */
|
194
|
+
if ( (matchIndexL3 > prefixLowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
|
195
|
+
mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
|
196
|
+
ip++;
|
197
|
+
offset = (U32)(ip-matchL3);
|
198
|
+
while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
|
199
|
+
goto _match_found;
|
200
|
+
}
|
201
|
+
|
202
|
+
/* check dict long +1 match */
|
203
|
+
if (dictMode == ZSTD_dictMatchState) {
|
204
|
+
U32 const dictMatchIndexL3 = dictHashLong[hl3];
|
205
|
+
const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3;
|
206
|
+
assert(dictMatchL3 < dictEnd);
|
207
|
+
if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) {
|
208
|
+
mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8;
|
107
209
|
ip++;
|
108
|
-
offset = (U32)(
|
109
|
-
while (((ip>anchor) & (
|
110
|
-
|
111
|
-
mLength = ZSTD_count(ip+4, match+4, iend) + 4;
|
112
|
-
offset = (U32)(ip-match);
|
113
|
-
while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
210
|
+
offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta);
|
211
|
+
while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */
|
212
|
+
goto _match_found;
|
114
213
|
}
|
115
|
-
} else {
|
116
|
-
ip += ((ip-anchor) >> kSearchStrength) + 1;
|
117
|
-
continue;
|
118
214
|
}
|
215
|
+
}
|
119
216
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
217
|
+
/* if no long +1 match, explore the short match we found */
|
218
|
+
if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
|
219
|
+
mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;
|
220
|
+
offset = (U32)(current - matchIndexS);
|
221
|
+
while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
222
|
+
} else {
|
223
|
+
mLength = ZSTD_count(ip+4, match+4, iend) + 4;
|
224
|
+
offset = (U32)(ip - match);
|
225
|
+
while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
124
226
|
}
|
125
227
|
|
228
|
+
/* fall-through */
|
229
|
+
|
230
|
+
_match_found:
|
231
|
+
offset_2 = offset_1;
|
232
|
+
offset_1 = offset;
|
233
|
+
|
234
|
+
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
235
|
+
|
236
|
+
_match_stored:
|
126
237
|
/* match found */
|
127
238
|
ip += mLength;
|
128
239
|
anchor = ip;
|
@@ -135,19 +246,44 @@ size_t ZSTD_compressBlock_doubleFast_generic(
|
|
135
246
|
hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
|
136
247
|
|
137
248
|
/* check immediate repcode */
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
249
|
+
if (dictMode == ZSTD_dictMatchState) {
|
250
|
+
while (ip <= ilimit) {
|
251
|
+
U32 const current2 = (U32)(ip-base);
|
252
|
+
U32 const repIndex2 = current2 - offset_2;
|
253
|
+
const BYTE* repMatch2 = dictMode == ZSTD_dictMatchState
|
254
|
+
&& repIndex2 < prefixLowestIndex ?
|
255
|
+
dictBase - dictIndexDelta + repIndex2 :
|
256
|
+
base + repIndex2;
|
257
|
+
if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
|
258
|
+
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
259
|
+
const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
|
260
|
+
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
|
261
|
+
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
262
|
+
ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
|
263
|
+
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
|
264
|
+
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
|
265
|
+
ip += repLength2;
|
266
|
+
anchor = ip;
|
267
|
+
continue;
|
268
|
+
}
|
269
|
+
break;
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
if (dictMode == ZSTD_noDict) {
|
274
|
+
while ( (ip <= ilimit)
|
275
|
+
&& ( (offset_2>0)
|
276
|
+
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
277
|
+
/* store sequence */
|
278
|
+
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
279
|
+
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
280
|
+
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
|
281
|
+
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
|
282
|
+
ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
|
283
|
+
ip += rLength;
|
284
|
+
anchor = ip;
|
285
|
+
continue; /* faster when present ... (?) */
|
286
|
+
} } } }
|
151
287
|
|
152
288
|
/* save reps for next block */
|
153
289
|
rep[0] = offset_1 ? offset_1 : offsetSaved;
|
@@ -167,13 +303,33 @@ size_t ZSTD_compressBlock_doubleFast(
|
|
167
303
|
{
|
168
304
|
default: /* includes case 3 */
|
169
305
|
case 4 :
|
170
|
-
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
|
306
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 4, ZSTD_noDict);
|
171
307
|
case 5 :
|
172
|
-
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
|
308
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 5, ZSTD_noDict);
|
173
309
|
case 6 :
|
174
|
-
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
|
310
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 6, ZSTD_noDict);
|
175
311
|
case 7 :
|
176
|
-
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
|
312
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 7, ZSTD_noDict);
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
|
317
|
+
size_t ZSTD_compressBlock_doubleFast_dictMatchState(
|
318
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
319
|
+
ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
|
320
|
+
{
|
321
|
+
const U32 mls = cParams->searchLength;
|
322
|
+
switch(mls)
|
323
|
+
{
|
324
|
+
default: /* includes case 3 */
|
325
|
+
case 4 :
|
326
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 4, ZSTD_dictMatchState);
|
327
|
+
case 5 :
|
328
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 5, ZSTD_dictMatchState);
|
329
|
+
case 6 :
|
330
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 6, ZSTD_dictMatchState);
|
331
|
+
case 7 :
|
332
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 7, ZSTD_dictMatchState);
|
177
333
|
}
|
178
334
|
}
|
179
335
|
|
@@ -187,75 +343,78 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
187
343
|
U32 const hBitsL = cParams->hashLog;
|
188
344
|
U32* const hashSmall = ms->chainTable;
|
189
345
|
U32 const hBitsS = cParams->chainLog;
|
190
|
-
const BYTE* const base = ms->window.base;
|
191
|
-
const BYTE* const dictBase = ms->window.dictBase;
|
192
346
|
const BYTE* const istart = (const BYTE*)src;
|
193
347
|
const BYTE* ip = istart;
|
194
348
|
const BYTE* anchor = istart;
|
195
|
-
const U32 lowestIndex = ms->window.lowLimit;
|
196
|
-
const BYTE* const dictStart = dictBase + lowestIndex;
|
197
|
-
const U32 dictLimit = ms->window.dictLimit;
|
198
|
-
const BYTE* const lowPrefixPtr = base + dictLimit;
|
199
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
200
349
|
const BYTE* const iend = istart + srcSize;
|
201
350
|
const BYTE* const ilimit = iend - 8;
|
351
|
+
const U32 prefixStartIndex = ms->window.dictLimit;
|
352
|
+
const BYTE* const base = ms->window.base;
|
353
|
+
const BYTE* const prefixStart = base + prefixStartIndex;
|
354
|
+
const U32 dictStartIndex = ms->window.lowLimit;
|
355
|
+
const BYTE* const dictBase = ms->window.dictBase;
|
356
|
+
const BYTE* const dictStart = dictBase + dictStartIndex;
|
357
|
+
const BYTE* const dictEnd = dictBase + prefixStartIndex;
|
202
358
|
U32 offset_1=rep[0], offset_2=rep[1];
|
203
359
|
|
360
|
+
DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)", srcSize);
|
361
|
+
|
204
362
|
/* Search Loop */
|
205
363
|
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
206
364
|
const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
|
207
365
|
const U32 matchIndex = hashSmall[hSmall];
|
208
|
-
const BYTE* matchBase = matchIndex <
|
366
|
+
const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base;
|
209
367
|
const BYTE* match = matchBase + matchIndex;
|
210
368
|
|
211
369
|
const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);
|
212
370
|
const U32 matchLongIndex = hashLong[hLong];
|
213
|
-
const BYTE* matchLongBase = matchLongIndex <
|
371
|
+
const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base;
|
214
372
|
const BYTE* matchLong = matchLongBase + matchLongIndex;
|
215
373
|
|
216
374
|
const U32 current = (U32)(ip-base);
|
217
375
|
const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
|
218
|
-
const BYTE* repBase = repIndex <
|
219
|
-
const BYTE* repMatch = repBase + repIndex;
|
376
|
+
const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;
|
377
|
+
const BYTE* const repMatch = repBase + repIndex;
|
220
378
|
size_t mLength;
|
221
379
|
hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
|
222
380
|
|
223
|
-
if (
|
224
|
-
|
225
|
-
|
226
|
-
|
381
|
+
if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
|
382
|
+
& (repIndex > dictStartIndex))
|
383
|
+
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
384
|
+
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
385
|
+
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
227
386
|
ip++;
|
228
387
|
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
|
229
388
|
} else {
|
230
|
-
if ((matchLongIndex >
|
231
|
-
const BYTE* matchEnd = matchLongIndex <
|
232
|
-
const BYTE* lowMatchPtr = matchLongIndex <
|
389
|
+
if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
|
390
|
+
const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
|
391
|
+
const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart;
|
233
392
|
U32 offset;
|
234
|
-
mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd,
|
393
|
+
mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8;
|
235
394
|
offset = current - matchLongIndex;
|
236
395
|
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
237
396
|
offset_2 = offset_1;
|
238
397
|
offset_1 = offset;
|
239
398
|
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
240
399
|
|
241
|
-
} else if ((matchIndex >
|
400
|
+
} else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
|
242
401
|
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
243
402
|
U32 const matchIndex3 = hashLong[h3];
|
244
|
-
const BYTE* const match3Base = matchIndex3 <
|
403
|
+
const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base;
|
245
404
|
const BYTE* match3 = match3Base + matchIndex3;
|
246
405
|
U32 offset;
|
247
406
|
hashLong[h3] = current + 1;
|
248
|
-
if ( (matchIndex3 >
|
249
|
-
const BYTE* matchEnd = matchIndex3 <
|
250
|
-
const BYTE* lowMatchPtr = matchIndex3 <
|
251
|
-
mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd,
|
407
|
+
if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
|
408
|
+
const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend;
|
409
|
+
const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart;
|
410
|
+
mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8;
|
252
411
|
ip++;
|
253
412
|
offset = current+1 - matchIndex3;
|
254
413
|
while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
|
255
414
|
} else {
|
256
|
-
const BYTE* matchEnd = matchIndex <
|
257
|
-
const BYTE* lowMatchPtr = matchIndex <
|
258
|
-
mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd,
|
415
|
+
const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend;
|
416
|
+
const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart;
|
417
|
+
mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;
|
259
418
|
offset = current - matchIndex;
|
260
419
|
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
261
420
|
}
|
@@ -282,12 +441,13 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
|
282
441
|
while (ip <= ilimit) {
|
283
442
|
U32 const current2 = (U32)(ip-base);
|
284
443
|
U32 const repIndex2 = current2 - offset_2;
|
285
|
-
const BYTE* repMatch2 = repIndex2 <
|
286
|
-
if ( (((U32)((
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
444
|
+
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
|
445
|
+
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
|
446
|
+
& (repIndex2 > dictStartIndex))
|
447
|
+
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
448
|
+
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
449
|
+
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
450
|
+
U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
291
451
|
ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
|
292
452
|
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
|
293
453
|
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
|