zstd-ruby 1.3.1.1 → 1.3.2.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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/.gitignore +1 -0
  4. data/ext/zstdruby/libzstd/Makefile +40 -26
  5. data/ext/zstdruby/libzstd/README.md +68 -45
  6. data/ext/zstdruby/libzstd/common/bitstream.h +35 -23
  7. data/ext/zstdruby/libzstd/common/compiler.h +1 -0
  8. data/ext/zstdruby/libzstd/common/error_private.c +4 -2
  9. data/ext/zstdruby/libzstd/common/error_private.h +4 -4
  10. data/ext/zstdruby/libzstd/common/fse.h +1 -1
  11. data/ext/zstdruby/libzstd/common/huf.h +1 -1
  12. data/ext/zstdruby/libzstd/common/mem.h +1 -0
  13. data/ext/zstdruby/libzstd/common/pool.c +61 -46
  14. data/ext/zstdruby/libzstd/common/pool.h +4 -0
  15. data/ext/zstdruby/libzstd/common/threading.c +11 -15
  16. data/ext/zstdruby/libzstd/common/threading.h +52 -32
  17. data/ext/zstdruby/libzstd/common/zstd_common.c +2 -2
  18. data/ext/zstdruby/libzstd/common/zstd_errors.h +3 -1
  19. data/ext/zstdruby/libzstd/common/zstd_internal.h +95 -21
  20. data/ext/zstdruby/libzstd/compress/fse_compress.c +3 -1
  21. data/ext/zstdruby/libzstd/compress/huf_compress.c +4 -3
  22. data/ext/zstdruby/libzstd/compress/zstd_compress.c +922 -2102
  23. data/ext/zstdruby/libzstd/compress/zstd_compress.h +307 -0
  24. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +308 -0
  25. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +28 -0
  26. data/ext/zstdruby/libzstd/compress/zstd_fast.c +242 -0
  27. data/ext/zstdruby/libzstd/compress/zstd_fast.h +30 -0
  28. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +749 -0
  29. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +38 -0
  30. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +707 -0
  31. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +67 -0
  32. data/ext/zstdruby/libzstd/compress/zstd_opt.c +957 -0
  33. data/ext/zstdruby/libzstd/compress/zstd_opt.h +14 -922
  34. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +210 -133
  35. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +20 -3
  36. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +373 -196
  37. data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -0
  38. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -0
  39. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
  40. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -0
  41. data/ext/zstdruby/libzstd/dictBuilder/cover.c +33 -22
  42. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +8 -5
  43. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -0
  44. data/ext/zstdruby/libzstd/dll/example/Makefile +5 -5
  45. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -0
  46. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -0
  47. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -0
  48. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -0
  49. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -0
  50. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -0
  51. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -0
  52. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -0
  53. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -0
  54. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -0
  55. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -0
  56. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -0
  57. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -0
  58. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -0
  59. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -0
  60. data/ext/zstdruby/libzstd/zstd.h +366 -118
  61. data/lib/zstd-ruby/version.rb +1 -1
  62. metadata +11 -1
