extzstd 0.2 → 0.3
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/HISTORY.ja.md +13 -0
- data/README.md +17 -14
- data/contrib/zstd/{NEWS → CHANGELOG} +115 -2
- data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
- data/contrib/zstd/Makefile +99 -53
- data/contrib/zstd/README.md +59 -39
- data/contrib/zstd/TESTING.md +1 -1
- data/contrib/zstd/appveyor.yml +17 -6
- data/contrib/zstd/lib/BUCK +29 -2
- data/contrib/zstd/lib/Makefile +118 -21
- data/contrib/zstd/lib/README.md +84 -44
- data/contrib/zstd/lib/common/bitstream.h +17 -33
- data/contrib/zstd/lib/common/compiler.h +62 -8
- data/contrib/zstd/lib/common/cpu.h +215 -0
- data/contrib/zstd/lib/common/debug.c +44 -0
- data/contrib/zstd/lib/common/debug.h +134 -0
- data/contrib/zstd/lib/common/entropy_common.c +16 -1
- data/contrib/zstd/lib/common/error_private.c +7 -0
- data/contrib/zstd/lib/common/fse.h +48 -44
- data/contrib/zstd/lib/common/fse_decompress.c +3 -3
- data/contrib/zstd/lib/common/huf.h +169 -113
- data/contrib/zstd/lib/common/mem.h +20 -2
- data/contrib/zstd/lib/common/pool.c +135 -49
- data/contrib/zstd/lib/common/pool.h +40 -21
- data/contrib/zstd/lib/common/threading.c +2 -2
- data/contrib/zstd/lib/common/threading.h +12 -12
- data/contrib/zstd/lib/common/xxhash.c +3 -2
- data/contrib/zstd/lib/common/zstd_common.c +3 -6
- data/contrib/zstd/lib/common/zstd_errors.h +17 -7
- data/contrib/zstd/lib/common/zstd_internal.h +76 -48
- data/contrib/zstd/lib/compress/fse_compress.c +89 -209
- data/contrib/zstd/lib/compress/hist.c +203 -0
- data/contrib/zstd/lib/compress/hist.h +95 -0
- data/contrib/zstd/lib/compress/huf_compress.c +188 -80
- data/contrib/zstd/lib/compress/zstd_compress.c +2500 -1203
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +463 -62
- data/contrib/zstd/lib/compress/zstd_double_fast.c +321 -131
- data/contrib/zstd/lib/compress/zstd_double_fast.h +13 -4
- data/contrib/zstd/lib/compress/zstd_fast.c +335 -108
- data/contrib/zstd/lib/compress/zstd_fast.h +12 -6
- data/contrib/zstd/lib/compress/zstd_lazy.c +654 -313
- data/contrib/zstd/lib/compress/zstd_lazy.h +44 -16
- data/contrib/zstd/lib/compress/zstd_ldm.c +310 -420
- data/contrib/zstd/lib/compress/zstd_ldm.h +63 -26
- data/contrib/zstd/lib/compress/zstd_opt.c +773 -325
- data/contrib/zstd/lib/compress/zstd_opt.h +31 -5
- data/contrib/zstd/lib/compress/zstdmt_compress.c +1468 -518
- data/contrib/zstd/lib/compress/zstdmt_compress.h +96 -45
- data/contrib/zstd/lib/decompress/huf_decompress.c +518 -282
- data/contrib/zstd/lib/decompress/zstd_ddict.c +240 -0
- data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
- data/contrib/zstd/lib/decompress/zstd_decompress.c +613 -1513
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1311 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +59 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +175 -0
- data/contrib/zstd/lib/dictBuilder/cover.c +194 -113
- data/contrib/zstd/lib/dictBuilder/cover.h +112 -0
- data/contrib/zstd/lib/dictBuilder/divsufsort.c +3 -3
- data/contrib/zstd/lib/dictBuilder/fastcover.c +740 -0
- data/contrib/zstd/lib/dictBuilder/zdict.c +142 -106
- data/contrib/zstd/lib/dictBuilder/zdict.h +115 -49
- data/contrib/zstd/lib/legacy/zstd_legacy.h +44 -12
- data/contrib/zstd/lib/legacy/zstd_v01.c +41 -10
- data/contrib/zstd/lib/legacy/zstd_v01.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v02.c +37 -12
- data/contrib/zstd/lib/legacy/zstd_v02.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v03.c +38 -12
- data/contrib/zstd/lib/legacy/zstd_v03.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v04.c +55 -174
- data/contrib/zstd/lib/legacy/zstd_v04.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v05.c +59 -31
- data/contrib/zstd/lib/legacy/zstd_v05.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v06.c +48 -20
- data/contrib/zstd/lib/legacy/zstd_v06.h +10 -5
- data/contrib/zstd/lib/legacy/zstd_v07.c +62 -29
- data/contrib/zstd/lib/legacy/zstd_v07.h +10 -5
- data/contrib/zstd/lib/zstd.h +1346 -832
- data/ext/extzstd.c +27 -19
- data/ext/extzstd_stream.c +20 -4
- data/ext/zstd_compress.c +1 -0
- data/ext/zstd_decompress.c +4 -0
- data/ext/zstd_dictbuilder.c +4 -0
- data/ext/zstd_dictbuilder_fastcover.c +5 -0
- data/lib/extzstd.rb +52 -220
- data/lib/extzstd/version.rb +1 -1
- metadata +21 -7
- data/contrib/zstd/circle.yml +0 -63
|
@@ -16,13 +16,19 @@ extern "C" {
|
|
|
16
16
|
#endif
|
|
17
17
|
|
|
18
18
|
#include "mem.h" /* U32 */
|
|
19
|
-
#include "
|
|
19
|
+
#include "zstd_compress_internal.h"
|
|
20
20
|
|
|
21
|
-
void ZSTD_fillHashTable(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
|
|
22
|
+
void const* end, ZSTD_dictTableLoadMethod_e dtlm);
|
|
23
|
+
size_t ZSTD_compressBlock_fast(
|
|
24
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
25
|
+
void const* src, size_t srcSize);
|
|
26
|
+
size_t ZSTD_compressBlock_fast_dictMatchState(
|
|
27
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
28
|
+
void const* src, size_t srcSize);
|
|
29
|
+
size_t ZSTD_compressBlock_fast_extDict(
|
|
30
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
31
|
+
void const* src, size_t srcSize);
|
|
26
32
|
|
|
27
33
|
#if defined (__cplusplus)
|
|
28
34
|
}
|
|
@@ -15,89 +15,108 @@
|
|
|
15
15
|
/*-*************************************
|
|
16
16
|
* Binary Tree search
|
|
17
17
|
***************************************/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
U32 nbCompares, U32 const mls, U32 const extDict)
|
|
18
|
+
|
|
19
|
+
static void
|
|
20
|
+
ZSTD_updateDUBT(ZSTD_matchState_t* ms,
|
|
21
|
+
const BYTE* ip, const BYTE* iend,
|
|
22
|
+
U32 mls)
|
|
24
23
|
{
|
|
25
|
-
|
|
26
|
-
U32
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
U32
|
|
30
|
-
U32
|
|
31
|
-
U32
|
|
24
|
+
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
|
25
|
+
U32* const hashTable = ms->hashTable;
|
|
26
|
+
U32 const hashLog = cParams->hashLog;
|
|
27
|
+
|
|
28
|
+
U32* const bt = ms->chainTable;
|
|
29
|
+
U32 const btLog = cParams->chainLog - 1;
|
|
30
|
+
U32 const btMask = (1 << btLog) - 1;
|
|
31
|
+
|
|
32
|
+
const BYTE* const base = ms->window.base;
|
|
33
|
+
U32 const target = (U32)(ip - base);
|
|
34
|
+
U32 idx = ms->nextToUpdate;
|
|
35
|
+
|
|
36
|
+
if (idx != target)
|
|
37
|
+
DEBUGLOG(7, "ZSTD_updateDUBT, from %u to %u (dictLimit:%u)",
|
|
38
|
+
idx, target, ms->window.dictLimit);
|
|
39
|
+
assert(ip + 8 <= iend); /* condition for ZSTD_hashPtr */
|
|
40
|
+
(void)iend;
|
|
41
|
+
|
|
42
|
+
assert(idx >= ms->window.dictLimit); /* condition for valid base+idx */
|
|
43
|
+
for ( ; idx < target ; idx++) {
|
|
44
|
+
size_t const h = ZSTD_hashPtr(base + idx, hashLog, mls); /* assumption : ip + 8 <= iend */
|
|
45
|
+
U32 const matchIndex = hashTable[h];
|
|
46
|
+
|
|
47
|
+
U32* const nextCandidatePtr = bt + 2*(idx&btMask);
|
|
48
|
+
U32* const sortMarkPtr = nextCandidatePtr + 1;
|
|
49
|
+
|
|
50
|
+
DEBUGLOG(8, "ZSTD_updateDUBT: insert %u", idx);
|
|
51
|
+
hashTable[h] = idx; /* Update Hash Table */
|
|
52
|
+
*nextCandidatePtr = matchIndex; /* update BT like a chain */
|
|
53
|
+
*sortMarkPtr = ZSTD_DUBT_UNSORTED_MARK;
|
|
54
|
+
}
|
|
55
|
+
ms->nextToUpdate = target;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/** ZSTD_insertDUBT1() :
|
|
60
|
+
* sort one already inserted but unsorted position
|
|
61
|
+
* assumption : current >= btlow == (current - btmask)
|
|
62
|
+
* doesn't fail */
|
|
63
|
+
static void
|
|
64
|
+
ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
|
|
65
|
+
U32 current, const BYTE* inputEnd,
|
|
66
|
+
U32 nbCompares, U32 btLow,
|
|
67
|
+
const ZSTD_dictMode_e dictMode)
|
|
68
|
+
{
|
|
69
|
+
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
|
70
|
+
U32* const bt = ms->chainTable;
|
|
71
|
+
U32 const btLog = cParams->chainLog - 1;
|
|
72
|
+
U32 const btMask = (1 << btLog) - 1;
|
|
32
73
|
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
|
33
|
-
const BYTE* const base =
|
|
34
|
-
const BYTE* const dictBase =
|
|
35
|
-
const U32 dictLimit =
|
|
74
|
+
const BYTE* const base = ms->window.base;
|
|
75
|
+
const BYTE* const dictBase = ms->window.dictBase;
|
|
76
|
+
const U32 dictLimit = ms->window.dictLimit;
|
|
77
|
+
const BYTE* const ip = (current>=dictLimit) ? base + current : dictBase + current;
|
|
78
|
+
const BYTE* const iend = (current>=dictLimit) ? inputEnd : dictBase + dictLimit;
|
|
36
79
|
const BYTE* const dictEnd = dictBase + dictLimit;
|
|
37
80
|
const BYTE* const prefixStart = base + dictLimit;
|
|
38
81
|
const BYTE* match;
|
|
39
|
-
const U32 current = (U32)(ip-base);
|
|
40
|
-
const U32 btLow = btMask >= current ? 0 : current - btMask;
|
|
41
82
|
U32* smallerPtr = bt + 2*(current&btMask);
|
|
42
83
|
U32* largerPtr = smallerPtr + 1;
|
|
84
|
+
U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */
|
|
43
85
|
U32 dummy32; /* to be nullified at the end */
|
|
44
|
-
U32 const windowLow =
|
|
45
|
-
U32 matchEndIdx = current+8+1;
|
|
46
|
-
size_t bestLength = 8;
|
|
47
|
-
#ifdef ZSTD_C_PREDICT
|
|
48
|
-
U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
|
|
49
|
-
U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
|
|
50
|
-
predictedSmall += (predictedSmall>0);
|
|
51
|
-
predictedLarge += (predictedLarge>0);
|
|
52
|
-
#endif /* ZSTD_C_PREDICT */
|
|
53
|
-
|
|
54
|
-
DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current);
|
|
86
|
+
U32 const windowLow = ms->window.lowLimit;
|
|
55
87
|
|
|
56
|
-
|
|
57
|
-
|
|
88
|
+
DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)",
|
|
89
|
+
current, dictLimit, windowLow);
|
|
90
|
+
assert(current >= btLow);
|
|
91
|
+
assert(ip < iend); /* condition for ZSTD_count */
|
|
58
92
|
|
|
59
93
|
while (nbCompares-- && (matchIndex > windowLow)) {
|
|
60
94
|
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
|
61
95
|
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
|
62
96
|
assert(matchIndex < current);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
*largerPtr = matchIndex;
|
|
77
|
-
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
|
78
|
-
largerPtr = nextPtr;
|
|
79
|
-
matchIndex = nextPtr[0];
|
|
80
|
-
predictedLarge = predictPtr[0] + (predictPtr[0]>0);
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
#endif
|
|
84
|
-
|
|
85
|
-
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
|
|
86
|
-
assert(matchIndex+matchLength >= dictLimit); /* might be wrong if extDict is incorrectly set to 0 */
|
|
87
|
-
match = base + matchIndex;
|
|
97
|
+
/* note : all candidates are now supposed sorted,
|
|
98
|
+
* but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK
|
|
99
|
+
* when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */
|
|
100
|
+
|
|
101
|
+
if ( (dictMode != ZSTD_extDict)
|
|
102
|
+
|| (matchIndex+matchLength >= dictLimit) /* both in current segment*/
|
|
103
|
+
|| (current < dictLimit) /* both in extDict */) {
|
|
104
|
+
const BYTE* const mBase = ( (dictMode != ZSTD_extDict)
|
|
105
|
+
|| (matchIndex+matchLength >= dictLimit)) ?
|
|
106
|
+
base : dictBase;
|
|
107
|
+
assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */
|
|
108
|
+
|| (current < dictLimit) );
|
|
109
|
+
match = mBase + matchIndex;
|
|
88
110
|
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
|
|
89
111
|
} else {
|
|
90
112
|
match = dictBase + matchIndex;
|
|
91
113
|
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
|
|
92
114
|
if (matchIndex+matchLength >= dictLimit)
|
|
93
|
-
match = base + matchIndex; /*
|
|
115
|
+
match = base + matchIndex; /* preparation for next read of match[matchLength] */
|
|
94
116
|
}
|
|
95
117
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (matchLength > matchEndIdx - matchIndex)
|
|
99
|
-
matchEndIdx = matchIndex + (U32)matchLength;
|
|
100
|
-
}
|
|
118
|
+
DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ",
|
|
119
|
+
current, matchIndex, (U32)matchLength);
|
|
101
120
|
|
|
102
121
|
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
|
|
103
122
|
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */
|
|
@@ -108,6 +127,8 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc,
|
|
|
108
127
|
*smallerPtr = matchIndex; /* update smaller idx */
|
|
109
128
|
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
|
|
110
129
|
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop searching */
|
|
130
|
+
DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is smaller : next => %u",
|
|
131
|
+
matchIndex, btLow, nextPtr[1]);
|
|
111
132
|
smallerPtr = nextPtr+1; /* new "candidate" => larger than match, which was smaller than target */
|
|
112
133
|
matchIndex = nextPtr[1]; /* new matchIndex, larger than previous and closer to current */
|
|
113
134
|
} else {
|
|
@@ -115,184 +136,301 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc,
|
|
|
115
136
|
*largerPtr = matchIndex;
|
|
116
137
|
commonLengthLarger = matchLength;
|
|
117
138
|
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop searching */
|
|
139
|
+
DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is larger => %u",
|
|
140
|
+
matchIndex, btLow, nextPtr[0]);
|
|
118
141
|
largerPtr = nextPtr;
|
|
119
142
|
matchIndex = nextPtr[0];
|
|
120
143
|
} }
|
|
121
144
|
|
|
122
145
|
*smallerPtr = *largerPtr = 0;
|
|
123
|
-
if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
|
|
124
|
-
assert(matchEndIdx > current + 8);
|
|
125
|
-
return matchEndIdx - (current + 8);
|
|
126
146
|
}
|
|
127
147
|
|
|
128
|
-
FORCE_INLINE_TEMPLATE
|
|
129
|
-
void ZSTD_updateTree_internal(ZSTD_CCtx* zc,
|
|
130
|
-
const BYTE* const ip, const BYTE* const iend,
|
|
131
|
-
const U32 nbCompares, const U32 mls, const U32 extDict)
|
|
132
|
-
{
|
|
133
|
-
const BYTE* const base = zc->base;
|
|
134
|
-
U32 const target = (U32)(ip - base);
|
|
135
|
-
U32 idx = zc->nextToUpdate;
|
|
136
|
-
DEBUGLOG(7, "ZSTD_updateTree_internal, from %u to %u (extDict:%u)",
|
|
137
|
-
idx, target, extDict);
|
|
138
148
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
149
|
+
static size_t
|
|
150
|
+
ZSTD_DUBT_findBetterDictMatch (
|
|
151
|
+
ZSTD_matchState_t* ms,
|
|
152
|
+
const BYTE* const ip, const BYTE* const iend,
|
|
153
|
+
size_t* offsetPtr,
|
|
154
|
+
size_t bestLength,
|
|
155
|
+
U32 nbCompares,
|
|
156
|
+
U32 const mls,
|
|
157
|
+
const ZSTD_dictMode_e dictMode)
|
|
147
158
|
{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
const ZSTD_matchState_t * const dms = ms->dictMatchState;
|
|
160
|
+
const ZSTD_compressionParameters* const dmsCParams = &dms->cParams;
|
|
161
|
+
const U32 * const dictHashTable = dms->hashTable;
|
|
162
|
+
U32 const hashLog = dmsCParams->hashLog;
|
|
163
|
+
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
|
|
164
|
+
U32 dictMatchIndex = dictHashTable[h];
|
|
165
|
+
|
|
166
|
+
const BYTE* const base = ms->window.base;
|
|
167
|
+
const BYTE* const prefixStart = base + ms->window.dictLimit;
|
|
168
|
+
U32 const current = (U32)(ip-base);
|
|
169
|
+
const BYTE* const dictBase = dms->window.base;
|
|
170
|
+
const BYTE* const dictEnd = dms->window.nextSrc;
|
|
171
|
+
U32 const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base);
|
|
172
|
+
U32 const dictLowLimit = dms->window.lowLimit;
|
|
173
|
+
U32 const dictIndexDelta = ms->window.lowLimit - dictHighLimit;
|
|
174
|
+
|
|
175
|
+
U32* const dictBt = dms->chainTable;
|
|
176
|
+
U32 const btLog = dmsCParams->chainLog - 1;
|
|
177
|
+
U32 const btMask = (1 << btLog) - 1;
|
|
178
|
+
U32 const btLow = (btMask >= dictHighLimit - dictLowLimit) ? dictLowLimit : dictHighLimit - btMask;
|
|
157
179
|
|
|
158
|
-
|
|
159
|
-
static size_t ZSTD_insertBtAndFindBestMatch (
|
|
160
|
-
ZSTD_CCtx* zc,
|
|
161
|
-
const BYTE* const ip, const BYTE* const iend,
|
|
162
|
-
size_t* offsetPtr,
|
|
163
|
-
U32 nbCompares, const U32 mls,
|
|
164
|
-
U32 extDict)
|
|
165
|
-
{
|
|
166
|
-
U32* const hashTable = zc->hashTable;
|
|
167
|
-
U32 const hashLog = zc->appliedParams.cParams.hashLog;
|
|
168
|
-
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
|
|
169
|
-
U32* const bt = zc->chainTable;
|
|
170
|
-
U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
|
|
171
|
-
U32 const btMask = (1 << btLog) - 1;
|
|
172
|
-
U32 matchIndex = hashTable[h];
|
|
173
180
|
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
|
174
|
-
const BYTE* const base = zc->base;
|
|
175
|
-
const BYTE* const dictBase = zc->dictBase;
|
|
176
|
-
const U32 dictLimit = zc->dictLimit;
|
|
177
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
|
178
|
-
const BYTE* const prefixStart = base + dictLimit;
|
|
179
|
-
const U32 current = (U32)(ip-base);
|
|
180
|
-
const U32 btLow = btMask >= current ? 0 : current - btMask;
|
|
181
|
-
const U32 windowLow = zc->lowLimit;
|
|
182
|
-
U32* smallerPtr = bt + 2*(current&btMask);
|
|
183
|
-
U32* largerPtr = bt + 2*(current&btMask) + 1;
|
|
184
|
-
U32 matchEndIdx = current+8+1;
|
|
185
|
-
U32 dummy32; /* to be nullified at the end */
|
|
186
|
-
size_t bestLength = 0;
|
|
187
181
|
|
|
188
|
-
|
|
189
|
-
|
|
182
|
+
(void)dictMode;
|
|
183
|
+
assert(dictMode == ZSTD_dictMatchState);
|
|
190
184
|
|
|
191
|
-
while (nbCompares-- && (
|
|
192
|
-
U32* const nextPtr =
|
|
185
|
+
while (nbCompares-- && (dictMatchIndex > dictLowLimit)) {
|
|
186
|
+
U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask);
|
|
193
187
|
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
|
194
|
-
const BYTE* match;
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
match = base +
|
|
198
|
-
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
|
|
199
|
-
} else {
|
|
200
|
-
match = dictBase + matchIndex;
|
|
201
|
-
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
|
|
202
|
-
if (matchIndex+matchLength >= dictLimit)
|
|
203
|
-
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
|
|
204
|
-
}
|
|
188
|
+
const BYTE* match = dictBase + dictMatchIndex;
|
|
189
|
+
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
|
|
190
|
+
if (dictMatchIndex+matchLength >= dictHighLimit)
|
|
191
|
+
match = base + dictMatchIndex + dictIndexDelta; /* to prepare for next usage of match[matchLength] */
|
|
205
192
|
|
|
206
193
|
if (matchLength > bestLength) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
194
|
+
U32 matchIndex = dictMatchIndex + dictIndexDelta;
|
|
195
|
+
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {
|
|
196
|
+
DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)",
|
|
197
|
+
current, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + current - matchIndex, dictMatchIndex, matchIndex);
|
|
210
198
|
bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
|
|
211
|
-
|
|
199
|
+
}
|
|
200
|
+
if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */
|
|
212
201
|
break; /* drop, to guarantee consistency (miss a little bit of compression) */
|
|
213
202
|
}
|
|
214
203
|
}
|
|
215
204
|
|
|
216
205
|
if (match[matchLength] < ip[matchLength]) {
|
|
217
|
-
/*
|
|
218
|
-
*smallerPtr = matchIndex; /* update smaller idx */
|
|
206
|
+
if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */
|
|
219
207
|
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
|
|
220
|
-
|
|
221
|
-
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
|
|
222
|
-
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
|
|
208
|
+
dictMatchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
|
|
223
209
|
} else {
|
|
224
210
|
/* match is larger than current */
|
|
225
|
-
|
|
211
|
+
if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */
|
|
226
212
|
commonLengthLarger = matchLength;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
} }
|
|
231
|
-
|
|
232
|
-
*smallerPtr = *largerPtr = 0;
|
|
213
|
+
dictMatchIndex = nextPtr[0];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
233
216
|
|
|
234
|
-
|
|
235
|
-
|
|
217
|
+
if (bestLength >= MINMATCH) {
|
|
218
|
+
U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
|
|
219
|
+
DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
|
|
220
|
+
current, (U32)bestLength, (U32)*offsetPtr, mIndex);
|
|
221
|
+
}
|
|
236
222
|
return bestLength;
|
|
223
|
+
|
|
237
224
|
}
|
|
238
225
|
|
|
239
226
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const BYTE* const ip, const BYTE* const iLimit,
|
|
227
|
+
static size_t
|
|
228
|
+
ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
|
|
229
|
+
const BYTE* const ip, const BYTE* const iend,
|
|
244
230
|
size_t* offsetPtr,
|
|
245
|
-
|
|
231
|
+
U32 const mls,
|
|
232
|
+
const ZSTD_dictMode_e dictMode)
|
|
246
233
|
{
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
234
|
+
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
|
235
|
+
U32* const hashTable = ms->hashTable;
|
|
236
|
+
U32 const hashLog = cParams->hashLog;
|
|
237
|
+
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
|
|
238
|
+
U32 matchIndex = hashTable[h];
|
|
239
|
+
|
|
240
|
+
const BYTE* const base = ms->window.base;
|
|
241
|
+
U32 const current = (U32)(ip-base);
|
|
242
|
+
U32 const windowLow = ms->window.lowLimit;
|
|
243
|
+
|
|
244
|
+
U32* const bt = ms->chainTable;
|
|
245
|
+
U32 const btLog = cParams->chainLog - 1;
|
|
246
|
+
U32 const btMask = (1 << btLog) - 1;
|
|
247
|
+
U32 const btLow = (btMask >= current) ? 0 : current - btMask;
|
|
248
|
+
U32 const unsortLimit = MAX(btLow, windowLow);
|
|
249
|
+
|
|
250
|
+
U32* nextCandidate = bt + 2*(matchIndex&btMask);
|
|
251
|
+
U32* unsortedMark = bt + 2*(matchIndex&btMask) + 1;
|
|
252
|
+
U32 nbCompares = 1U << cParams->searchLog;
|
|
253
|
+
U32 nbCandidates = nbCompares;
|
|
254
|
+
U32 previousCandidate = 0;
|
|
255
|
+
|
|
256
|
+
DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", current);
|
|
257
|
+
assert(ip <= iend-8); /* required for h calculation */
|
|
258
|
+
|
|
259
|
+
/* reach end of unsorted candidates list */
|
|
260
|
+
while ( (matchIndex > unsortLimit)
|
|
261
|
+
&& (*unsortedMark == ZSTD_DUBT_UNSORTED_MARK)
|
|
262
|
+
&& (nbCandidates > 1) ) {
|
|
263
|
+
DEBUGLOG(8, "ZSTD_DUBT_findBestMatch: candidate %u is unsorted",
|
|
264
|
+
matchIndex);
|
|
265
|
+
*unsortedMark = previousCandidate; /* the unsortedMark becomes a reversed chain, to move up back to original position */
|
|
266
|
+
previousCandidate = matchIndex;
|
|
267
|
+
matchIndex = *nextCandidate;
|
|
268
|
+
nextCandidate = bt + 2*(matchIndex&btMask);
|
|
269
|
+
unsortedMark = bt + 2*(matchIndex&btMask) + 1;
|
|
270
|
+
nbCandidates --;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* nullify last candidate if it's still unsorted
|
|
274
|
+
* simplification, detrimental to compression ratio, beneficial for speed */
|
|
275
|
+
if ( (matchIndex > unsortLimit)
|
|
276
|
+
&& (*unsortedMark==ZSTD_DUBT_UNSORTED_MARK) ) {
|
|
277
|
+
DEBUGLOG(7, "ZSTD_DUBT_findBestMatch: nullify last unsorted candidate %u",
|
|
278
|
+
matchIndex);
|
|
279
|
+
*nextCandidate = *unsortedMark = 0;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* batch sort stacked candidates */
|
|
283
|
+
matchIndex = previousCandidate;
|
|
284
|
+
while (matchIndex) { /* will end on matchIndex == 0 */
|
|
285
|
+
U32* const nextCandidateIdxPtr = bt + 2*(matchIndex&btMask) + 1;
|
|
286
|
+
U32 const nextCandidateIdx = *nextCandidateIdxPtr;
|
|
287
|
+
ZSTD_insertDUBT1(ms, matchIndex, iend,
|
|
288
|
+
nbCandidates, unsortLimit, dictMode);
|
|
289
|
+
matchIndex = nextCandidateIdx;
|
|
290
|
+
nbCandidates++;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/* find longest match */
|
|
294
|
+
{ size_t commonLengthSmaller = 0, commonLengthLarger = 0;
|
|
295
|
+
const BYTE* const dictBase = ms->window.dictBase;
|
|
296
|
+
const U32 dictLimit = ms->window.dictLimit;
|
|
297
|
+
const BYTE* const dictEnd = dictBase + dictLimit;
|
|
298
|
+
const BYTE* const prefixStart = base + dictLimit;
|
|
299
|
+
U32* smallerPtr = bt + 2*(current&btMask);
|
|
300
|
+
U32* largerPtr = bt + 2*(current&btMask) + 1;
|
|
301
|
+
U32 matchEndIdx = current + 8 + 1;
|
|
302
|
+
U32 dummy32; /* to be nullified at the end */
|
|
303
|
+
size_t bestLength = 0;
|
|
304
|
+
|
|
305
|
+
matchIndex = hashTable[h];
|
|
306
|
+
hashTable[h] = current; /* Update Hash Table */
|
|
307
|
+
|
|
308
|
+
while (nbCompares-- && (matchIndex > windowLow)) {
|
|
309
|
+
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
|
310
|
+
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
|
311
|
+
const BYTE* match;
|
|
312
|
+
|
|
313
|
+
if ((dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) {
|
|
314
|
+
match = base + matchIndex;
|
|
315
|
+
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
|
|
316
|
+
} else {
|
|
317
|
+
match = dictBase + matchIndex;
|
|
318
|
+
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
|
|
319
|
+
if (matchIndex+matchLength >= dictLimit)
|
|
320
|
+
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (matchLength > bestLength) {
|
|
324
|
+
if (matchLength > matchEndIdx - matchIndex)
|
|
325
|
+
matchEndIdx = matchIndex + (U32)matchLength;
|
|
326
|
+
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
|
|
327
|
+
bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
|
|
328
|
+
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
|
|
329
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
330
|
+
nbCompares = 0; /* in addition to avoiding checking any
|
|
331
|
+
* further in this loop, make sure we
|
|
332
|
+
* skip checking in the dictionary. */
|
|
333
|
+
}
|
|
334
|
+
break; /* drop, to guarantee consistency (miss a little bit of compression) */
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (match[matchLength] < ip[matchLength]) {
|
|
339
|
+
/* match is smaller than current */
|
|
340
|
+
*smallerPtr = matchIndex; /* update smaller idx */
|
|
341
|
+
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
|
|
342
|
+
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
|
343
|
+
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
|
|
344
|
+
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
|
|
345
|
+
} else {
|
|
346
|
+
/* match is larger than current */
|
|
347
|
+
*largerPtr = matchIndex;
|
|
348
|
+
commonLengthLarger = matchLength;
|
|
349
|
+
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
|
350
|
+
largerPtr = nextPtr;
|
|
351
|
+
matchIndex = nextPtr[0];
|
|
352
|
+
} }
|
|
353
|
+
|
|
354
|
+
*smallerPtr = *largerPtr = 0;
|
|
355
|
+
|
|
356
|
+
if (dictMode == ZSTD_dictMatchState && nbCompares) {
|
|
357
|
+
bestLength = ZSTD_DUBT_findBetterDictMatch(
|
|
358
|
+
ms, ip, iend,
|
|
359
|
+
offsetPtr, bestLength, nbCompares,
|
|
360
|
+
mls, dictMode);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
assert(matchEndIdx > current+8); /* ensure nextToUpdate is increased */
|
|
364
|
+
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
|
|
365
|
+
if (bestLength >= MINMATCH) {
|
|
366
|
+
U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
|
|
367
|
+
DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
|
|
368
|
+
current, (U32)bestLength, (U32)*offsetPtr, mIndex);
|
|
369
|
+
}
|
|
370
|
+
return bestLength;
|
|
371
|
+
}
|
|
250
372
|
}
|
|
251
373
|
|
|
252
374
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
375
|
+
/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
|
|
376
|
+
FORCE_INLINE_TEMPLATE size_t
|
|
377
|
+
ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms,
|
|
378
|
+
const BYTE* const ip, const BYTE* const iLimit,
|
|
379
|
+
size_t* offsetPtr,
|
|
380
|
+
const U32 mls /* template */,
|
|
381
|
+
const ZSTD_dictMode_e dictMode)
|
|
382
|
+
{
|
|
383
|
+
DEBUGLOG(7, "ZSTD_BtFindBestMatch");
|
|
384
|
+
if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
|
|
385
|
+
ZSTD_updateDUBT(ms, ip, iLimit, mls);
|
|
386
|
+
return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offsetPtr, mls, dictMode);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
static size_t
|
|
391
|
+
ZSTD_BtFindBestMatch_selectMLS ( ZSTD_matchState_t* ms,
|
|
392
|
+
const BYTE* ip, const BYTE* const iLimit,
|
|
393
|
+
size_t* offsetPtr)
|
|
258
394
|
{
|
|
259
|
-
switch(
|
|
395
|
+
switch(ms->cParams.minMatch)
|
|
260
396
|
{
|
|
261
397
|
default : /* includes case 3 */
|
|
262
|
-
case 4 : return ZSTD_BtFindBestMatch(
|
|
263
|
-
case 5 : return ZSTD_BtFindBestMatch(
|
|
398
|
+
case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
|
|
399
|
+
case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
|
|
264
400
|
case 7 :
|
|
265
|
-
case 6 : return ZSTD_BtFindBestMatch(
|
|
401
|
+
case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
|
|
266
402
|
}
|
|
267
403
|
}
|
|
268
404
|
|
|
269
405
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
size_t* offsetPtr,
|
|
275
|
-
const U32 maxNbAttempts, const U32 mls)
|
|
406
|
+
static size_t ZSTD_BtFindBestMatch_dictMatchState_selectMLS (
|
|
407
|
+
ZSTD_matchState_t* ms,
|
|
408
|
+
const BYTE* ip, const BYTE* const iLimit,
|
|
409
|
+
size_t* offsetPtr)
|
|
276
410
|
{
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
411
|
+
switch(ms->cParams.minMatch)
|
|
412
|
+
{
|
|
413
|
+
default : /* includes case 3 */
|
|
414
|
+
case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
|
|
415
|
+
case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
|
|
416
|
+
case 7 :
|
|
417
|
+
case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
|
|
418
|
+
}
|
|
280
419
|
}
|
|
281
420
|
|
|
282
421
|
|
|
283
|
-
static size_t
|
|
284
|
-
|
|
422
|
+
static size_t ZSTD_BtFindBestMatch_extDict_selectMLS (
|
|
423
|
+
ZSTD_matchState_t* ms,
|
|
285
424
|
const BYTE* ip, const BYTE* const iLimit,
|
|
286
|
-
size_t* offsetPtr
|
|
287
|
-
const U32 maxNbAttempts, const U32 matchLengthSearch)
|
|
425
|
+
size_t* offsetPtr)
|
|
288
426
|
{
|
|
289
|
-
switch(
|
|
427
|
+
switch(ms->cParams.minMatch)
|
|
290
428
|
{
|
|
291
429
|
default : /* includes case 3 */
|
|
292
|
-
case 4 : return
|
|
293
|
-
case 5 : return
|
|
430
|
+
case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
|
|
431
|
+
case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
|
|
294
432
|
case 7 :
|
|
295
|
-
case 6 : return
|
|
433
|
+
case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
|
|
296
434
|
}
|
|
297
435
|
}
|
|
298
436
|
|
|
@@ -301,19 +439,22 @@ static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
|
|
|
301
439
|
/* *********************************
|
|
302
440
|
* Hash Chain
|
|
303
441
|
***********************************/
|
|
304
|
-
#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
|
|
442
|
+
#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & (mask)]
|
|
305
443
|
|
|
306
444
|
/* Update chains up to ip (excluded)
|
|
307
445
|
Assumption : always within prefix (i.e. not within extDict) */
|
|
308
|
-
U32
|
|
446
|
+
static U32 ZSTD_insertAndFindFirstIndex_internal(
|
|
447
|
+
ZSTD_matchState_t* ms,
|
|
448
|
+
const ZSTD_compressionParameters* const cParams,
|
|
449
|
+
const BYTE* ip, U32 const mls)
|
|
309
450
|
{
|
|
310
|
-
U32* const hashTable =
|
|
311
|
-
const U32 hashLog =
|
|
312
|
-
U32* const chainTable =
|
|
313
|
-
const U32 chainMask = (1 <<
|
|
314
|
-
const BYTE* const base =
|
|
451
|
+
U32* const hashTable = ms->hashTable;
|
|
452
|
+
const U32 hashLog = cParams->hashLog;
|
|
453
|
+
U32* const chainTable = ms->chainTable;
|
|
454
|
+
const U32 chainMask = (1 << cParams->chainLog) - 1;
|
|
455
|
+
const BYTE* const base = ms->window.base;
|
|
315
456
|
const U32 target = (U32)(ip - base);
|
|
316
|
-
U32 idx =
|
|
457
|
+
U32 idx = ms->nextToUpdate;
|
|
317
458
|
|
|
318
459
|
while(idx < target) { /* catch up */
|
|
319
460
|
size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
|
|
@@ -322,40 +463,47 @@ U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
|
|
|
322
463
|
idx++;
|
|
323
464
|
}
|
|
324
465
|
|
|
325
|
-
|
|
466
|
+
ms->nextToUpdate = target;
|
|
326
467
|
return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
|
|
327
468
|
}
|
|
328
469
|
|
|
470
|
+
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) {
|
|
471
|
+
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
|
472
|
+
return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch);
|
|
473
|
+
}
|
|
474
|
+
|
|
329
475
|
|
|
330
476
|
/* inlining is important to hardwire a hot branch (template emulation) */
|
|
331
477
|
FORCE_INLINE_TEMPLATE
|
|
332
478
|
size_t ZSTD_HcFindBestMatch_generic (
|
|
333
|
-
|
|
479
|
+
ZSTD_matchState_t* ms,
|
|
334
480
|
const BYTE* const ip, const BYTE* const iLimit,
|
|
335
481
|
size_t* offsetPtr,
|
|
336
|
-
const U32
|
|
482
|
+
const U32 mls, const ZSTD_dictMode_e dictMode)
|
|
337
483
|
{
|
|
338
|
-
|
|
339
|
-
const
|
|
484
|
+
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
|
485
|
+
U32* const chainTable = ms->chainTable;
|
|
486
|
+
const U32 chainSize = (1 << cParams->chainLog);
|
|
340
487
|
const U32 chainMask = chainSize-1;
|
|
341
|
-
const BYTE* const base =
|
|
342
|
-
const BYTE* const dictBase =
|
|
343
|
-
const U32 dictLimit =
|
|
488
|
+
const BYTE* const base = ms->window.base;
|
|
489
|
+
const BYTE* const dictBase = ms->window.dictBase;
|
|
490
|
+
const U32 dictLimit = ms->window.dictLimit;
|
|
344
491
|
const BYTE* const prefixStart = base + dictLimit;
|
|
345
492
|
const BYTE* const dictEnd = dictBase + dictLimit;
|
|
346
|
-
const U32 lowLimit =
|
|
493
|
+
const U32 lowLimit = ms->window.lowLimit;
|
|
347
494
|
const U32 current = (U32)(ip-base);
|
|
348
495
|
const U32 minChain = current > chainSize ? current - chainSize : 0;
|
|
349
|
-
|
|
496
|
+
U32 nbAttempts = 1U << cParams->searchLog;
|
|
350
497
|
size_t ml=4-1;
|
|
351
498
|
|
|
352
499
|
/* HC4 match finder */
|
|
353
|
-
U32 matchIndex =
|
|
500
|
+
U32 matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls);
|
|
354
501
|
|
|
355
502
|
for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
|
|
356
503
|
size_t currentMl=0;
|
|
357
|
-
if ((
|
|
504
|
+
if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {
|
|
358
505
|
const BYTE* const match = base + matchIndex;
|
|
506
|
+
assert(matchIndex >= dictLimit); /* ensures this is true if dictMode != ZSTD_extDict */
|
|
359
507
|
if (match[ml] == ip[ml]) /* potentially better */
|
|
360
508
|
currentMl = ZSTD_count(ip, match, iLimit);
|
|
361
509
|
} else {
|
|
@@ -376,40 +524,87 @@ size_t ZSTD_HcFindBestMatch_generic (
|
|
|
376
524
|
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
|
|
377
525
|
}
|
|
378
526
|
|
|
527
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
528
|
+
const ZSTD_matchState_t* const dms = ms->dictMatchState;
|
|
529
|
+
const U32* const dmsChainTable = dms->chainTable;
|
|
530
|
+
const U32 dmsChainSize = (1 << dms->cParams.chainLog);
|
|
531
|
+
const U32 dmsChainMask = dmsChainSize - 1;
|
|
532
|
+
const U32 dmsLowestIndex = dms->window.dictLimit;
|
|
533
|
+
const BYTE* const dmsBase = dms->window.base;
|
|
534
|
+
const BYTE* const dmsEnd = dms->window.nextSrc;
|
|
535
|
+
const U32 dmsSize = (U32)(dmsEnd - dmsBase);
|
|
536
|
+
const U32 dmsIndexDelta = dictLimit - dmsSize;
|
|
537
|
+
const U32 dmsMinChain = dmsSize > dmsChainSize ? dmsSize - dmsChainSize : 0;
|
|
538
|
+
|
|
539
|
+
matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)];
|
|
540
|
+
|
|
541
|
+
for ( ; (matchIndex>dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) {
|
|
542
|
+
size_t currentMl=0;
|
|
543
|
+
const BYTE* const match = dmsBase + matchIndex;
|
|
544
|
+
assert(match+4 <= dmsEnd);
|
|
545
|
+
if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
|
|
546
|
+
currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4;
|
|
547
|
+
|
|
548
|
+
/* save best solution */
|
|
549
|
+
if (currentMl > ml) {
|
|
550
|
+
ml = currentMl;
|
|
551
|
+
*offsetPtr = current - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
|
|
552
|
+
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if (matchIndex <= dmsMinChain) break;
|
|
556
|
+
matchIndex = dmsChainTable[matchIndex & dmsChainMask];
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
379
560
|
return ml;
|
|
380
561
|
}
|
|
381
562
|
|
|
382
563
|
|
|
383
564
|
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
|
|
384
|
-
|
|
565
|
+
ZSTD_matchState_t* ms,
|
|
385
566
|
const BYTE* ip, const BYTE* const iLimit,
|
|
386
|
-
size_t* offsetPtr
|
|
387
|
-
|
|
567
|
+
size_t* offsetPtr)
|
|
568
|
+
{
|
|
569
|
+
switch(ms->cParams.minMatch)
|
|
570
|
+
{
|
|
571
|
+
default : /* includes case 3 */
|
|
572
|
+
case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
|
|
573
|
+
case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
|
|
574
|
+
case 7 :
|
|
575
|
+
case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS (
|
|
581
|
+
ZSTD_matchState_t* ms,
|
|
582
|
+
const BYTE* ip, const BYTE* const iLimit,
|
|
583
|
+
size_t* offsetPtr)
|
|
388
584
|
{
|
|
389
|
-
switch(
|
|
585
|
+
switch(ms->cParams.minMatch)
|
|
390
586
|
{
|
|
391
587
|
default : /* includes case 3 */
|
|
392
|
-
case 4 : return ZSTD_HcFindBestMatch_generic(
|
|
393
|
-
case 5 : return ZSTD_HcFindBestMatch_generic(
|
|
588
|
+
case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
|
|
589
|
+
case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
|
|
394
590
|
case 7 :
|
|
395
|
-
case 6 : return ZSTD_HcFindBestMatch_generic(
|
|
591
|
+
case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
|
|
396
592
|
}
|
|
397
593
|
}
|
|
398
594
|
|
|
399
595
|
|
|
400
596
|
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
|
|
401
|
-
|
|
597
|
+
ZSTD_matchState_t* ms,
|
|
402
598
|
const BYTE* ip, const BYTE* const iLimit,
|
|
403
|
-
size_t*
|
|
404
|
-
U32 const maxNbAttempts, U32 const matchLengthSearch)
|
|
599
|
+
size_t* offsetPtr)
|
|
405
600
|
{
|
|
406
|
-
switch(
|
|
601
|
+
switch(ms->cParams.minMatch)
|
|
407
602
|
{
|
|
408
603
|
default : /* includes case 3 */
|
|
409
|
-
case 4 : return ZSTD_HcFindBestMatch_generic(
|
|
410
|
-
case 5 : return ZSTD_HcFindBestMatch_generic(
|
|
604
|
+
case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
|
|
605
|
+
case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
|
|
411
606
|
case 7 :
|
|
412
|
-
case 6 : return ZSTD_HcFindBestMatch_generic(
|
|
607
|
+
case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
|
|
413
608
|
}
|
|
414
609
|
}
|
|
415
610
|
|
|
@@ -418,34 +613,58 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
|
|
|
418
613
|
* Common parser - lazy strategy
|
|
419
614
|
*********************************/
|
|
420
615
|
FORCE_INLINE_TEMPLATE
|
|
421
|
-
size_t ZSTD_compressBlock_lazy_generic(
|
|
422
|
-
|
|
423
|
-
|
|
616
|
+
size_t ZSTD_compressBlock_lazy_generic(
|
|
617
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore,
|
|
618
|
+
U32 rep[ZSTD_REP_NUM],
|
|
619
|
+
const void* src, size_t srcSize,
|
|
620
|
+
const U32 searchMethod, const U32 depth,
|
|
621
|
+
ZSTD_dictMode_e const dictMode)
|
|
424
622
|
{
|
|
425
|
-
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
|
426
623
|
const BYTE* const istart = (const BYTE*)src;
|
|
427
624
|
const BYTE* ip = istart;
|
|
428
625
|
const BYTE* anchor = istart;
|
|
429
626
|
const BYTE* const iend = istart + srcSize;
|
|
430
627
|
const BYTE* const ilimit = iend - 8;
|
|
431
|
-
const BYTE* const base =
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
size_t* offsetPtr
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
628
|
+
const BYTE* const base = ms->window.base;
|
|
629
|
+
const U32 prefixLowestIndex = ms->window.dictLimit;
|
|
630
|
+
const BYTE* const prefixLowest = base + prefixLowestIndex;
|
|
631
|
+
|
|
632
|
+
typedef size_t (*searchMax_f)(
|
|
633
|
+
ZSTD_matchState_t* ms,
|
|
634
|
+
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
|
|
635
|
+
searchMax_f const searchMax = dictMode == ZSTD_dictMatchState ?
|
|
636
|
+
(searchMethod ? ZSTD_BtFindBestMatch_dictMatchState_selectMLS : ZSTD_HcFindBestMatch_dictMatchState_selectMLS) :
|
|
637
|
+
(searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS);
|
|
638
|
+
U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0;
|
|
639
|
+
|
|
640
|
+
const ZSTD_matchState_t* const dms = ms->dictMatchState;
|
|
641
|
+
const U32 dictLowestIndex = dictMode == ZSTD_dictMatchState ?
|
|
642
|
+
dms->window.dictLimit : 0;
|
|
643
|
+
const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
|
|
644
|
+
dms->window.base : NULL;
|
|
645
|
+
const BYTE* const dictLowest = dictMode == ZSTD_dictMatchState ?
|
|
646
|
+
dictBase + dictLowestIndex : NULL;
|
|
647
|
+
const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
|
|
648
|
+
dms->window.nextSrc : NULL;
|
|
649
|
+
const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
|
|
650
|
+
prefixLowestIndex - (U32)(dictEnd - dictBase) :
|
|
651
|
+
0;
|
|
652
|
+
const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictLowest);
|
|
441
653
|
|
|
442
654
|
/* init */
|
|
443
|
-
ip += (
|
|
444
|
-
|
|
445
|
-
|
|
655
|
+
ip += (dictAndPrefixLength == 0);
|
|
656
|
+
ms->nextToUpdate3 = ms->nextToUpdate;
|
|
657
|
+
if (dictMode == ZSTD_noDict) {
|
|
658
|
+
U32 const maxRep = (U32)(ip - prefixLowest);
|
|
446
659
|
if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
|
|
447
660
|
if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
|
|
448
661
|
}
|
|
662
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
663
|
+
/* dictMatchState repCode checks don't currently handle repCode == 0
|
|
664
|
+
* disabling. */
|
|
665
|
+
assert(offset_1 <= dictAndPrefixLength);
|
|
666
|
+
assert(offset_2 <= dictAndPrefixLength);
|
|
667
|
+
}
|
|
449
668
|
|
|
450
669
|
/* Match Loop */
|
|
451
670
|
while (ip < ilimit) {
|
|
@@ -454,21 +673,34 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
|
|
454
673
|
const BYTE* start=ip+1;
|
|
455
674
|
|
|
456
675
|
/* check repCode */
|
|
457
|
-
if (
|
|
458
|
-
|
|
676
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
677
|
+
const U32 repIndex = (U32)(ip - base) + 1 - offset_1;
|
|
678
|
+
const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
|
|
679
|
+
&& repIndex < prefixLowestIndex) ?
|
|
680
|
+
dictBase + (repIndex - dictIndexDelta) :
|
|
681
|
+
base + repIndex;
|
|
682
|
+
if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
|
|
683
|
+
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
|
684
|
+
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
|
685
|
+
matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
|
686
|
+
if (depth==0) goto _storeSequence;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
if ( dictMode == ZSTD_noDict
|
|
690
|
+
&& ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
|
|
459
691
|
matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
|
460
692
|
if (depth==0) goto _storeSequence;
|
|
461
693
|
}
|
|
462
694
|
|
|
463
695
|
/* first search (depth 0) */
|
|
464
|
-
{ size_t offsetFound =
|
|
465
|
-
size_t const ml2 = searchMax(
|
|
696
|
+
{ size_t offsetFound = 999999999;
|
|
697
|
+
size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
|
|
466
698
|
if (ml2 > matchLength)
|
|
467
699
|
matchLength = ml2, start = ip, offset=offsetFound;
|
|
468
700
|
}
|
|
469
701
|
|
|
470
702
|
if (matchLength < 4) {
|
|
471
|
-
ip += ((ip-anchor) >>
|
|
703
|
+
ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */
|
|
472
704
|
continue;
|
|
473
705
|
}
|
|
474
706
|
|
|
@@ -476,15 +708,31 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
|
|
476
708
|
if (depth>=1)
|
|
477
709
|
while (ip<ilimit) {
|
|
478
710
|
ip ++;
|
|
479
|
-
if (
|
|
711
|
+
if ( (dictMode == ZSTD_noDict)
|
|
712
|
+
&& (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
|
480
713
|
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
|
481
714
|
int const gain2 = (int)(mlRep * 3);
|
|
482
715
|
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
|
483
716
|
if ((mlRep >= 4) && (gain2 > gain1))
|
|
484
717
|
matchLength = mlRep, offset = 0, start = ip;
|
|
485
718
|
}
|
|
486
|
-
{
|
|
487
|
-
|
|
719
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
720
|
+
const U32 repIndex = (U32)(ip - base) - offset_1;
|
|
721
|
+
const BYTE* repMatch = repIndex < prefixLowestIndex ?
|
|
722
|
+
dictBase + (repIndex - dictIndexDelta) :
|
|
723
|
+
base + repIndex;
|
|
724
|
+
if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
|
|
725
|
+
&& (MEM_read32(repMatch) == MEM_read32(ip)) ) {
|
|
726
|
+
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
|
727
|
+
size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
|
728
|
+
int const gain2 = (int)(mlRep * 3);
|
|
729
|
+
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
|
730
|
+
if ((mlRep >= 4) && (gain2 > gain1))
|
|
731
|
+
matchLength = mlRep, offset = 0, start = ip;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
{ size_t offset2=999999999;
|
|
735
|
+
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
|
488
736
|
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
|
489
737
|
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
|
|
490
738
|
if ((ml2 >= 4) && (gain2 > gain1)) {
|
|
@@ -495,15 +743,31 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
|
|
495
743
|
/* let's find an even better one */
|
|
496
744
|
if ((depth==2) && (ip<ilimit)) {
|
|
497
745
|
ip ++;
|
|
498
|
-
if (
|
|
499
|
-
|
|
500
|
-
|
|
746
|
+
if ( (dictMode == ZSTD_noDict)
|
|
747
|
+
&& (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
|
748
|
+
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
|
749
|
+
int const gain2 = (int)(mlRep * 4);
|
|
501
750
|
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
|
502
|
-
if ((
|
|
503
|
-
matchLength =
|
|
751
|
+
if ((mlRep >= 4) && (gain2 > gain1))
|
|
752
|
+
matchLength = mlRep, offset = 0, start = ip;
|
|
504
753
|
}
|
|
505
|
-
{
|
|
506
|
-
|
|
754
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
755
|
+
const U32 repIndex = (U32)(ip - base) - offset_1;
|
|
756
|
+
const BYTE* repMatch = repIndex < prefixLowestIndex ?
|
|
757
|
+
dictBase + (repIndex - dictIndexDelta) :
|
|
758
|
+
base + repIndex;
|
|
759
|
+
if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
|
|
760
|
+
&& (MEM_read32(repMatch) == MEM_read32(ip)) ) {
|
|
761
|
+
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
|
|
762
|
+
size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
|
|
763
|
+
int const gain2 = (int)(mlRep * 4);
|
|
764
|
+
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
|
765
|
+
if ((mlRep >= 4) && (gain2 > gain1))
|
|
766
|
+
matchLength = mlRep, offset = 0, start = ip;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
{ size_t offset2=999999999;
|
|
770
|
+
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
|
507
771
|
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
|
508
772
|
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
|
|
509
773
|
if ((ml2 >= 4) && (gain2 > gain1)) {
|
|
@@ -520,91 +784,156 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
|
|
520
784
|
*/
|
|
521
785
|
/* catch up */
|
|
522
786
|
if (offset) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
787
|
+
if (dictMode == ZSTD_noDict) {
|
|
788
|
+
while ( ((start > anchor) & (start - (offset-ZSTD_REP_MOVE) > prefixLowest))
|
|
789
|
+
&& (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */
|
|
790
|
+
{ start--; matchLength++; }
|
|
791
|
+
}
|
|
792
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
793
|
+
U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
|
|
794
|
+
const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex;
|
|
795
|
+
const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest;
|
|
796
|
+
while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
|
|
797
|
+
}
|
|
526
798
|
offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
|
|
527
799
|
}
|
|
528
800
|
/* store sequence */
|
|
529
801
|
_storeSequence:
|
|
530
802
|
{ size_t const litLength = start - anchor;
|
|
531
|
-
ZSTD_storeSeq(
|
|
803
|
+
ZSTD_storeSeq(seqStore, litLength, anchor, (U32)offset, matchLength-MINMATCH);
|
|
532
804
|
anchor = ip = start + matchLength;
|
|
533
805
|
}
|
|
534
806
|
|
|
535
807
|
/* check immediate repcode */
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
808
|
+
if (dictMode == ZSTD_dictMatchState) {
|
|
809
|
+
while (ip <= ilimit) {
|
|
810
|
+
U32 const current2 = (U32)(ip-base);
|
|
811
|
+
U32 const repIndex = current2 - offset_2;
|
|
812
|
+
const BYTE* repMatch = dictMode == ZSTD_dictMatchState
|
|
813
|
+
&& repIndex < prefixLowestIndex ?
|
|
814
|
+
dictBase - dictIndexDelta + repIndex :
|
|
815
|
+
base + repIndex;
|
|
816
|
+
if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */)
|
|
817
|
+
&& (MEM_read32(repMatch) == MEM_read32(ip)) ) {
|
|
818
|
+
const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend;
|
|
819
|
+
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4;
|
|
820
|
+
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset_2 <=> offset_1 */
|
|
821
|
+
ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
|
|
822
|
+
ip += matchLength;
|
|
823
|
+
anchor = ip;
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
break;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
if (dictMode == ZSTD_noDict) {
|
|
831
|
+
while ( ((ip <= ilimit) & (offset_2>0))
|
|
832
|
+
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
|
|
833
|
+
/* store sequence */
|
|
834
|
+
matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
|
835
|
+
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
|
|
836
|
+
ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
|
|
837
|
+
ip += matchLength;
|
|
838
|
+
anchor = ip;
|
|
839
|
+
continue; /* faster when present ... (?) */
|
|
840
|
+
} } }
|
|
546
841
|
|
|
547
842
|
/* Save reps for next block */
|
|
548
|
-
|
|
549
|
-
|
|
843
|
+
rep[0] = offset_1 ? offset_1 : savedOffset;
|
|
844
|
+
rep[1] = offset_2 ? offset_2 : savedOffset;
|
|
550
845
|
|
|
551
846
|
/* Return the last literals size */
|
|
552
847
|
return iend - anchor;
|
|
553
848
|
}
|
|
554
849
|
|
|
555
850
|
|
|
556
|
-
size_t ZSTD_compressBlock_btlazy2(
|
|
851
|
+
size_t ZSTD_compressBlock_btlazy2(
|
|
852
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
853
|
+
void const* src, size_t srcSize)
|
|
557
854
|
{
|
|
558
|
-
return ZSTD_compressBlock_lazy_generic(
|
|
855
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 1, 2, ZSTD_noDict);
|
|
559
856
|
}
|
|
560
857
|
|
|
561
|
-
size_t ZSTD_compressBlock_lazy2(
|
|
858
|
+
size_t ZSTD_compressBlock_lazy2(
|
|
859
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
860
|
+
void const* src, size_t srcSize)
|
|
562
861
|
{
|
|
563
|
-
return ZSTD_compressBlock_lazy_generic(
|
|
862
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 2, ZSTD_noDict);
|
|
564
863
|
}
|
|
565
864
|
|
|
566
|
-
size_t ZSTD_compressBlock_lazy(
|
|
865
|
+
size_t ZSTD_compressBlock_lazy(
|
|
866
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
867
|
+
void const* src, size_t srcSize)
|
|
567
868
|
{
|
|
568
|
-
return ZSTD_compressBlock_lazy_generic(
|
|
869
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 1, ZSTD_noDict);
|
|
569
870
|
}
|
|
570
871
|
|
|
571
|
-
size_t ZSTD_compressBlock_greedy(
|
|
872
|
+
size_t ZSTD_compressBlock_greedy(
|
|
873
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
874
|
+
void const* src, size_t srcSize)
|
|
572
875
|
{
|
|
573
|
-
return ZSTD_compressBlock_lazy_generic(
|
|
876
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 0, ZSTD_noDict);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
size_t ZSTD_compressBlock_btlazy2_dictMatchState(
|
|
880
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
881
|
+
void const* src, size_t srcSize)
|
|
882
|
+
{
|
|
883
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 1, 2, ZSTD_dictMatchState);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
size_t ZSTD_compressBlock_lazy2_dictMatchState(
|
|
887
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
888
|
+
void const* src, size_t srcSize)
|
|
889
|
+
{
|
|
890
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 2, ZSTD_dictMatchState);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
size_t ZSTD_compressBlock_lazy_dictMatchState(
|
|
894
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
895
|
+
void const* src, size_t srcSize)
|
|
896
|
+
{
|
|
897
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 1, ZSTD_dictMatchState);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
size_t ZSTD_compressBlock_greedy_dictMatchState(
|
|
901
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
902
|
+
void const* src, size_t srcSize)
|
|
903
|
+
{
|
|
904
|
+
return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 0, ZSTD_dictMatchState);
|
|
574
905
|
}
|
|
575
906
|
|
|
576
907
|
|
|
577
908
|
FORCE_INLINE_TEMPLATE
|
|
578
|
-
size_t ZSTD_compressBlock_lazy_extDict_generic(
|
|
579
|
-
|
|
580
|
-
|
|
909
|
+
size_t ZSTD_compressBlock_lazy_extDict_generic(
|
|
910
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore,
|
|
911
|
+
U32 rep[ZSTD_REP_NUM],
|
|
912
|
+
const void* src, size_t srcSize,
|
|
913
|
+
const U32 searchMethod, const U32 depth)
|
|
581
914
|
{
|
|
582
|
-
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
|
583
915
|
const BYTE* const istart = (const BYTE*)src;
|
|
584
916
|
const BYTE* ip = istart;
|
|
585
917
|
const BYTE* anchor = istart;
|
|
586
918
|
const BYTE* const iend = istart + srcSize;
|
|
587
919
|
const BYTE* const ilimit = iend - 8;
|
|
588
|
-
const BYTE* const base =
|
|
589
|
-
const U32 dictLimit =
|
|
590
|
-
const U32 lowestIndex =
|
|
920
|
+
const BYTE* const base = ms->window.base;
|
|
921
|
+
const U32 dictLimit = ms->window.dictLimit;
|
|
922
|
+
const U32 lowestIndex = ms->window.lowLimit;
|
|
591
923
|
const BYTE* const prefixStart = base + dictLimit;
|
|
592
|
-
const BYTE* const dictBase =
|
|
924
|
+
const BYTE* const dictBase = ms->window.dictBase;
|
|
593
925
|
const BYTE* const dictEnd = dictBase + dictLimit;
|
|
594
|
-
const BYTE* const dictStart = dictBase +
|
|
926
|
+
const BYTE* const dictStart = dictBase + lowestIndex;
|
|
595
927
|
|
|
596
|
-
|
|
597
|
-
|
|
928
|
+
typedef size_t (*searchMax_f)(
|
|
929
|
+
ZSTD_matchState_t* ms,
|
|
930
|
+
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
|
|
931
|
+
searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_extDict_selectMLS : ZSTD_HcFindBestMatch_extDict_selectMLS;
|
|
598
932
|
|
|
599
|
-
|
|
600
|
-
size_t* offsetPtr,
|
|
601
|
-
U32 maxNbAttempts, U32 matchLengthSearch);
|
|
602
|
-
searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
|
|
603
|
-
|
|
604
|
-
U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1];
|
|
933
|
+
U32 offset_1 = rep[0], offset_2 = rep[1];
|
|
605
934
|
|
|
606
935
|
/* init */
|
|
607
|
-
|
|
936
|
+
ms->nextToUpdate3 = ms->nextToUpdate;
|
|
608
937
|
ip += (ip == prefixStart);
|
|
609
938
|
|
|
610
939
|
/* Match Loop */
|
|
@@ -627,14 +956,14 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
|
|
627
956
|
} }
|
|
628
957
|
|
|
629
958
|
/* first search (depth 0) */
|
|
630
|
-
{ size_t offsetFound =
|
|
631
|
-
size_t const ml2 = searchMax(
|
|
959
|
+
{ size_t offsetFound = 999999999;
|
|
960
|
+
size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
|
|
632
961
|
if (ml2 > matchLength)
|
|
633
962
|
matchLength = ml2, start = ip, offset=offsetFound;
|
|
634
963
|
}
|
|
635
964
|
|
|
636
965
|
if (matchLength < 4) {
|
|
637
|
-
ip += ((ip-anchor) >>
|
|
966
|
+
ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */
|
|
638
967
|
continue;
|
|
639
968
|
}
|
|
640
969
|
|
|
@@ -660,8 +989,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
|
|
660
989
|
} }
|
|
661
990
|
|
|
662
991
|
/* search match, depth 1 */
|
|
663
|
-
{ size_t offset2=
|
|
664
|
-
size_t const ml2 = searchMax(
|
|
992
|
+
{ size_t offset2=999999999;
|
|
993
|
+
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
|
665
994
|
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
|
666
995
|
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
|
|
667
996
|
if ((ml2 >= 4) && (gain2 > gain1)) {
|
|
@@ -690,8 +1019,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
|
|
690
1019
|
} }
|
|
691
1020
|
|
|
692
1021
|
/* search match, depth 2 */
|
|
693
|
-
{ size_t offset2=
|
|
694
|
-
size_t const ml2 = searchMax(
|
|
1022
|
+
{ size_t offset2=999999999;
|
|
1023
|
+
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
|
|
695
1024
|
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
|
696
1025
|
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
|
|
697
1026
|
if ((ml2 >= 4) && (gain2 > gain1)) {
|
|
@@ -713,7 +1042,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
|
|
713
1042
|
/* store sequence */
|
|
714
1043
|
_storeSequence:
|
|
715
1044
|
{ size_t const litLength = start - anchor;
|
|
716
|
-
ZSTD_storeSeq(
|
|
1045
|
+
ZSTD_storeSeq(seqStore, litLength, anchor, (U32)offset, matchLength-MINMATCH);
|
|
717
1046
|
anchor = ip = start + matchLength;
|
|
718
1047
|
}
|
|
719
1048
|
|
|
@@ -728,7 +1057,7 @@ _storeSequence:
|
|
|
728
1057
|
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
|
729
1058
|
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
|
730
1059
|
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
|
|
731
|
-
ZSTD_storeSeq(
|
|
1060
|
+
ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
|
|
732
1061
|
ip += matchLength;
|
|
733
1062
|
anchor = ip;
|
|
734
1063
|
continue; /* faster when present ... (?) */
|
|
@@ -737,29 +1066,41 @@ _storeSequence:
|
|
|
737
1066
|
} }
|
|
738
1067
|
|
|
739
1068
|
/* Save reps for next block */
|
|
740
|
-
|
|
1069
|
+
rep[0] = offset_1;
|
|
1070
|
+
rep[1] = offset_2;
|
|
741
1071
|
|
|
742
1072
|
/* Return the last literals size */
|
|
743
1073
|
return iend - anchor;
|
|
744
1074
|
}
|
|
745
1075
|
|
|
746
1076
|
|
|
747
|
-
size_t ZSTD_compressBlock_greedy_extDict(
|
|
1077
|
+
size_t ZSTD_compressBlock_greedy_extDict(
|
|
1078
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
1079
|
+
void const* src, size_t srcSize)
|
|
748
1080
|
{
|
|
749
|
-
return ZSTD_compressBlock_lazy_extDict_generic(
|
|
1081
|
+
return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 0, 0);
|
|
750
1082
|
}
|
|
751
1083
|
|
|
752
|
-
size_t ZSTD_compressBlock_lazy_extDict(
|
|
1084
|
+
size_t ZSTD_compressBlock_lazy_extDict(
|
|
1085
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
1086
|
+
void const* src, size_t srcSize)
|
|
1087
|
+
|
|
753
1088
|
{
|
|
754
|
-
return ZSTD_compressBlock_lazy_extDict_generic(
|
|
1089
|
+
return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 0, 1);
|
|
755
1090
|
}
|
|
756
1091
|
|
|
757
|
-
size_t ZSTD_compressBlock_lazy2_extDict(
|
|
1092
|
+
size_t ZSTD_compressBlock_lazy2_extDict(
|
|
1093
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
1094
|
+
void const* src, size_t srcSize)
|
|
1095
|
+
|
|
758
1096
|
{
|
|
759
|
-
return ZSTD_compressBlock_lazy_extDict_generic(
|
|
1097
|
+
return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 0, 2);
|
|
760
1098
|
}
|
|
761
1099
|
|
|
762
|
-
size_t ZSTD_compressBlock_btlazy2_extDict(
|
|
1100
|
+
size_t ZSTD_compressBlock_btlazy2_extDict(
|
|
1101
|
+
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
1102
|
+
void const* src, size_t srcSize)
|
|
1103
|
+
|
|
763
1104
|
{
|
|
764
|
-
return ZSTD_compressBlock_lazy_extDict_generic(
|
|
1105
|
+
return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 1, 2);
|
|
765
1106
|
}
|