@@ -0,0 +1,67 @@
1
+ /*
2
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ */
9
+
10
+ #ifndef ZSTD_LDM_H
11
+ #define ZSTD_LDM_H
12
+
13
+ #include "zstd_compress.h"
14
+
15
+ #if defined (__cplusplus)
16
+ extern "C" {
17
+ #endif
18
+
19
+ /*-*************************************
20
+ * Long distance matching
21
+ ***************************************/
22
+
23
+ #define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_DEFAULTMAX
24
+ #define ZSTD_LDM_HASHEVERYLOG_NOTSET 9999
25
+
26
+ /** ZSTD_compressBlock_ldm_generic() :
27
+ *
28
+ * This is a block compressor intended for long distance matching.
29
+ *
30
+ * The function searches for matches of length at least
31
+ * ldmParams.minMatchLength using a hash table in cctx->ldmState.
32
+ * Matches can be at a distance of up to cParams.windowLog.
33
+ *
34
+ * Upon finding a match, the unmatched literals are compressed using a
35
+ * ZSTD_blockCompressor (depending on the strategy in the compression
36
+ * parameters), which stores the matched sequences. The "long distance"
37
+ * match is then stored with the remaining literals from the
38
+ * ZSTD_blockCompressor. */
39
+ size_t ZSTD_compressBlock_ldm(ZSTD_CCtx* cctx, const void* src, size_t srcSize);
40
+ size_t ZSTD_compressBlock_ldm_extDict(ZSTD_CCtx* ctx,
41
+ const void* src, size_t srcSize);
42
+
43
+ /** ZSTD_ldm_initializeParameters() :
44
+ * Initialize the long distance matching parameters to their default values. */
45
+ size_t ZSTD_ldm_initializeParameters(ldmParams_t* params, U32 enableLdm);
46
+
47
+ /** ZSTD_ldm_getTableSize() :
48
+ * Estimate the space needed for long distance matching tables. */
49
+ size_t ZSTD_ldm_getTableSize(U32 hashLog, U32 bucketSizeLog);
50
+
51
+ /** ZSTD_ldm_getTableSize() :
52
+ * Return prime8bytes^(minMatchLength-1) */
53
+ U64 ZSTD_ldm_getHashPower(U32 minMatchLength);
54
+
55
+ /** ZSTD_ldm_adjustParameters() :
56
+ * If the params->hashEveryLog is not set, set it to its default value based on
57
+ * windowLog and params->hashLog.
58
+ *
59
+ * Ensures that params->bucketSizeLog is <= params->hashLog (setting it to
60
+ * params->hashLog if it is not). */
61
+ void ZSTD_ldm_adjustParameters(ldmParams_t* params, U32 windowLog);
62
+
63
+ #if defined (__cplusplus)
64
+ }
65
+ #endif
66
+
67
+ #endif /* ZSTD_FAST_H */
@@ -0,0 +1,957 @@
1
+ /*
2
+ * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+ #include "zstd_opt.h"
12
+ #include "zstd_lazy.h"
13
+
14
+
15
+ #define ZSTD_LITFREQ_ADD 2
16
+ #define ZSTD_FREQ_DIV 4
17
+ #define ZSTD_MAX_PRICE (1<<30)
18
+
19
+ /*-*************************************
20
+ * Price functions for optimal parser
21
+ ***************************************/
22
+ static void ZSTD_setLog2Prices(optState_t* optPtr)
23
+ {
24
+ optPtr->log2matchLengthSum = ZSTD_highbit32(optPtr->matchLengthSum+1);
25
+ optPtr->log2litLengthSum = ZSTD_highbit32(optPtr->litLengthSum+1);
26
+ optPtr->log2litSum = ZSTD_highbit32(optPtr->litSum+1);
27
+ optPtr->log2offCodeSum = ZSTD_highbit32(optPtr->offCodeSum+1);
28
+ optPtr->factor = 1 + ((optPtr->litSum>>5) / optPtr->litLengthSum) + ((optPtr->litSum<<1) / (optPtr->litSum + optPtr->matchSum));
29
+ }
30
+
31
+
32
+ static void ZSTD_rescaleFreqs(optState_t* optPtr, const BYTE* src, size_t srcSize)
33
+ {
34
+ unsigned u;
35
+
36
+ optPtr->cachedLiterals = NULL;
37
+ optPtr->cachedPrice = optPtr->cachedLitLength = 0;
38
+ optPtr->staticPrices = 0;
39
+
40
+ if (optPtr->litLengthSum == 0) {
41
+ if (srcSize <= 1024) optPtr->staticPrices = 1;
42
+
43
+ assert(optPtr->litFreq!=NULL);
44
+ for (u=0; u<=MaxLit; u++)
45
+ optPtr->litFreq[u] = 0;
46
+ for (u=0; u<srcSize; u++)
47
+ optPtr->litFreq[src[u]]++;
48
+
49
+ optPtr->litSum = 0;
50
+ optPtr->litLengthSum = MaxLL+1;
51
+ optPtr->matchLengthSum = MaxML+1;
52
+ optPtr->offCodeSum = (MaxOff+1);
53
+ optPtr->matchSum = (ZSTD_LITFREQ_ADD<<Litbits);
54
+
55
+ for (u=0; u<=MaxLit; u++) {
56
+ optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>ZSTD_FREQ_DIV);
57
+ optPtr->litSum += optPtr->litFreq[u];
58
+ }
59
+ for (u=0; u<=MaxLL; u++)
60
+ optPtr->litLengthFreq[u] = 1;
61
+ for (u=0; u<=MaxML; u++)
62
+ optPtr->matchLengthFreq[u] = 1;
63
+ for (u=0; u<=MaxOff; u++)
64
+ optPtr->offCodeFreq[u] = 1;
65
+ } else {
66
+ optPtr->matchLengthSum = 0;
67
+ optPtr->litLengthSum = 0;
68
+ optPtr->offCodeSum = 0;
69
+ optPtr->matchSum = 0;
70
+ optPtr->litSum = 0;
71
+
72
+ for (u=0; u<=MaxLit; u++) {
73
+ optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>(ZSTD_FREQ_DIV+1));
74
+ optPtr->litSum += optPtr->litFreq[u];
75
+ }
76
+ for (u=0; u<=MaxLL; u++) {
77
+ optPtr->litLengthFreq[u] = 1 + (optPtr->litLengthFreq[u]>>(ZSTD_FREQ_DIV+1));
78
+ optPtr->litLengthSum += optPtr->litLengthFreq[u];
79
+ }
80
+ for (u=0; u<=MaxML; u++) {
81
+ optPtr->matchLengthFreq[u] = 1 + (optPtr->matchLengthFreq[u]>>ZSTD_FREQ_DIV);
82
+ optPtr->matchLengthSum += optPtr->matchLengthFreq[u];
83
+ optPtr->matchSum += optPtr->matchLengthFreq[u] * (u + 3);
84
+ }
85
+ optPtr->matchSum *= ZSTD_LITFREQ_ADD;
86
+ for (u=0; u<=MaxOff; u++) {
87
+ optPtr->offCodeFreq[u] = 1 + (optPtr->offCodeFreq[u]>>ZSTD_FREQ_DIV);
88
+ optPtr->offCodeSum += optPtr->offCodeFreq[u];
89
+ }
90
+ }
91
+
92
+ ZSTD_setLog2Prices(optPtr);
93
+ }
94
+
95
+
96
+ static U32 ZSTD_getLiteralPrice(optState_t* optPtr, U32 litLength, const BYTE* literals)
97
+ {
98
+ U32 price, u;
99
+
100
+ if (optPtr->staticPrices)
101
+ return ZSTD_highbit32((U32)litLength+1) + (litLength*6);
102
+
103
+ if (litLength == 0)
104
+ return optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[0]+1);
105
+
106
+ /* literals */
107
+ if (optPtr->cachedLiterals == literals) {
108
+ U32 const additional = litLength - optPtr->cachedLitLength;
109
+ const BYTE* literals2 = optPtr->cachedLiterals + optPtr->cachedLitLength;
110
+ price = optPtr->cachedPrice + additional * optPtr->log2litSum;
111
+ for (u=0; u < additional; u++)
112
+ price -= ZSTD_highbit32(optPtr->litFreq[literals2[u]]+1);
113
+ optPtr->cachedPrice = price;
114
+ optPtr->cachedLitLength = litLength;
115
+ } else {
116
+ price = litLength * optPtr->log2litSum;
117
+ for (u=0; u < litLength; u++)
118
+ price -= ZSTD_highbit32(optPtr->litFreq[literals[u]]+1);
119
+
120
+ if (litLength >= 12) {
121
+ optPtr->cachedLiterals = literals;
122
+ optPtr->cachedPrice = price;
123
+ optPtr->cachedLitLength = litLength;
124
+ }
125
+ }
126
+
127
+ /* literal Length */
128
+ { const BYTE LL_deltaCode = 19;
129
+ const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
130
+ price += LL_bits[llCode] + optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[llCode]+1);
131
+ }
132
+
133
+ return price;
134
+ }
135
+
136
+
137
+ FORCE_INLINE_TEMPLATE U32 ZSTD_getPrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength, const int ultra)
138
+ {
139
+ /* offset */
140
+ U32 price;
141
+ BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
142
+
143
+ if (optPtr->staticPrices)
144
+ return ZSTD_getLiteralPrice(optPtr, litLength, literals) + ZSTD_highbit32((U32)matchLength+1) + 16 + offCode;
145
+
146
+ price = offCode + optPtr->log2offCodeSum - ZSTD_highbit32(optPtr->offCodeFreq[offCode]+1);
147
+ if (!ultra && offCode >= 20) price += (offCode-19)*2;
148
+
149
+ /* match Length */
150
+ { const BYTE ML_deltaCode = 36;
151
+ const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
152
+ price += ML_bits[mlCode] + optPtr->log2matchLengthSum - ZSTD_highbit32(optPtr->matchLengthFreq[mlCode]+1);
153
+ }
154
+
155
+ return price + ZSTD_getLiteralPrice(optPtr, litLength, literals) + optPtr->factor;
156
+ }
157
+
158
+
159
+ static void ZSTD_updatePrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
160
+ {
161
+ U32 u;
162
+
163
+ /* literals */
164
+ optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
165
+ for (u=0; u < litLength; u++)
166
+ optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
167
+
168
+ /* literal Length */
169
+ { const BYTE LL_deltaCode = 19;
170
+ const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
171
+ optPtr->litLengthFreq[llCode]++;
172
+ optPtr->litLengthSum++;
173
+ }
174
+
175
+ /* match offset */
176
+ { BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
177
+ optPtr->offCodeSum++;
178
+ optPtr->offCodeFreq[offCode]++;
179
+ }
180
+
181
+ /* match Length */
182
+ { const BYTE ML_deltaCode = 36;
183
+ const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
184
+ optPtr->matchLengthFreq[mlCode]++;
185
+ optPtr->matchLengthSum++;
186
+ }
187
+
188
+ ZSTD_setLog2Prices(optPtr);
189
+ }
190
+
191
+
192
+ #define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
193
+ { \
194
+ while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; } \
195
+ opt[pos].mlen = mlen_; \
196
+ opt[pos].off = offset_; \
197
+ opt[pos].litlen = litlen_; \
198
+ opt[pos].price = price_; \
199
+ }
200
+
201
+
202
+ /* function safe only for comparisons */
203
+ static U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
204
+ {
205
+ switch (length)
206
+ {
207
+ default :
208
+ case 4 : return MEM_read32(memPtr);
209
+ case 3 : if (MEM_isLittleEndian())
210
+ return MEM_read32(memPtr)<<8;
211
+ else
212
+ return MEM_read32(memPtr)>>8;
213
+ }
214
+ }
215
+
216
+
217
+ /* Update hashTable3 up to ip (excluded)
218
+ Assumption : always within prefix (i.e. not within extDict) */
219
+ static
220
+ U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* zc, const BYTE* ip)
221
+ {
222
+ U32* const hashTable3 = zc->hashTable3;
223
+ U32 const hashLog3 = zc->hashLog3;
224
+ const BYTE* const base = zc->base;
225
+ U32 idx = zc->nextToUpdate3;
226
+ const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
227
+ const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
228
+
229
+ while(idx < target) {
230
+ hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
231
+ idx++;
232
+ }
233
+
234
+ return hashTable3[hash3];
235
+ }
236
+
237
+
238
+ /*-*************************************
239
+ * Binary Tree search
240
+ ***************************************/
241
+ static U32 ZSTD_insertBtAndGetAllMatches (
242
+ ZSTD_CCtx* zc,
243
+ const BYTE* const ip, const BYTE* const iLimit,
244
+ U32 nbCompares, const U32 mls,
245
+ U32 extDict, ZSTD_match_t* matches, const U32 minMatchLen)
246
+ {
247
+ const BYTE* const base = zc->base;
248
+ const U32 current = (U32)(ip-base);
249
+ const U32 hashLog = zc->appliedParams.cParams.hashLog;
250
+ const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
251
+ U32* const hashTable = zc->hashTable;
252
+ U32 matchIndex = hashTable[h];
253
+ U32* const bt = zc->chainTable;
254
+ const U32 btLog = zc->appliedParams.cParams.chainLog - 1;
255
+ const U32 btMask= (1U << btLog) - 1;
256
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
257
+ const BYTE* const dictBase = zc->dictBase;
258
+ const U32 dictLimit = zc->dictLimit;
259
+ const BYTE* const dictEnd = dictBase + dictLimit;
260
+ const BYTE* const prefixStart = base + dictLimit;
261
+ const U32 btLow = btMask >= current ? 0 : current - btMask;
262
+ const U32 windowLow = zc->lowLimit;
263
+ U32* smallerPtr = bt + 2*(current&btMask);
264
+ U32* largerPtr = bt + 2*(current&btMask) + 1;
265
+ U32 matchEndIdx = current+8;
266
+ U32 dummy32; /* to be nullified at the end */
267
+ U32 mnum = 0;
268
+
269
+ const U32 minMatch = (mls == 3) ? 3 : 4;
270
+ size_t bestLength = minMatchLen-1;
271
+
272
+ if (minMatch == 3) { /* HC3 match finder */
273
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
274
+ if (matchIndex3>windowLow && (current - matchIndex3 < (1<<18))) {
275
+ const BYTE* match;
276
+ size_t currentMl=0;
277
+ if ((!extDict) || matchIndex3 >= dictLimit) {
278
+ match = base + matchIndex3;
279
+ if (match[bestLength] == ip[bestLength]) currentMl = ZSTD_count(ip, match, iLimit);
280
+ } else {
281
+ match = dictBase + matchIndex3;
282
+ if (ZSTD_readMINMATCH(match, MINMATCH) == ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
283
+ currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
284
+ }
285
+
286
+ /* save best solution */
287
+ if (currentMl > bestLength) {
288
+ bestLength = currentMl;
289
+ matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex3;
290
+ matches[mnum].len = (U32)currentMl;
291
+ mnum++;
292
+ if (currentMl > ZSTD_OPT_NUM) goto update;
293
+ if (ip+currentMl == iLimit) goto update; /* best possible, and avoid read overflow*/
294
+ }
295
+ }
296
+ }
297
+
298
+ hashTable[h] = current; /* Update Hash Table */
299
+
300
+ while (nbCompares-- && (matchIndex > windowLow)) {
301
+ U32* nextPtr = bt + 2*(matchIndex & btMask);
302
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
303
+ const BYTE* match;
304
+
305
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
306
+ match = base + matchIndex;
307
+ if (match[matchLength] == ip[matchLength]) {
308
+ matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iLimit) +1;
309
+ }
310
+ } else {
311
+ match = dictBase + matchIndex;
312
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
313
+ if (matchIndex+matchLength >= dictLimit)
314
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
315
+ }
316
+
317
+ if (matchLength > bestLength) {
318
+ if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength;
319
+ bestLength = matchLength;
320
+ matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex;
321
+ matches[mnum].len = (U32)matchLength;
322
+ mnum++;
323
+ if (matchLength > ZSTD_OPT_NUM) break;
324
+ if (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */
325
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
326
+ }
327
+
328
+ if (match[matchLength] < ip[matchLength]) {
329
+ /* match is smaller than current */
330
+ *smallerPtr = matchIndex; /* update smaller idx */
331
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
332
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
333
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
334
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
335
+ } else {
336
+ /* match is larger than current */
337
+ *largerPtr = matchIndex;
338
+ commonLengthLarger = matchLength;
339
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
340
+ largerPtr = nextPtr;
341
+ matchIndex = nextPtr[0];
342
+ } }
343
+
344
+ *smallerPtr = *largerPtr = 0;
345
+
346
+ update:
347
+ zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
348
+ return mnum;
349
+ }
350
+
351
+
352
+ /** Tree updater, providing best match */
353
+ static U32 ZSTD_BtGetAllMatches (
354
+ ZSTD_CCtx* zc,
355
+ const BYTE* const ip, const BYTE* const iLimit,
356
+ const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
357
+ {
358
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
359
+ ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
360
+ return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
361
+ }
362
+
363
+
364
+ static U32 ZSTD_BtGetAllMatches_selectMLS (
365
+ ZSTD_CCtx* zc, /* Index table will be updated */
366
+ const BYTE* ip, const BYTE* const iHighLimit,
367
+ const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
368
+ {
369
+ switch(matchLengthSearch)
370
+ {
371
+ case 3 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
372
+ default :
373
+ case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
374
+ case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
375
+ case 7 :
376
+ case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
377
+ }
378
+ }
379
+
380
+ /** Tree updater, providing best match */
381
+ static U32 ZSTD_BtGetAllMatches_extDict (
382
+ ZSTD_CCtx* zc,
383
+ const BYTE* const ip, const BYTE* const iLimit,
384
+ const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
385
+ {
386
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
387
+ ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
388
+ return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
389
+ }
390
+
391
+
392
+ static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
393
+ ZSTD_CCtx* zc, /* Index table will be updated */
394
+ const BYTE* ip, const BYTE* const iHighLimit,
395
+ const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
396
+ {
397
+ switch(matchLengthSearch)
398
+ {
399
+ case 3 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
400
+ default :
401
+ case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
402
+ case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
403
+ case 7 :
404
+ case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
405
+ }
406
+ }
407
+
408
+
409
+ /*-*******************************
410
+ * Optimal parser
411
+ *********************************/
412
+ FORCE_INLINE_TEMPLATE
413
+ size_t ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
414
+ const void* src, size_t srcSize, const int ultra)
415
+ {
416
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
417
+ optState_t* optStatePtr = &(ctx->optState);
418
+ const BYTE* const istart = (const BYTE*)src;
419
+ const BYTE* ip = istart;
420
+ const BYTE* anchor = istart;
421
+ const BYTE* const iend = istart + srcSize;
422
+ const BYTE* const ilimit = iend - 8;
423
+ const BYTE* const base = ctx->base;
424
+ const BYTE* const prefixStart = base + ctx->dictLimit;
425
+
426
+ const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
427
+ const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
428
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
429
+ const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
430
+
431
+ ZSTD_optimal_t* opt = optStatePtr->priceTable;
432
+ ZSTD_match_t* matches = optStatePtr->matchTable;
433
+ const BYTE* inr;
434
+ U32 offset, rep[ZSTD_REP_NUM];
435
+
436
+ /* init */
437
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
438
+ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
439
+ ip += (ip==prefixStart);
440
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
441
+
442
+ /* Match Loop */
443
+ while (ip < ilimit) {
444
+ U32 cur, match_num, last_pos, litlen, price;
445
+ U32 u, mlen, best_mlen, best_off, litLength;
446
+ memset(opt, 0, sizeof(ZSTD_optimal_t));
447
+ last_pos = 0;
448
+ litlen = (U32)(ip - anchor);
449
+
450
+ /* check repCode */
451
+ { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
452
+ for (i=(ip == anchor); i<last_i; i++) {
453
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
454
+ if ( (repCur > 0) && (repCur < (S32)(ip-prefixStart))
455
+ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
456
+ mlen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repCur, iend) + minMatch;
457
+ if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
458
+ best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
459
+ goto _storeSequence;
460
+ }
461
+ best_off = i - (ip == anchor);
462
+ do {
463
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
464
+ if (mlen > last_pos || price < opt[mlen].price)
465
+ SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
466
+ mlen--;
467
+ } while (mlen >= minMatch);
468
+ } } }
469
+
470
+ match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
471
+
472
+ if (!last_pos && !match_num) { ip++; continue; }
473
+
474
+ if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
475
+ best_mlen = matches[match_num-1].len;
476
+ best_off = matches[match_num-1].off;
477
+ cur = 0;
478
+ last_pos = 1;
479
+ goto _storeSequence;
480
+ }
481
+
482
+ /* set prices using matches at position = 0 */
483
+ best_mlen = (last_pos) ? last_pos : minMatch;
484
+ for (u = 0; u < match_num; u++) {
485
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
486
+ best_mlen = matches[u].len;
487
+ while (mlen <= best_mlen) {
488
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
489
+ if (mlen > last_pos || price < opt[mlen].price)
490
+ SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
491
+ mlen++;
492
+ } }
493
+
494
+ if (last_pos < minMatch) { ip++; continue; }
495
+
496
+ /* initialize opt[0] */
497
+ { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
498
+ opt[0].mlen = 1;
499
+ opt[0].litlen = litlen;
500
+
501
+ /* check further positions */
502
+ for (cur = 1; cur <= last_pos; cur++) {
503
+ inr = ip + cur;
504
+
505
+ if (opt[cur-1].mlen == 1) {
506
+ litlen = opt[cur-1].litlen + 1;
507
+ if (cur > litlen) {
508
+ price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
509
+ } else
510
+ price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
511
+ } else {
512
+ litlen = 1;
513
+ price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
514
+ }
515
+
516
+ if (cur > last_pos || price <= opt[cur].price)
517
+ SET_PRICE(cur, 1, 0, litlen, price);
518
+
519
+ if (cur == last_pos) break;
520
+
521
+ if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
522
+ continue;
523
+
524
+ mlen = opt[cur].mlen;
525
+ if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
526
+ opt[cur].rep[2] = opt[cur-mlen].rep[1];
527
+ opt[cur].rep[1] = opt[cur-mlen].rep[0];
528
+ opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
529
+ } else {
530
+ opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
531
+ opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
532
+ /* If opt[cur].off == ZSTD_REP_MOVE_OPT, then mlen != 1.
533
+ * offset ZSTD_REP_MOVE_OPT is used for the special case
534
+ * litLength == 0, where offset 0 means something special.
535
+ * mlen == 1 means the previous byte was stored as a literal,
536
+ * so they are mutually exclusive.
537
+ */
538
+ assert(!(opt[cur].off == ZSTD_REP_MOVE_OPT && mlen == 1));
539
+ opt[cur].rep[0] = (opt[cur].off == ZSTD_REP_MOVE_OPT) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
540
+ }
541
+
542
+ best_mlen = minMatch;
543
+ { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
544
+ for (i=(opt[cur].mlen != 1); i<last_i; i++) { /* check rep */
545
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
546
+ if ( (repCur > 0) && (repCur < (S32)(inr-prefixStart))
547
+ && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
548
+ mlen = (U32)ZSTD_count(inr+minMatch, inr+minMatch - repCur, iend) + minMatch;
549
+
550
+ if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
551
+ best_mlen = mlen; best_off = i; last_pos = cur + 1;
552
+ goto _storeSequence;
553
+ }
554
+
555
+ best_off = i - (opt[cur].mlen != 1);
556
+ if (mlen > best_mlen) best_mlen = mlen;
557
+
558
+ do {
559
+ if (opt[cur].mlen == 1) {
560
+ litlen = opt[cur].litlen;
561
+ if (cur > litlen) {
562
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
563
+ } else
564
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
565
+ } else {
566
+ litlen = 0;
567
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
568
+ }
569
+
570
+ if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
571
+ SET_PRICE(cur + mlen, mlen, i, litlen, price);
572
+ mlen--;
573
+ } while (mlen >= minMatch);
574
+ } } }
575
+
576
+ match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
577
+
578
+ if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
579
+ best_mlen = matches[match_num-1].len;
580
+ best_off = matches[match_num-1].off;
581
+ last_pos = cur + 1;
582
+ goto _storeSequence;
583
+ }
584
+
585
+ /* set prices using matches at position = cur */
586
+ for (u = 0; u < match_num; u++) {
587
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
588
+ best_mlen = matches[u].len;
589
+
590
+ while (mlen <= best_mlen) {
591
+ if (opt[cur].mlen == 1) {
592
+ litlen = opt[cur].litlen;
593
+ if (cur > litlen)
594
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
595
+ else
596
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
597
+ } else {
598
+ litlen = 0;
599
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
600
+ }
601
+
602
+ if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
603
+ SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
604
+
605
+ mlen++;
606
+ } } }
607
+
608
+ best_mlen = opt[last_pos].mlen;
609
+ best_off = opt[last_pos].off;
610
+ cur = last_pos - best_mlen;
611
+
612
+ /* store sequence */
613
+ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
614
+ opt[0].mlen = 1;
615
+
616
+ while (1) {
617
+ mlen = opt[cur].mlen;
618
+ offset = opt[cur].off;
619
+ opt[cur].mlen = best_mlen;
620
+ opt[cur].off = best_off;
621
+ best_mlen = mlen;
622
+ best_off = offset;
623
+ if (mlen > cur) break;
624
+ cur -= mlen;
625
+ }
626
+
627
+ for (u = 0; u <= last_pos;) {
628
+ u += opt[u].mlen;
629
+ }
630
+
631
+ for (cur=0; cur < last_pos; ) {
632
+ mlen = opt[cur].mlen;
633
+ if (mlen == 1) { ip++; cur++; continue; }
634
+ offset = opt[cur].off;
635
+ cur += mlen;
636
+ litLength = (U32)(ip - anchor);
637
+
638
+ if (offset > ZSTD_REP_MOVE_OPT) {
639
+ rep[2] = rep[1];
640
+ rep[1] = rep[0];
641
+ rep[0] = offset - ZSTD_REP_MOVE_OPT;
642
+ offset--;
643
+ } else {
644
+ if (offset != 0) {
645
+ best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
646
+ if (offset != 1) rep[2] = rep[1];
647
+ rep[1] = rep[0];
648
+ rep[0] = best_off;
649
+ }
650
+ if (litLength==0) offset--;
651
+ }
652
+
653
+ ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
654
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
655
+ anchor = ip = ip + mlen;
656
+ } } /* for (cur=0; cur < last_pos; ) */
657
+
658
+ /* Save reps for next block */
659
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
660
+
661
+ /* Return the last literals size */
662
+ return iend - anchor;
663
+ }
664
+
665
+
666
+ size_t ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
667
+ {
668
+ return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0);
669
+ }
670
+
671
+ size_t ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
672
+ {
673
+ return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1);
674
+ }
675
+
676
+
677
+ FORCE_INLINE_TEMPLATE
678
+ size_t ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
679
+ const void* src, size_t srcSize, const int ultra)
680
+ {
681
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
682
+ optState_t* optStatePtr = &(ctx->optState);
683
+ const BYTE* const istart = (const BYTE*)src;
684
+ const BYTE* ip = istart;
685
+ const BYTE* anchor = istart;
686
+ const BYTE* const iend = istart + srcSize;
687
+ const BYTE* const ilimit = iend - 8;
688
+ const BYTE* const base = ctx->base;
689
+ const U32 lowestIndex = ctx->lowLimit;
690
+ const U32 dictLimit = ctx->dictLimit;
691
+ const BYTE* const prefixStart = base + dictLimit;
692
+ const BYTE* const dictBase = ctx->dictBase;
693
+ const BYTE* const dictEnd = dictBase + dictLimit;
694
+
695
+ const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
696
+ const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
697
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
698
+ const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
699
+
700
+ ZSTD_optimal_t* opt = optStatePtr->priceTable;
701
+ ZSTD_match_t* matches = optStatePtr->matchTable;
702
+ const BYTE* inr;
703
+
704
+ /* init */
705
+ U32 offset, rep[ZSTD_REP_NUM];
706
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
707
+
708
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
709
+ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
710
+ ip += (ip==prefixStart);
711
+
712
+ /* Match Loop */
713
+ while (ip < ilimit) {
714
+ U32 cur, match_num, last_pos, litlen, price;
715
+ U32 u, mlen, best_mlen, best_off, litLength;
716
+ U32 current = (U32)(ip-base);
717
+ memset(opt, 0, sizeof(ZSTD_optimal_t));
718
+ last_pos = 0;
719
+ opt[0].litlen = (U32)(ip - anchor);
720
+
721
+ /* check repCode */
722
+ { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
723
+ for (i = (ip==anchor); i<last_i; i++) {
724
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
725
+ const U32 repIndex = (U32)(current - repCur);
726
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
727
+ const BYTE* const repMatch = repBase + repIndex;
728
+ if ( (repCur > 0 && repCur <= (S32)current)
729
+ && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
730
+ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
731
+ /* repcode detected we should take it */
732
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
733
+ mlen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
734
+
735
+ if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
736
+ best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
737
+ goto _storeSequence;
738
+ }
739
+
740
+ best_off = i - (ip==anchor);
741
+ litlen = opt[0].litlen;
742
+ do {
743
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
744
+ if (mlen > last_pos || price < opt[mlen].price)
745
+ SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
746
+ mlen--;
747
+ } while (mlen >= minMatch);
748
+ } } }
749
+
750
+ match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
751
+
752
+ if (!last_pos && !match_num) { ip++; continue; }
753
+
754
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
755
+ opt[0].mlen = 1;
756
+
757
+ if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
758
+ best_mlen = matches[match_num-1].len;
759
+ best_off = matches[match_num-1].off;
760
+ cur = 0;
761
+ last_pos = 1;
762
+ goto _storeSequence;
763
+ }
764
+
765
+ best_mlen = (last_pos) ? last_pos : minMatch;
766
+
767
+ /* set prices using matches at position = 0 */
768
+ for (u = 0; u < match_num; u++) {
769
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
770
+ best_mlen = matches[u].len;
771
+ litlen = opt[0].litlen;
772
+ while (mlen <= best_mlen) {
773
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
774
+ if (mlen > last_pos || price < opt[mlen].price)
775
+ SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
776
+ mlen++;
777
+ } }
778
+
779
+ if (last_pos < minMatch) {
780
+ ip++; continue;
781
+ }
782
+
783
+ /* check further positions */
784
+ for (cur = 1; cur <= last_pos; cur++) {
785
+ inr = ip + cur;
786
+
787
+ if (opt[cur-1].mlen == 1) {
788
+ litlen = opt[cur-1].litlen + 1;
789
+ if (cur > litlen) {
790
+ price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
791
+ } else
792
+ price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
793
+ } else {
794
+ litlen = 1;
795
+ price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
796
+ }
797
+
798
+ if (cur > last_pos || price <= opt[cur].price)
799
+ SET_PRICE(cur, 1, 0, litlen, price);
800
+
801
+ if (cur == last_pos) break;
802
+
803
+ if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
804
+ continue;
805
+
806
+ mlen = opt[cur].mlen;
807
+ if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
808
+ opt[cur].rep[2] = opt[cur-mlen].rep[1];
809
+ opt[cur].rep[1] = opt[cur-mlen].rep[0];
810
+ opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
811
+ } else {
812
+ opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
813
+ opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
814
+ assert(!(opt[cur].off == ZSTD_REP_MOVE_OPT && mlen == 1));
815
+ opt[cur].rep[0] = (opt[cur].off == ZSTD_REP_MOVE_OPT) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
816
+ }
817
+
818
+ best_mlen = minMatch;
819
+ { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
820
+ for (i = (mlen != 1); i<last_i; i++) {
821
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
822
+ const U32 repIndex = (U32)(current+cur - repCur);
823
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
824
+ const BYTE* const repMatch = repBase + repIndex;
825
+ if ( (repCur > 0 && repCur <= (S32)(current+cur))
826
+ && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
827
+ && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
828
+ /* repcode detected */
829
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
830
+ mlen = (U32)ZSTD_count_2segments(inr+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
831
+
832
+ if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
833
+ best_mlen = mlen; best_off = i; last_pos = cur + 1;
834
+ goto _storeSequence;
835
+ }
836
+
837
+ best_off = i - (opt[cur].mlen != 1);
838
+ if (mlen > best_mlen) best_mlen = mlen;
839
+
840
+ do {
841
+ if (opt[cur].mlen == 1) {
842
+ litlen = opt[cur].litlen;
843
+ if (cur > litlen) {
844
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
845
+ } else
846
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
847
+ } else {
848
+ litlen = 0;
849
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
850
+ }
851
+
852
+ if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
853
+ SET_PRICE(cur + mlen, mlen, i, litlen, price);
854
+ mlen--;
855
+ } while (mlen >= minMatch);
856
+ } } }
857
+
858
+ match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
859
+
860
+ if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
861
+ best_mlen = matches[match_num-1].len;
862
+ best_off = matches[match_num-1].off;
863
+ last_pos = cur + 1;
864
+ goto _storeSequence;
865
+ }
866
+
867
+ /* set prices using matches at position = cur */
868
+ for (u = 0; u < match_num; u++) {
869
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
870
+ best_mlen = matches[u].len;
871
+
872
+ while (mlen <= best_mlen) {
873
+ if (opt[cur].mlen == 1) {
874
+ litlen = opt[cur].litlen;
875
+ if (cur > litlen)
876
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
877
+ else
878
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
879
+ } else {
880
+ litlen = 0;
881
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
882
+ }
883
+
884
+ if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
885
+ SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
886
+
887
+ mlen++;
888
+ } } } /* for (cur = 1; cur <= last_pos; cur++) */
889
+
890
+ best_mlen = opt[last_pos].mlen;
891
+ best_off = opt[last_pos].off;
892
+ cur = last_pos - best_mlen;
893
+
894
+ /* store sequence */
895
+ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
896
+ opt[0].mlen = 1;
897
+
898
+ while (1) {
899
+ mlen = opt[cur].mlen;
900
+ offset = opt[cur].off;
901
+ opt[cur].mlen = best_mlen;
902
+ opt[cur].off = best_off;
903
+ best_mlen = mlen;
904
+ best_off = offset;
905
+ if (mlen > cur) break;
906
+ cur -= mlen;
907
+ }
908
+
909
+ for (u = 0; u <= last_pos; ) {
910
+ u += opt[u].mlen;
911
+ }
912
+
913
+ for (cur=0; cur < last_pos; ) {
914
+ mlen = opt[cur].mlen;
915
+ if (mlen == 1) { ip++; cur++; continue; }
916
+ offset = opt[cur].off;
917
+ cur += mlen;
918
+ litLength = (U32)(ip - anchor);
919
+
920
+ if (offset > ZSTD_REP_MOVE_OPT) {
921
+ rep[2] = rep[1];
922
+ rep[1] = rep[0];
923
+ rep[0] = offset - ZSTD_REP_MOVE_OPT;
924
+ offset--;
925
+ } else {
926
+ if (offset != 0) {
927
+ best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
928
+ if (offset != 1) rep[2] = rep[1];
929
+ rep[1] = rep[0];
930
+ rep[0] = best_off;
931
+ }
932
+
933
+ if (litLength==0) offset--;
934
+ }
935
+
936
+ ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
937
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
938
+ anchor = ip = ip + mlen;
939
+ } } /* for (cur=0; cur < last_pos; ) */
940
+
941
+ /* Save reps for next block */
942
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
943
+
944
+ /* Return the last literals size */
945
+ return iend - anchor;
946
+ }
947
+
948
+
949
+ size_t ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
950
+ {
951
+ return ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0);
952
+ }
953
+
954
+ size_t ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
955
+ {
956
+ return ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1);
957
+ }