extzstd 0.0.2.CONCEPT-x86-mingw32 → 0.0.3.CONCEPT-x86-mingw32

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +72 -22
  3. data/Rakefile +73 -19
  4. data/contrib/zstd/README.md +68 -0
  5. data/contrib/zstd/common/bitstream.h +414 -0
  6. data/contrib/zstd/common/entropy_common.c +231 -0
  7. data/contrib/zstd/common/error_private.h +125 -0
  8. data/contrib/zstd/common/error_public.h +77 -0
  9. data/contrib/zstd/common/fse.h +628 -0
  10. data/contrib/zstd/common/fse_decompress.c +331 -0
  11. data/contrib/zstd/common/huf.h +228 -0
  12. data/contrib/zstd/common/mem.h +377 -0
  13. data/contrib/zstd/common/xxhash.c +854 -0
  14. data/contrib/zstd/common/xxhash.h +273 -0
  15. data/contrib/zstd/common/zbuff.h +197 -0
  16. data/contrib/zstd/common/zstd.h +475 -0
  17. data/contrib/zstd/common/zstd_common.c +91 -0
  18. data/contrib/zstd/common/zstd_internal.h +238 -0
  19. data/contrib/zstd/compress/fse_compress.c +807 -0
  20. data/contrib/zstd/compress/huf_compress.c +577 -0
  21. data/contrib/zstd/compress/zbuff_compress.c +327 -0
  22. data/contrib/zstd/compress/zstd_compress.c +3074 -0
  23. data/contrib/zstd/compress/zstd_opt.h +1046 -0
  24. data/contrib/zstd/decompress/huf_decompress.c +894 -0
  25. data/contrib/zstd/decompress/zbuff_decompress.c +294 -0
  26. data/contrib/zstd/decompress/zstd_decompress.c +1362 -0
  27. data/contrib/zstd/dictBuilder/divsufsort.c +1913 -0
  28. data/contrib/zstd/dictBuilder/divsufsort.h +67 -0
  29. data/contrib/zstd/dictBuilder/zdict.c +1045 -0
  30. data/contrib/zstd/dictBuilder/zdict.h +113 -0
  31. data/contrib/zstd/legacy/zstd_legacy.h +140 -0
  32. data/contrib/zstd/legacy/zstd_v01.c +2178 -0
  33. data/contrib/zstd/{zstd.h → legacy/zstd_v01.h} +46 -39
  34. data/contrib/zstd/legacy/zstd_v02.c +3748 -0
  35. data/contrib/zstd/legacy/zstd_v02.h +99 -0
  36. data/contrib/zstd/legacy/zstd_v03.c +3389 -0
  37. data/contrib/zstd/legacy/zstd_v03.h +99 -0
  38. data/contrib/zstd/legacy/zstd_v04.c +4056 -0
  39. data/contrib/zstd/legacy/zstd_v04.h +148 -0
  40. data/contrib/zstd/legacy/zstd_v05.c +4325 -0
  41. data/contrib/zstd/legacy/zstd_v05.h +171 -0
  42. data/contrib/zstd/legacy/zstd_v06.c +4581 -0
  43. data/contrib/zstd/legacy/zstd_v06.h +185 -0
  44. data/ext/extconf.rb +10 -12
  45. data/ext/extzstd.c +497 -144
  46. data/ext/extzstd.h +127 -22
  47. data/ext/extzstd_buffered.c +265 -0
  48. data/ext/extzstd_nogvls.h +174 -0
  49. data/ext/zstd_amalgam.c +18 -0
  50. data/ext/zstd_legacy_v01.c +1 -0
  51. data/ext/zstd_legacy_v02.c +1 -0
  52. data/ext/zstd_legacy_v03.c +1 -0
  53. data/ext/zstd_legacy_v04.c +1 -0
  54. data/ext/zstd_legacy_v05.c +1 -0
  55. data/ext/zstd_legacy_v06.c +1 -0
  56. data/gemstub.rb +17 -1
  57. data/lib/2.0/extzstd.so +0 -0
  58. data/lib/2.1/extzstd.so +0 -0
  59. data/lib/2.2/extzstd.so +0 -0
  60. data/lib/2.3/extzstd.so +0 -0
  61. data/lib/extzstd.rb +197 -77
  62. data/lib/extzstd/version.rb +1 -1
  63. data/test/test_basic.rb +41 -0
  64. metadata +71 -20
  65. data/contrib/zstd/Makefile +0 -115
  66. data/contrib/zstd/fse.c +0 -2466
  67. data/contrib/zstd/fse.h +0 -320
  68. data/contrib/zstd/fse_static.h +0 -282
  69. data/contrib/zstd/libzstd.pc.in +0 -14
  70. data/contrib/zstd/zstd.c +0 -1768
  71. data/contrib/zstd/zstd_static.h +0 -89
  72. data/ext/extzstd-stream.c +0 -398
@@ -0,0 +1,327 @@
1
+ /*
2
+ Buffered version of Zstd compression library
3
+ Copyright (C) 2015-2016, Yann Collet.
4
+
5
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are
9
+ met:
10
+ * Redistributions of source code must retain the above copyright
11
+ notice, this list of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above
13
+ copyright notice, this list of conditions and the following disclaimer
14
+ in the documentation and/or other materials provided with the
15
+ distribution.
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ You can contact the author at :
29
+ - zstd homepage : http://www.zstd.net/
30
+ */
31
+
32
+
33
+ /* *************************************
34
+ * Dependencies
35
+ ***************************************/
36
+ #include <stdlib.h>
37
+ #include "error_private.h"
38
+ #include "zstd_internal.h" /* MIN, ZSTD_BLOCKHEADERSIZE, defaultCustomMem */
39
+ #define ZBUFF_STATIC_LINKING_ONLY
40
+ #include "zbuff.h"
41
+
42
+
43
+ /* *************************************
44
+ * Constants
45
+ ***************************************/
46
+ static size_t const ZBUFF_endFrameSize = ZSTD_BLOCKHEADERSIZE;
47
+
48
+
49
+ /*_**************************************************
50
+ * Streaming compression
51
+ *
52
+ * A ZBUFF_CCtx object is required to track streaming operation.
53
+ * Use ZBUFF_createCCtx() and ZBUFF_freeCCtx() to create/release resources.
54
+ * Use ZBUFF_compressInit() to start a new compression operation.
55
+ * ZBUFF_CCtx objects can be reused multiple times.
56
+ *
57
+ * Use ZBUFF_compressContinue() repetitively to consume your input.
58
+ * *srcSizePtr and *dstCapacityPtr can be any size.
59
+ * The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.
60
+ * Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.
61
+ * The content of dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters or change dst .
62
+ * @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)
63
+ * or an error code, which can be tested using ZBUFF_isError().
64
+ *
65
+ * ZBUFF_compressFlush() can be used to instruct ZBUFF to compress and output whatever remains within its buffer.
66
+ * Note that it will not output more than *dstCapacityPtr.
67
+ * Therefore, some content might still be left into its internal buffer if dst buffer is too small.
68
+ * @return : nb of bytes still present into internal buffer (0 if it's empty)
69
+ * or an error code, which can be tested using ZBUFF_isError().
70
+ *
71
+ * ZBUFF_compressEnd() instructs to finish a frame.
72
+ * It will perform a flush and write frame epilogue.
73
+ * Similar to ZBUFF_compressFlush(), it may not be able to output the entire internal buffer content if *dstCapacityPtr is too small.
74
+ * @return : nb of bytes still present into internal buffer (0 if it's empty)
75
+ * or an error code, which can be tested using ZBUFF_isError().
76
+ *
77
+ * Hint : recommended buffer sizes (not compulsory)
78
+ * input : ZSTD_BLOCKSIZE_MAX (128 KB), internal unit size, it improves latency to use this value.
79
+ * output : ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize : ensures it's always possible to write/flush/end a full block at best speed.
80
+ * **************************************************/
81
+
82
+ typedef enum { ZBUFFcs_init, ZBUFFcs_load, ZBUFFcs_flush, ZBUFFcs_final } ZBUFF_cStage;
83
+
84
+ /* *** Resources *** */
85
+ struct ZBUFF_CCtx_s {
86
+ ZSTD_CCtx* zc;
87
+ char* inBuff;
88
+ size_t inBuffSize;
89
+ size_t inToCompress;
90
+ size_t inBuffPos;
91
+ size_t inBuffTarget;
92
+ size_t blockSize;
93
+ char* outBuff;
94
+ size_t outBuffSize;
95
+ size_t outBuffContentSize;
96
+ size_t outBuffFlushedSize;
97
+ ZBUFF_cStage stage;
98
+ ZSTD_customMem customMem;
99
+ }; /* typedef'd tp ZBUFF_CCtx within "zstd_buffered.h" */
100
+
101
+ ZBUFF_CCtx* ZBUFF_createCCtx(void)
102
+ {
103
+ return ZBUFF_createCCtx_advanced(defaultCustomMem);
104
+ }
105
+
106
+ ZBUFF_CCtx* ZBUFF_createCCtx_advanced(ZSTD_customMem customMem)
107
+ {
108
+ ZBUFF_CCtx* zbc;
109
+
110
+ if (!customMem.customAlloc && !customMem.customFree)
111
+ customMem = defaultCustomMem;
112
+
113
+ if (!customMem.customAlloc || !customMem.customFree)
114
+ return NULL;
115
+
116
+ zbc = (ZBUFF_CCtx*)customMem.customAlloc(customMem.opaque, sizeof(ZBUFF_CCtx));
117
+ if (zbc==NULL) return NULL;
118
+ memset(zbc, 0, sizeof(ZBUFF_CCtx));
119
+ memcpy(&zbc->customMem, &customMem, sizeof(ZSTD_customMem));
120
+ zbc->zc = ZSTD_createCCtx_advanced(customMem);
121
+ if (zbc->zc == NULL) { ZBUFF_freeCCtx(zbc); return NULL; }
122
+ return zbc;
123
+ }
124
+
125
+ size_t ZBUFF_freeCCtx(ZBUFF_CCtx* zbc)
126
+ {
127
+ if (zbc==NULL) return 0; /* support free on NULL */
128
+ ZSTD_freeCCtx(zbc->zc);
129
+ if (zbc->inBuff) zbc->customMem.customFree(zbc->customMem.opaque, zbc->inBuff);
130
+ if (zbc->outBuff) zbc->customMem.customFree(zbc->customMem.opaque, zbc->outBuff);
131
+ zbc->customMem.customFree(zbc->customMem.opaque, zbc);
132
+ return 0;
133
+ }
134
+
135
+
136
+ /* *** Initialization *** */
137
+
138
+ size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc,
139
+ const void* dict, size_t dictSize,
140
+ ZSTD_parameters params, unsigned long long pledgedSrcSize)
141
+ {
142
+ /* allocate buffers */
143
+ { size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog;
144
+ if (zbc->inBuffSize < neededInBuffSize) {
145
+ zbc->inBuffSize = neededInBuffSize;
146
+ zbc->customMem.customFree(zbc->customMem.opaque, zbc->inBuff); /* should not be necessary */
147
+ zbc->inBuff = (char*)zbc->customMem.customAlloc(zbc->customMem.opaque, neededInBuffSize);
148
+ if (zbc->inBuff == NULL) return ERROR(memory_allocation);
149
+ }
150
+ zbc->blockSize = MIN(ZSTD_BLOCKSIZE_MAX, neededInBuffSize);
151
+ }
152
+ if (zbc->outBuffSize < ZSTD_compressBound(zbc->blockSize)+1) {
153
+ zbc->outBuffSize = ZSTD_compressBound(zbc->blockSize)+1;
154
+ zbc->customMem.customFree(zbc->customMem.opaque, zbc->outBuff); /* should not be necessary */
155
+ zbc->outBuff = (char*)zbc->customMem.customAlloc(zbc->customMem.opaque, zbc->outBuffSize);
156
+ if (zbc->outBuff == NULL) return ERROR(memory_allocation);
157
+ }
158
+
159
+ { size_t const errorCode = ZSTD_compressBegin_advanced(zbc->zc, dict, dictSize, params, pledgedSrcSize);
160
+ if (ZSTD_isError(errorCode)) return errorCode; }
161
+
162
+ zbc->inToCompress = 0;
163
+ zbc->inBuffPos = 0;
164
+ zbc->inBuffTarget = zbc->blockSize;
165
+ zbc->outBuffContentSize = zbc->outBuffFlushedSize = 0;
166
+ zbc->stage = ZBUFFcs_load;
167
+ return 0; /* ready to go */
168
+ }
169
+
170
+
171
+ size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, int compressionLevel)
172
+ {
173
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
174
+ return ZBUFF_compressInit_advanced(zbc, dict, dictSize, params, 0);
175
+ }
176
+
177
+ size_t ZBUFF_compressInit(ZBUFF_CCtx* zbc, int compressionLevel)
178
+ {
179
+ return ZBUFF_compressInitDictionary(zbc, NULL, 0, compressionLevel);
180
+ }
181
+
182
+
183
+ /* internal util function */
184
+ MEM_STATIC size_t ZBUFF_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
185
+ {
186
+ size_t const length = MIN(dstCapacity, srcSize);
187
+ memcpy(dst, src, length);
188
+ return length;
189
+ }
190
+
191
+
192
+ /* *** Compression *** */
193
+
194
+ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
195
+ void* dst, size_t* dstCapacityPtr,
196
+ const void* src, size_t* srcSizePtr,
197
+ int flush)
198
+ {
199
+ U32 notDone = 1;
200
+ const char* const istart = (const char*)src;
201
+ const char* const iend = istart + *srcSizePtr;
202
+ const char* ip = istart;
203
+ char* const ostart = (char*)dst;
204
+ char* const oend = ostart + *dstCapacityPtr;
205
+ char* op = ostart;
206
+
207
+ while (notDone) {
208
+ switch(zbc->stage)
209
+ {
210
+ case ZBUFFcs_init: return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */
211
+
212
+ case ZBUFFcs_load:
213
+ /* complete inBuffer */
214
+ { size_t const toLoad = zbc->inBuffTarget - zbc->inBuffPos;
215
+ size_t const loaded = ZBUFF_limitCopy(zbc->inBuff + zbc->inBuffPos, toLoad, ip, iend-ip);
216
+ zbc->inBuffPos += loaded;
217
+ ip += loaded;
218
+ if ( (zbc->inBuffPos==zbc->inToCompress) || (!flush && (toLoad != loaded)) ) {
219
+ notDone = 0; break; /* not enough input to get a full block : stop there, wait for more */
220
+ } }
221
+ /* compress current block (note : this stage cannot be stopped in the middle) */
222
+ { void* cDst;
223
+ size_t cSize;
224
+ size_t const iSize = zbc->inBuffPos - zbc->inToCompress;
225
+ size_t oSize = oend-op;
226
+ if (oSize >= ZSTD_compressBound(iSize))
227
+ cDst = op; /* compress directly into output buffer (avoid flush stage) */
228
+ else
229
+ cDst = zbc->outBuff, oSize = zbc->outBuffSize;
230
+ cSize = ZSTD_compressContinue(zbc->zc, cDst, oSize, zbc->inBuff + zbc->inToCompress, iSize);
231
+ if (ZSTD_isError(cSize)) return cSize;
232
+ /* prepare next block */
233
+ zbc->inBuffTarget = zbc->inBuffPos + zbc->blockSize;
234
+ if (zbc->inBuffTarget > zbc->inBuffSize)
235
+ zbc->inBuffPos = 0, zbc->inBuffTarget = zbc->blockSize; /* note : inBuffSize >= blockSize */
236
+ zbc->inToCompress = zbc->inBuffPos;
237
+ if (cDst == op) { op += cSize; break; } /* no need to flush */
238
+ zbc->outBuffContentSize = cSize;
239
+ zbc->outBuffFlushedSize = 0;
240
+ zbc->stage = ZBUFFcs_flush; /* continue to flush stage */
241
+ }
242
+
243
+ case ZBUFFcs_flush:
244
+ { size_t const toFlush = zbc->outBuffContentSize - zbc->outBuffFlushedSize;
245
+ size_t const flushed = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outBuffFlushedSize, toFlush);
246
+ op += flushed;
247
+ zbc->outBuffFlushedSize += flushed;
248
+ if (toFlush!=flushed) { notDone = 0; break; } /* dst too small to store flushed data : stop there */
249
+ zbc->outBuffContentSize = zbc->outBuffFlushedSize = 0;
250
+ zbc->stage = ZBUFFcs_load;
251
+ break;
252
+ }
253
+
254
+ case ZBUFFcs_final:
255
+ notDone = 0; /* do nothing */
256
+ break;
257
+
258
+ default:
259
+ return ERROR(GENERIC); /* impossible */
260
+ }
261
+ }
262
+
263
+ *srcSizePtr = ip - istart;
264
+ *dstCapacityPtr = op - ostart;
265
+ { size_t hintInSize = zbc->inBuffTarget - zbc->inBuffPos;
266
+ if (hintInSize==0) hintInSize = zbc->blockSize;
267
+ return hintInSize;
268
+ }
269
+ }
270
+
271
+ size_t ZBUFF_compressContinue(ZBUFF_CCtx* zbc,
272
+ void* dst, size_t* dstCapacityPtr,
273
+ const void* src, size_t* srcSizePtr)
274
+ {
275
+ return ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, src, srcSizePtr, 0);
276
+ }
277
+
278
+
279
+
280
+ /* *** Finalize *** */
281
+
282
+ size_t ZBUFF_compressFlush(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)
283
+ {
284
+ size_t srcSize = 0;
285
+ ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, &srcSize, &srcSize, 1); /* use a valid src address instead of NULL */
286
+ return zbc->outBuffContentSize - zbc->outBuffFlushedSize;
287
+ }
288
+
289
+
290
+ size_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)
291
+ {
292
+ BYTE* const ostart = (BYTE*)dst;
293
+ BYTE* const oend = ostart + *dstCapacityPtr;
294
+ BYTE* op = ostart;
295
+
296
+ if (zbc->stage != ZBUFFcs_final) {
297
+ /* flush whatever remains */
298
+ size_t outSize = *dstCapacityPtr;
299
+ size_t const remainingToFlush = ZBUFF_compressFlush(zbc, dst, &outSize);
300
+ op += outSize;
301
+ if (remainingToFlush) {
302
+ *dstCapacityPtr = op-ostart;
303
+ return remainingToFlush + ZBUFF_endFrameSize;
304
+ }
305
+ /* create epilogue */
306
+ zbc->stage = ZBUFFcs_final;
307
+ zbc->outBuffContentSize = ZSTD_compressEnd(zbc->zc, zbc->outBuff, zbc->outBuffSize); /* epilogue into outBuff */
308
+ }
309
+
310
+ /* flush epilogue */
311
+ { size_t const toFlush = zbc->outBuffContentSize - zbc->outBuffFlushedSize;
312
+ size_t const flushed = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outBuffFlushedSize, toFlush);
313
+ op += flushed;
314
+ zbc->outBuffFlushedSize += flushed;
315
+ *dstCapacityPtr = op-ostart;
316
+ if (toFlush==flushed) zbc->stage = ZBUFFcs_init; /* end reached */
317
+ return toFlush - flushed;
318
+ }
319
+ }
320
+
321
+
322
+
323
+ /* *************************************
324
+ * Tool functions
325
+ ***************************************/
326
+ size_t ZBUFF_recommendedCInSize(void) { return ZSTD_BLOCKSIZE_MAX; }
327
+ size_t ZBUFF_recommendedCOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize; }
@@ -0,0 +1,3074 @@
1
+ /*
2
+ ZSTD HC - High Compression Mode of Zstandard
3
+ Copyright (C) 2015-2016, Yann Collet.
4
+
5
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are
9
+ met:
10
+
11
+ * Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+ * Redistributions in binary form must reproduce the above
14
+ copyright notice, this list of conditions and the following disclaimer
15
+ in the documentation and/or other materials provided with the
16
+ distribution.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ You can contact the author at :
31
+ - Zstd source repository : https://www.zstd.net
32
+ */
33
+
34
+
35
+ /* *******************************************************
36
+ * Compiler specifics
37
+ *********************************************************/
38
+ #ifdef _MSC_VER /* Visual Studio */
39
+ # define FORCE_INLINE static __forceinline
40
+ # include <intrin.h> /* For Visual 2005 */
41
+ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
42
+ #else
43
+ # ifdef __GNUC__
44
+ # define FORCE_INLINE static inline __attribute__((always_inline))
45
+ # else
46
+ # define FORCE_INLINE static inline
47
+ # endif
48
+ #endif
49
+
50
+
51
+ /*-*************************************
52
+ * Dependencies
53
+ ***************************************/
54
+ #include <string.h> /* memset */
55
+ #include "mem.h"
56
+ #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
57
+ #include "xxhash.h" /* XXH_reset, update, digest */
58
+ #define FSE_STATIC_LINKING_ONLY
59
+ #include "fse.h"
60
+ #define HUF_STATIC_LINKING_ONLY
61
+ #include "huf.h"
62
+ #include "zstd_internal.h" /* includes zstd.h */
63
+
64
+
65
+ /*-*************************************
66
+ * Constants
67
+ ***************************************/
68
+ static const U32 g_searchStrength = 8; /* control skip over incompressible data */
69
+
70
+
71
+ /*-*************************************
72
+ * Helper functions
73
+ ***************************************/
74
+ size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; }
75
+
76
+ static U32 ZSTD_highbit32(U32 val)
77
+ {
78
+ # if defined(_MSC_VER) /* Visual */
79
+ unsigned long r=0;
80
+ _BitScanReverse(&r, val);
81
+ return (unsigned)r;
82
+ # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
83
+ return 31 - __builtin_clz(val);
84
+ # else /* Software version */
85
+ static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
86
+ U32 v = val;
87
+ int r;
88
+ v |= v >> 1;
89
+ v |= v >> 2;
90
+ v |= v >> 4;
91
+ v |= v >> 8;
92
+ v |= v >> 16;
93
+ r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
94
+ return r;
95
+ # endif
96
+ }
97
+
98
+ /*-*************************************
99
+ * Sequence storage
100
+ ***************************************/
101
+ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
102
+ {
103
+ ssPtr->offset = ssPtr->offsetStart;
104
+ ssPtr->lit = ssPtr->litStart;
105
+ ssPtr->litLength = ssPtr->litLengthStart;
106
+ ssPtr->matchLength = ssPtr->matchLengthStart;
107
+ ssPtr->longLengthID = 0;
108
+ }
109
+
110
+
111
+ /*-*************************************
112
+ * Context memory management
113
+ ***************************************/
114
+ struct ZSTD_CCtx_s
115
+ {
116
+ const BYTE* nextSrc; /* next block here to continue on current prefix */
117
+ const BYTE* base; /* All regular indexes relative to this position */
118
+ const BYTE* dictBase; /* extDict indexes relative to this position */
119
+ U32 dictLimit; /* below that point, need extDict */
120
+ U32 lowLimit; /* below that point, no more data */
121
+ U32 nextToUpdate; /* index from which to continue dictionary update */
122
+ U32 nextToUpdate3; /* index from which to continue dictionary update */
123
+ U32 hashLog3; /* dispatch table : larger == faster, more memory */
124
+ U32 loadedDictEnd;
125
+ U32 stage; /* 0: created; 1: init,dictLoad; 2:started */
126
+ U32 rep[ZSTD_REP_NUM];
127
+ U32 savedRep[ZSTD_REP_NUM];
128
+ U32 dictID;
129
+ ZSTD_parameters params;
130
+ void* workSpace;
131
+ size_t workSpaceSize;
132
+ size_t blockSize;
133
+ U64 frameContentSize;
134
+ XXH64_state_t xxhState;
135
+ ZSTD_customMem customMem;
136
+
137
+ seqStore_t seqStore; /* sequences storage ptrs */
138
+ U32* hashTable;
139
+ U32* hashTable3;
140
+ U32* chainTable;
141
+ HUF_CElt* hufTable;
142
+ U32 flagStaticTables;
143
+ FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
144
+ FSE_CTable matchlengthCTable [FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
145
+ FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
146
+ };
147
+
148
+ ZSTD_CCtx* ZSTD_createCCtx(void)
149
+ {
150
+ return ZSTD_createCCtx_advanced(defaultCustomMem);
151
+ }
152
+
153
+ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
154
+ {
155
+ ZSTD_CCtx* cctx;
156
+
157
+ if (!customMem.customAlloc && !customMem.customFree)
158
+ customMem = defaultCustomMem;
159
+
160
+ if (!customMem.customAlloc || !customMem.customFree)
161
+ return NULL;
162
+
163
+ cctx = (ZSTD_CCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTD_CCtx));
164
+ if (!cctx) return NULL;
165
+ memset(cctx, 0, sizeof(ZSTD_CCtx));
166
+ memcpy(&(cctx->customMem), &customMem, sizeof(ZSTD_customMem));
167
+ return cctx;
168
+ }
169
+
170
+ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
171
+ {
172
+ if (cctx==NULL) return 0; /* support free on NULL */
173
+ if (cctx->workSpace) cctx->customMem.customFree(cctx->customMem.opaque, cctx->workSpace);
174
+ cctx->customMem.customFree(cctx->customMem.opaque, cctx);
175
+ return 0; /* reserved as a potential error code in the future */
176
+ }
177
+
178
+ size_t ZSTD_sizeofCCtx(const ZSTD_CCtx* cctx)
179
+ {
180
+ return sizeof(*cctx) + cctx->workSpaceSize;
181
+ }
182
+
183
+ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
184
+ {
185
+ return &(ctx->seqStore);
186
+ }
187
+
188
+
189
+ #define CLAMP(val,min,max) { if (val<min) val=min; else if (val>max) val=max; }
190
+ #define CLAMPCHECK(val,min,max) { if ((val<min) || (val>max)) return ERROR(compressionParameter_unsupported); }
191
+
192
+ /** ZSTD_checkParams() :
193
+ ensure param values remain within authorized range.
194
+ @return : 0, or an error code if one value is beyond authorized range */
195
+ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
196
+ {
197
+ CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
198
+ CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
199
+ CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
200
+ CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
201
+ { U32 const searchLengthMin = (cParams.strategy == ZSTD_fast || cParams.strategy == ZSTD_greedy) ? ZSTD_SEARCHLENGTH_MIN+1 : ZSTD_SEARCHLENGTH_MIN;
202
+ U32 const searchLengthMax = (cParams.strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX-1;
203
+ CLAMPCHECK(cParams.searchLength, searchLengthMin, searchLengthMax); }
204
+ CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
205
+ if ((U32)(cParams.strategy) > (U32)ZSTD_btopt) return ERROR(compressionParameter_unsupported);
206
+ return 0;
207
+ }
208
+
209
+
210
+ /** ZSTD_checkCParams_advanced() :
211
+ temporary work-around, while the compressor compatibility remains limited regarding windowLog < 18 */
212
+ size_t ZSTD_checkCParams_advanced(ZSTD_compressionParameters cParams, U64 srcSize)
213
+ {
214
+ if (srcSize > (1ULL << ZSTD_WINDOWLOG_MIN)) return ZSTD_checkCParams(cParams);
215
+ if (cParams.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) return ERROR(compressionParameter_unsupported);
216
+ if (srcSize <= (1ULL << cParams.windowLog)) cParams.windowLog = ZSTD_WINDOWLOG_MIN; /* fake value - temporary work around */
217
+ if (srcSize <= (1ULL << cParams.chainLog)) cParams.chainLog = ZSTD_CHAINLOG_MIN; /* fake value - temporary work around */
218
+ if ((srcSize <= (1ULL << cParams.hashLog)) && ((U32)cParams.strategy < (U32)ZSTD_btlazy2)) cParams.hashLog = ZSTD_HASHLOG_MIN; /* fake value - temporary work around */
219
+ return ZSTD_checkCParams(cParams);
220
+ }
221
+
222
+
223
+ /** ZSTD_adjustCParams() :
224
+ optimize cPar for a given input (`srcSize` and `dictSize`).
225
+ mostly downsizing to reduce memory consumption and initialization.
226
+ Both `srcSize` and `dictSize` are optional (use 0 if unknown),
227
+ but if both are 0, no optimization can be done.
228
+ Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
229
+ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
230
+ {
231
+ if (srcSize+dictSize == 0) return cPar; /* no size information available : no adjustment */
232
+
233
+ /* resize params, to use less memory when necessary */
234
+ { U32 const minSrcSize = (srcSize==0) ? 500 : 0;
235
+ U64 const rSize = srcSize + dictSize + minSrcSize;
236
+ if (rSize < ((U64)1<<ZSTD_WINDOWLOG_MAX)) {
237
+ U32 const srcLog = ZSTD_highbit32((U32)(rSize)-1) + 1;
238
+ if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
239
+ } }
240
+ if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog;
241
+ { U32 const btPlus = (cPar.strategy == ZSTD_btlazy2) || (cPar.strategy == ZSTD_btopt);
242
+ U32 const maxChainLog = cPar.windowLog+btPlus;
243
+ if (cPar.chainLog > maxChainLog) cPar.chainLog = maxChainLog; } /* <= ZSTD_CHAINLOG_MAX */
244
+
245
+ if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
246
+ if ((cPar.hashLog < ZSTD_HASHLOG_MIN) && ( (U32)cPar.strategy >= (U32)ZSTD_btlazy2)) cPar.hashLog = ZSTD_HASHLOG_MIN; /* required to ensure collision resistance in bt */
247
+
248
+ return cPar;
249
+ }
250
+
251
+
252
+ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
253
+ {
254
+ const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
255
+ const U32 divider = (cParams.searchLength==3) ? 3 : 4;
256
+ const size_t maxNbSeq = blockSize / divider;
257
+ const size_t tokenSpace = blockSize + 11*maxNbSeq;
258
+
259
+ const size_t chainSize = (cParams.strategy == ZSTD_fast) ? 0 : (1 << cParams.chainLog);
260
+ const size_t hSize = ((size_t)1) << cParams.hashLog;
261
+ const U32 hashLog3 = (cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
262
+ const size_t h3Size = ((size_t)1) << hashLog3;
263
+ const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
264
+
265
+ size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
266
+ + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
267
+ size_t const neededSpace = tableSpace + (256*sizeof(U32)) /* huffTable */ + tokenSpace
268
+ + ((cParams.strategy == ZSTD_btopt) ? optSpace : 0);
269
+
270
+ return sizeof(ZSTD_CCtx) + neededSpace;
271
+ }
272
+
273
+ /*! ZSTD_resetCCtx_advanced() :
274
+ note : 'params' is expected to be validated */
275
+ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
276
+ ZSTD_parameters params, U64 frameContentSize,
277
+ U32 reset)
278
+ { /* note : params considered validated here */
279
+ const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
280
+ const U32 divider = (params.cParams.searchLength==3) ? 3 : 4;
281
+ const size_t maxNbSeq = blockSize / divider;
282
+ const size_t tokenSpace = blockSize + 11*maxNbSeq;
283
+ const size_t chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog);
284
+ const size_t hSize = ((size_t)1) << params.cParams.hashLog;
285
+ const U32 hashLog3 = (params.cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
286
+ const size_t h3Size = ((size_t)1) << hashLog3;
287
+ const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
288
+
289
+ /* Check if workSpace is large enough, alloc a new one if needed */
290
+ { size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
291
+ + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
292
+ size_t const neededSpace = tableSpace + (256*sizeof(U32)) /* huffTable */ + tokenSpace
293
+ + ((params.cParams.strategy == ZSTD_btopt) ? optSpace : 0);
294
+ if (zc->workSpaceSize < neededSpace) {
295
+ zc->customMem.customFree(zc->customMem.opaque, zc->workSpace);
296
+ zc->workSpace = zc->customMem.customAlloc(zc->customMem.opaque, neededSpace);
297
+ if (zc->workSpace == NULL) return ERROR(memory_allocation);
298
+ zc->workSpaceSize = neededSpace;
299
+ } }
300
+
301
+ if (reset) memset(zc->workSpace, 0, tableSpace ); /* reset only tables */
302
+ XXH64_reset(&zc->xxhState, 0);
303
+ zc->hashLog3 = hashLog3;
304
+ zc->hashTable = (U32*)(zc->workSpace);
305
+ zc->chainTable = zc->hashTable + hSize;
306
+ zc->hashTable3 = zc->chainTable + chainSize;
307
+ zc->seqStore.buffer = zc->hashTable3 + h3Size;
308
+ zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
309
+ zc->flagStaticTables = 0;
310
+ zc->seqStore.buffer = ((U32*)(zc->seqStore.buffer)) + 256; /* note : HUF_CElt* is incomplete type, size is simulated using U32 */
311
+
312
+ zc->nextToUpdate = 1;
313
+ zc->nextSrc = NULL;
314
+ zc->base = NULL;
315
+ zc->dictBase = NULL;
316
+ zc->dictLimit = 0;
317
+ zc->lowLimit = 0;
318
+ zc->params = params;
319
+ zc->blockSize = blockSize;
320
+ zc->frameContentSize = frameContentSize;
321
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = repStartValue[i]; }
322
+
323
+ if (params.cParams.strategy == ZSTD_btopt) {
324
+ zc->seqStore.litFreq = (U32*)(zc->seqStore.buffer);
325
+ zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<<Litbits);
326
+ zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
327
+ zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML+1);
328
+ zc->seqStore.buffer = zc->seqStore.offCodeFreq + (MaxOff+1);
329
+ zc->seqStore.matchTable = (ZSTD_match_t*)zc->seqStore.buffer;
330
+ zc->seqStore.buffer = zc->seqStore.matchTable + ZSTD_OPT_NUM+1;
331
+ zc->seqStore.priceTable = (ZSTD_optimal_t*)zc->seqStore.buffer;
332
+ zc->seqStore.buffer = zc->seqStore.priceTable + ZSTD_OPT_NUM+1;
333
+ zc->seqStore.litLengthSum = 0;
334
+ }
335
+ zc->seqStore.offsetStart = (U32*)(zc->seqStore.buffer);
336
+ zc->seqStore.buffer = zc->seqStore.offsetStart + maxNbSeq;
337
+ zc->seqStore.litLengthStart = (U16*)zc->seqStore.buffer;
338
+ zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + maxNbSeq;
339
+ zc->seqStore.llCodeStart = (BYTE*) (zc->seqStore.matchLengthStart + maxNbSeq);
340
+ zc->seqStore.mlCodeStart = zc->seqStore.llCodeStart + maxNbSeq;
341
+ zc->seqStore.offCodeStart = zc->seqStore.mlCodeStart + maxNbSeq;
342
+ zc->seqStore.litStart = zc->seqStore.offCodeStart + maxNbSeq;
343
+
344
+ zc->stage = 1;
345
+ zc->dictID = 0;
346
+ zc->loadedDictEnd = 0;
347
+
348
+ return 0;
349
+ }
350
+
351
+
352
+ /*! ZSTD_copyCCtx() :
353
+ * Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
354
+ * Only works during stage 1 (i.e. after creation, but before first call to ZSTD_compressContinue()).
355
+ * @return : 0, or an error code */
356
+ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
357
+ {
358
+ if (srcCCtx->stage!=1) return ERROR(stage_wrong);
359
+
360
+ memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
361
+ ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params, srcCCtx->frameContentSize, 0);
362
+ dstCCtx->params.fParams.contentSizeFlag = 0; /* content size different from the one set during srcCCtx init */
363
+
364
+ /* copy tables */
365
+ { const size_t chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog);
366
+ const size_t hSize = ((size_t)1) << srcCCtx->params.cParams.hashLog;
367
+ const size_t h3Size = (size_t)1 << srcCCtx->hashLog3;
368
+ const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
369
+ memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace);
370
+ }
371
+
372
+ /* copy dictionary offsets */
373
+ dstCCtx->nextToUpdate = srcCCtx->nextToUpdate;
374
+ dstCCtx->nextToUpdate3= srcCCtx->nextToUpdate3;
375
+ dstCCtx->nextSrc = srcCCtx->nextSrc;
376
+ dstCCtx->base = srcCCtx->base;
377
+ dstCCtx->dictBase = srcCCtx->dictBase;
378
+ dstCCtx->dictLimit = srcCCtx->dictLimit;
379
+ dstCCtx->lowLimit = srcCCtx->lowLimit;
380
+ dstCCtx->loadedDictEnd= srcCCtx->loadedDictEnd;
381
+ dstCCtx->dictID = srcCCtx->dictID;
382
+
383
+ /* copy entropy tables */
384
+ dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
385
+ if (srcCCtx->flagStaticTables) {
386
+ memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4);
387
+ memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable));
388
+ memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable));
389
+ memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable));
390
+ }
391
+
392
+ return 0;
393
+ }
394
+
395
+
396
+ /*! ZSTD_reduceTable() :
397
+ * reduce table indexes by `reducerValue` */
398
+ static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
399
+ {
400
+ U32 u;
401
+ for (u=0 ; u < size ; u++) {
402
+ if (table[u] < reducerValue) table[u] = 0;
403
+ else table[u] -= reducerValue;
404
+ }
405
+ }
406
+
407
+ /*! ZSTD_reduceIndex() :
408
+ * rescale all indexes to avoid future overflow (indexes are U32) */
409
+ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
410
+ {
411
+ { const U32 hSize = 1 << zc->params.cParams.hashLog;
412
+ ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
413
+
414
+ { const U32 chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog);
415
+ ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
416
+
417
+ { const U32 h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
418
+ ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
419
+ }
420
+
421
+
422
+ /*-*******************************************************
423
+ * Block entropic compression
424
+ *********************************************************/
425
+
426
+ /* Frame format description
427
+ Frame Header - [ Block Header - Block ] - Frame End
428
+ 1) Frame Header
429
+ - 4 bytes : Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h)
430
+ - 1 byte : Frame Header Descriptor
431
+ - 1-13 bytes : Optional fields
432
+ 2) Block Header
433
+ - 3 bytes, starting with a 2-bits descriptor
434
+ Uncompressed, Compressed, Frame End, unused
435
+ 3) Block
436
+ See Block Format Description
437
+ 4) Frame End
438
+ - 3 bytes, compatible with Block Header
439
+ */
440
+
441
+
442
+ /* Frame header :
443
+
444
+ 1 byte - FrameHeaderDescription :
445
+ bit 0-1 : dictID (0, 1, 2 or 4 bytes)
446
+ bit 2-4 : reserved (must be zero)
447
+ bit 5 : SkippedWindowLog (if 1, WindowLog byte is not present)
448
+ bit 6-7 : FrameContentFieldsize (0, 2, 4, or 8)
449
+ if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1;
450
+
451
+ Optional : WindowLog (0 or 1 byte)
452
+ bit 0-2 : octal Fractional (1/8th)
453
+ bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB)
454
+
455
+ Optional : content size (0, 1, 2, 4 or 8 bytes)
456
+ 0 : unknown
457
+ 1 : 0-255 bytes
458
+ 2 : 256 - 65535+256
459
+ 8 : up to 16 exa
460
+
461
+ Optional : dictID (0, 1, 2 or 4 bytes)
462
+ Automatic adaptation
463
+ 0 : no dictID
464
+ 1 : 1 - 255
465
+ 2 : 256 - 65535
466
+ 4 : all other values
467
+ */
468
+
469
+
470
+ /* Block format description
471
+
472
+ Block = Literals Section - Sequences Section
473
+ Prerequisite : size of (compressed) block, maximum size of regenerated data
474
+
475
+ 1) Literal Section
476
+
477
+ 1.1) Header : 1-5 bytes
478
+ flags: 2 bits
479
+ 00 compressed by Huff0
480
+ 01 repeat
481
+ 10 is Raw (uncompressed)
482
+ 11 is Rle
483
+ Note : using 01 => Huff0 with precomputed table ?
484
+ Note : delta map ? => compressed ?
485
+
486
+ 1.1.1) Huff0-compressed literal block : 3-5 bytes
487
+ srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
488
+ srcSize < 1 KB => 3 bytes (2-2-10-10)
489
+ srcSize < 16KB => 4 bytes (2-2-14-14)
490
+ else => 5 bytes (2-2-18-18)
491
+ big endian convention
492
+
493
+ 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
494
+ size : 5 bits: (IS_RAW<<6) + (0<<4) + size
495
+ 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
496
+ size&255
497
+ 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
498
+ size>>8&255
499
+ size&255
500
+
501
+ 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
502
+ size : 5 bits: (IS_RLE<<6) + (0<<4) + size
503
+ 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
504
+ size&255
505
+ 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
506
+ size>>8&255
507
+ size&255
508
+
509
+ 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
510
+ srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
511
+ srcSize < 1 KB => 3 bytes (2-2-10-10)
512
+ srcSize < 16KB => 4 bytes (2-2-14-14)
513
+ else => 5 bytes (2-2-18-18)
514
+ big endian convention
515
+
516
+ 1- CTable available (stored into workspace)
517
+ 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
518
+
519
+
520
+ 1.2) Literal block content
521
+
522
+ 1.2.1) Huff0 block, using sizes from header
523
+ See Huff0 format
524
+
525
+ 1.2.2) Huff0 block, using prepared table
526
+
527
+ 1.2.3) Raw content
528
+
529
+ 1.2.4) single byte
530
+
531
+
532
+ 2) Sequences section
533
+
534
+ - Nb Sequences : 2 bytes, little endian
535
+ - Control Token : 1 byte (see below)
536
+ - Dumps Length : 1 or 2 bytes (depending on control token)
537
+ - Dumps : as stated by dumps length
538
+ - Literal Lengths FSE table (as needed depending on encoding method)
539
+ - Offset Codes FSE table (as needed depending on encoding method)
540
+ - Match Lengths FSE table (as needed depending on encoding method)
541
+
542
+ 2.1) Control Token
543
+ 8 bits, divided as :
544
+ 0-1 : dumpsLength
545
+ 2-3 : MatchLength, FSE encoding method
546
+ 4-5 : Offset Codes, FSE encoding method
547
+ 6-7 : Literal Lengths, FSE encoding method
548
+
549
+ FSE encoding method :
550
+ FSE_ENCODING_RAW : uncompressed; no header
551
+ FSE_ENCODING_RLE : single repeated value; header 1 byte
552
+ FSE_ENCODING_STATIC : use prepared table; no header
553
+ FSE_ENCODING_DYNAMIC : read NCount
554
+ */
555
+
556
+ size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
557
+ {
558
+ BYTE* const ostart = (BYTE* const)dst;
559
+
560
+ if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
561
+ memcpy(ostart + ZSTD_blockHeaderSize, src, srcSize);
562
+
563
+ /* Build header */
564
+ ostart[0] = (BYTE)(srcSize>>16);
565
+ ostart[1] = (BYTE)(srcSize>>8);
566
+ ostart[2] = (BYTE) srcSize;
567
+ ostart[0] += (BYTE)(bt_raw<<6); /* is a raw (uncompressed) block */
568
+
569
+ return ZSTD_blockHeaderSize+srcSize;
570
+ }
571
+
572
+
573
+ static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
574
+ {
575
+ BYTE* const ostart = (BYTE* const)dst;
576
+ U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
577
+
578
+ if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
579
+
580
+ switch(flSize)
581
+ {
582
+ case 1: /* 2 - 1 - 5 */
583
+ ostart[0] = (BYTE)((lbt_raw<<6) + (0<<5) + srcSize);
584
+ break;
585
+ case 2: /* 2 - 2 - 12 */
586
+ ostart[0] = (BYTE)((lbt_raw<<6) + (2<<4) + (srcSize >> 8));
587
+ ostart[1] = (BYTE)srcSize;
588
+ break;
589
+ default: /*note : should not be necessary : flSize is within {1,2,3} */
590
+ case 3: /* 2 - 2 - 20 */
591
+ ostart[0] = (BYTE)((lbt_raw<<6) + (3<<4) + (srcSize >> 16));
592
+ ostart[1] = (BYTE)(srcSize>>8);
593
+ ostart[2] = (BYTE)srcSize;
594
+ break;
595
+ }
596
+
597
+ memcpy(ostart + flSize, src, srcSize);
598
+ return srcSize + flSize;
599
+ }
600
+
601
+ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
602
+ {
603
+ BYTE* const ostart = (BYTE* const)dst;
604
+ U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
605
+
606
+ (void)dstCapacity; /* dstCapacity guaranteed to be >=4, hence large enough */
607
+
608
+ switch(flSize)
609
+ {
610
+ case 1: /* 2 - 1 - 5 */
611
+ ostart[0] = (BYTE)((lbt_rle<<6) + (0<<5) + srcSize);
612
+ break;
613
+ case 2: /* 2 - 2 - 12 */
614
+ ostart[0] = (BYTE)((lbt_rle<<6) + (2<<4) + (srcSize >> 8));
615
+ ostart[1] = (BYTE)srcSize;
616
+ break;
617
+ default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */
618
+ case 3: /* 2 - 2 - 20 */
619
+ ostart[0] = (BYTE)((lbt_rle<<6) + (3<<4) + (srcSize >> 16));
620
+ ostart[1] = (BYTE)(srcSize>>8);
621
+ ostart[2] = (BYTE)srcSize;
622
+ break;
623
+ }
624
+
625
+ ostart[flSize] = *(const BYTE*)src;
626
+ return flSize+1;
627
+ }
628
+
629
+
630
+ static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
631
+
632
+ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
633
+ void* dst, size_t dstCapacity,
634
+ const void* src, size_t srcSize)
635
+ {
636
+ size_t const minGain = ZSTD_minGain(srcSize);
637
+ size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
638
+ BYTE* const ostart = (BYTE*)dst;
639
+ U32 singleStream = srcSize < 256;
640
+ litBlockType_t hType = lbt_huffman;
641
+ size_t cLitSize;
642
+
643
+
644
+ /* small ? don't even attempt compression (speed opt) */
645
+ # define LITERAL_NOENTROPY 63
646
+ { size_t const minLitSize = zc->flagStaticTables ? 6 : LITERAL_NOENTROPY;
647
+ if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
648
+ }
649
+
650
+ if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
651
+ if (zc->flagStaticTables && (lhSize==3)) {
652
+ hType = lbt_repeat;
653
+ singleStream = 1;
654
+ cLitSize = HUF_compress1X_usingCTable(ostart+lhSize, dstCapacity-lhSize, src, srcSize, zc->hufTable);
655
+ } else {
656
+ cLitSize = singleStream ? HUF_compress1X(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11)
657
+ : HUF_compress2 (ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11);
658
+ }
659
+
660
+ if ((cLitSize==0) | (cLitSize >= srcSize - minGain))
661
+ return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
662
+ if (cLitSize==1)
663
+ return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
664
+
665
+ /* Build header */
666
+ switch(lhSize)
667
+ {
668
+ case 3: /* 2 - 2 - 10 - 10 */
669
+ ostart[0] = (BYTE)((srcSize>>6) + (singleStream << 4) + (hType<<6));
670
+ ostart[1] = (BYTE)((srcSize<<2) + (cLitSize>>8));
671
+ ostart[2] = (BYTE)(cLitSize);
672
+ break;
673
+ case 4: /* 2 - 2 - 14 - 14 */
674
+ ostart[0] = (BYTE)((srcSize>>10) + (2<<4) + (hType<<6));
675
+ ostart[1] = (BYTE)(srcSize>> 2);
676
+ ostart[2] = (BYTE)((srcSize<<6) + (cLitSize>>8));
677
+ ostart[3] = (BYTE)(cLitSize);
678
+ break;
679
+ default: /* should not be necessary, lhSize is only {3,4,5} */
680
+ case 5: /* 2 - 2 - 18 - 18 */
681
+ ostart[0] = (BYTE)((srcSize>>14) + (3<<4) + (hType<<6));
682
+ ostart[1] = (BYTE)(srcSize>>6);
683
+ ostart[2] = (BYTE)((srcSize<<2) + (cLitSize>>16));
684
+ ostart[3] = (BYTE)(cLitSize>>8);
685
+ ostart[4] = (BYTE)(cLitSize);
686
+ break;
687
+ }
688
+ return lhSize+cLitSize;
689
+ }
690
+
691
+
692
+ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq)
693
+ {
694
+ /* LL codes */
695
+ { static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
696
+ 8, 9, 10, 11, 12, 13, 14, 15,
697
+ 16, 16, 17, 17, 18, 18, 19, 19,
698
+ 20, 20, 20, 20, 21, 21, 21, 21,
699
+ 22, 22, 22, 22, 22, 22, 22, 22,
700
+ 23, 23, 23, 23, 23, 23, 23, 23,
701
+ 24, 24, 24, 24, 24, 24, 24, 24,
702
+ 24, 24, 24, 24, 24, 24, 24, 24 };
703
+ const BYTE LL_deltaCode = 19;
704
+ const U16* const llTable = seqStorePtr->litLengthStart;
705
+ BYTE* const llCodeTable = seqStorePtr->llCodeStart;
706
+ size_t u;
707
+ for (u=0; u<nbSeq; u++) {
708
+ U32 const ll = llTable[u];
709
+ llCodeTable[u] = (ll>63) ? (BYTE)ZSTD_highbit32(ll) + LL_deltaCode : LL_Code[ll];
710
+ }
711
+ if (seqStorePtr->longLengthID==1)
712
+ llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
713
+ }
714
+
715
+ /* Offset codes */
716
+ { const U32* const offsetTable = seqStorePtr->offsetStart;
717
+ BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
718
+ size_t u;
719
+ for (u=0; u<nbSeq; u++) ofCodeTable[u] = (BYTE)ZSTD_highbit32(offsetTable[u]);
720
+ }
721
+
722
+ /* ML codes */
723
+ { static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
724
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
725
+ 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
726
+ 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
727
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
728
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
729
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
730
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
731
+ const BYTE ML_deltaCode = 36;
732
+ const U16* const mlTable = seqStorePtr->matchLengthStart;
733
+ BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
734
+ size_t u;
735
+ for (u=0; u<nbSeq; u++) {
736
+ U32 const ml = mlTable[u];
737
+ mlCodeTable[u] = (ml>127) ? (BYTE)ZSTD_highbit32(ml) + ML_deltaCode : ML_Code[ml];
738
+ }
739
+ if (seqStorePtr->longLengthID==2)
740
+ mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
741
+ }
742
+ }
743
+
744
+
745
+ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
746
+ void* dst, size_t dstCapacity,
747
+ size_t srcSize)
748
+ {
749
+ const seqStore_t* seqStorePtr = &(zc->seqStore);
750
+ U32 count[MaxSeq+1];
751
+ S16 norm[MaxSeq+1];
752
+ FSE_CTable* CTable_LitLength = zc->litlengthCTable;
753
+ FSE_CTable* CTable_OffsetBits = zc->offcodeCTable;
754
+ FSE_CTable* CTable_MatchLength = zc->matchlengthCTable;
755
+ U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
756
+ U16* const llTable = seqStorePtr->litLengthStart;
757
+ U16* const mlTable = seqStorePtr->matchLengthStart;
758
+ const U32* const offsetTable = seqStorePtr->offsetStart;
759
+ const U32* const offsetTableEnd = seqStorePtr->offset;
760
+ BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
761
+ BYTE* const llCodeTable = seqStorePtr->llCodeStart;
762
+ BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
763
+ BYTE* const ostart = (BYTE*)dst;
764
+ BYTE* const oend = ostart + dstCapacity;
765
+ BYTE* op = ostart;
766
+ size_t const nbSeq = offsetTableEnd - offsetTable;
767
+ BYTE* seqHead;
768
+
769
+ /* Compress literals */
770
+ { const BYTE* const literals = seqStorePtr->litStart;
771
+ size_t const litSize = seqStorePtr->lit - literals;
772
+ size_t const cSize = ZSTD_compressLiterals(zc, op, dstCapacity, literals, litSize);
773
+ if (ZSTD_isError(cSize)) return cSize;
774
+ op += cSize;
775
+ }
776
+
777
+ /* Sequences Header */
778
+ if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
779
+ if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
780
+ else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
781
+ else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
782
+ if (nbSeq==0) goto _check_compressibility;
783
+
784
+ /* seqHead : flags for FSE encoding type */
785
+ seqHead = op++;
786
+
787
+ #define MIN_SEQ_FOR_DYNAMIC_FSE 64
788
+ #define MAX_SEQ_FOR_STATIC_FSE 1000
789
+
790
+ /* convert length/distances into codes */
791
+ ZSTD_seqToCodes(seqStorePtr, nbSeq);
792
+
793
+ /* CTable for Literal Lengths */
794
+ { U32 max = MaxLL;
795
+ size_t const mostFrequent = FSE_countFast(count, &max, llCodeTable, nbSeq);
796
+ if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
797
+ *op++ = llCodeTable[0];
798
+ FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
799
+ LLtype = FSE_ENCODING_RLE;
800
+ } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
801
+ LLtype = FSE_ENCODING_STATIC;
802
+ } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog-1)))) {
803
+ FSE_buildCTable(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog);
804
+ LLtype = FSE_ENCODING_RAW;
805
+ } else {
806
+ size_t nbSeq_1 = nbSeq;
807
+ const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
808
+ if (count[llCodeTable[nbSeq-1]]>1) { count[llCodeTable[nbSeq-1]]--; nbSeq_1--; }
809
+ FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
810
+ { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
811
+ if (FSE_isError(NCountSize)) return ERROR(GENERIC);
812
+ op += NCountSize; }
813
+ FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
814
+ LLtype = FSE_ENCODING_DYNAMIC;
815
+ } }
816
+
817
+ /* CTable for Offsets */
818
+ { U32 max = MaxOff;
819
+ size_t const mostFrequent = FSE_countFast(count, &max, ofCodeTable, nbSeq);
820
+ if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
821
+ *op++ = ofCodeTable[0];
822
+ FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
823
+ Offtype = FSE_ENCODING_RLE;
824
+ } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
825
+ Offtype = FSE_ENCODING_STATIC;
826
+ } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (OF_defaultNormLog-1)))) {
827
+ FSE_buildCTable(CTable_OffsetBits, OF_defaultNorm, MaxOff, OF_defaultNormLog);
828
+ Offtype = FSE_ENCODING_RAW;
829
+ } else {
830
+ size_t nbSeq_1 = nbSeq;
831
+ const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
832
+ if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }
833
+ FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
834
+ { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
835
+ if (FSE_isError(NCountSize)) return ERROR(GENERIC);
836
+ op += NCountSize; }
837
+ FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
838
+ Offtype = FSE_ENCODING_DYNAMIC;
839
+ } }
840
+
841
+ /* CTable for MatchLengths */
842
+ { U32 max = MaxML;
843
+ size_t const mostFrequent = FSE_countFast(count, &max, mlCodeTable, nbSeq);
844
+ if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
845
+ *op++ = *mlCodeTable;
846
+ FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
847
+ MLtype = FSE_ENCODING_RLE;
848
+ } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
849
+ MLtype = FSE_ENCODING_STATIC;
850
+ } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog-1)))) {
851
+ FSE_buildCTable(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog);
852
+ MLtype = FSE_ENCODING_RAW;
853
+ } else {
854
+ size_t nbSeq_1 = nbSeq;
855
+ const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
856
+ if (count[mlCodeTable[nbSeq-1]]>1) { count[mlCodeTable[nbSeq-1]]--; nbSeq_1--; }
857
+ FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
858
+ { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
859
+ if (FSE_isError(NCountSize)) return ERROR(GENERIC);
860
+ op += NCountSize; }
861
+ FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
862
+ MLtype = FSE_ENCODING_DYNAMIC;
863
+ } }
864
+
865
+ *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
866
+ zc->flagStaticTables = 0;
867
+
868
+ /* Encoding Sequences */
869
+ { BIT_CStream_t blockStream;
870
+ FSE_CState_t stateMatchLength;
871
+ FSE_CState_t stateOffsetBits;
872
+ FSE_CState_t stateLitLength;
873
+
874
+ { size_t const errorCode = BIT_initCStream(&blockStream, op, oend-op);
875
+ if (ERR_isError(errorCode)) return ERROR(dstSize_tooSmall); } /* not enough space remaining */
876
+
877
+ /* first symbols */
878
+ FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
879
+ FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
880
+ FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
881
+ BIT_addBits(&blockStream, llTable[nbSeq-1], LL_bits[llCodeTable[nbSeq-1]]);
882
+ if (MEM_32bits()) BIT_flushBits(&blockStream);
883
+ BIT_addBits(&blockStream, mlTable[nbSeq-1], ML_bits[mlCodeTable[nbSeq-1]]);
884
+ if (MEM_32bits()) BIT_flushBits(&blockStream);
885
+ BIT_addBits(&blockStream, offsetTable[nbSeq-1], ofCodeTable[nbSeq-1]);
886
+ BIT_flushBits(&blockStream);
887
+
888
+ { size_t n;
889
+ for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
890
+ const BYTE ofCode = ofCodeTable[n];
891
+ const BYTE mlCode = mlCodeTable[n];
892
+ const BYTE llCode = llCodeTable[n];
893
+ const U32 llBits = LL_bits[llCode];
894
+ const U32 mlBits = ML_bits[mlCode];
895
+ const U32 ofBits = ofCode; /* 32b*/ /* 64b*/
896
+ /* (7)*/ /* (7)*/
897
+ FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
898
+ FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
899
+ if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
900
+ FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
901
+ if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
902
+ BIT_flushBits(&blockStream); /* (7)*/
903
+ BIT_addBits(&blockStream, llTable[n], llBits);
904
+ if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
905
+ BIT_addBits(&blockStream, mlTable[n], mlBits);
906
+ if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
907
+ BIT_addBits(&blockStream, offsetTable[n], ofBits); /* 31 */
908
+ BIT_flushBits(&blockStream); /* (7)*/
909
+ } }
910
+
911
+ FSE_flushCState(&blockStream, &stateMatchLength);
912
+ FSE_flushCState(&blockStream, &stateOffsetBits);
913
+ FSE_flushCState(&blockStream, &stateLitLength);
914
+
915
+ { size_t const streamSize = BIT_closeCStream(&blockStream);
916
+ if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
917
+ op += streamSize;
918
+ } }
919
+
920
+ /* check compressibility */
921
+ _check_compressibility:
922
+ { size_t const minGain = ZSTD_minGain(srcSize);
923
+ size_t const maxCSize = srcSize - minGain;
924
+ if ((size_t)(op-ostart) >= maxCSize) return 0; }
925
+
926
+ /* confirm repcodes */
927
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = zc->savedRep[i]; }
928
+
929
+ return op - ostart;
930
+ }
931
+
932
+
933
+ /*! ZSTD_storeSeq() :
934
+ Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
935
+ `offsetCode` : distance to match, or 0 == repCode.
936
+ `matchCode` : matchLength - MINMATCH
937
+ */
938
+ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
939
+ {
940
+ #if 0 /* for debug */
941
+ static const BYTE* g_start = NULL;
942
+ const U32 pos = (U32)(literals - g_start);
943
+ if (g_start==NULL) g_start = literals;
944
+ //if ((pos > 1) && (pos < 50000))
945
+ printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
946
+ pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
947
+ #endif
948
+ ZSTD_statsUpdatePrices(&seqStorePtr->stats, litLength, (const BYTE*)literals, offsetCode, matchCode); /* debug only */
949
+
950
+ /* copy Literals */
951
+ ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
952
+ seqStorePtr->lit += litLength;
953
+
954
+ /* literal Length */
955
+ if (litLength>0xFFFF) { seqStorePtr->longLengthID = 1; seqStorePtr->longLengthPos = (U32)(seqStorePtr->litLength - seqStorePtr->litLengthStart); }
956
+ *seqStorePtr->litLength++ = (U16)litLength;
957
+
958
+ /* match offset */
959
+ *(seqStorePtr->offset++) = offsetCode + 1;
960
+
961
+ /* match Length */
962
+ if (matchCode>0xFFFF) { seqStorePtr->longLengthID = 2; seqStorePtr->longLengthPos = (U32)(seqStorePtr->matchLength - seqStorePtr->matchLengthStart); }
963
+ *seqStorePtr->matchLength++ = (U16)matchCode;
964
+ }
965
+
966
+
967
+ /*-*************************************
968
+ * Match length counter
969
+ ***************************************/
970
+ static unsigned ZSTD_NbCommonBytes (register size_t val)
971
+ {
972
+ if (MEM_isLittleEndian()) {
973
+ if (MEM_64bits()) {
974
+ # if defined(_MSC_VER) && defined(_WIN64)
975
+ unsigned long r = 0;
976
+ _BitScanForward64( &r, (U64)val );
977
+ return (unsigned)(r>>3);
978
+ # elif defined(__GNUC__) && (__GNUC__ >= 3)
979
+ return (__builtin_ctzll((U64)val) >> 3);
980
+ # else
981
+ static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
982
+ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
983
+ # endif
984
+ } else { /* 32 bits */
985
+ # if defined(_MSC_VER)
986
+ unsigned long r=0;
987
+ _BitScanForward( &r, (U32)val );
988
+ return (unsigned)(r>>3);
989
+ # elif defined(__GNUC__) && (__GNUC__ >= 3)
990
+ return (__builtin_ctz((U32)val) >> 3);
991
+ # else
992
+ static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
993
+ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
994
+ # endif
995
+ }
996
+ } else { /* Big Endian CPU */
997
+ if (MEM_64bits()) {
998
+ # if defined(_MSC_VER) && defined(_WIN64)
999
+ unsigned long r = 0;
1000
+ _BitScanReverse64( &r, val );
1001
+ return (unsigned)(r>>3);
1002
+ # elif defined(__GNUC__) && (__GNUC__ >= 3)
1003
+ return (__builtin_clzll(val) >> 3);
1004
+ # else
1005
+ unsigned r;
1006
+ const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
1007
+ if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
1008
+ if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
1009
+ r += (!val);
1010
+ return r;
1011
+ # endif
1012
+ } else { /* 32 bits */
1013
+ # if defined(_MSC_VER)
1014
+ unsigned long r = 0;
1015
+ _BitScanReverse( &r, (unsigned long)val );
1016
+ return (unsigned)(r>>3);
1017
+ # elif defined(__GNUC__) && (__GNUC__ >= 3)
1018
+ return (__builtin_clz((U32)val) >> 3);
1019
+ # else
1020
+ unsigned r;
1021
+ if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
1022
+ r += (!val);
1023
+ return r;
1024
+ # endif
1025
+ } }
1026
+ }
1027
+
1028
+
1029
+ static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
1030
+ {
1031
+ const BYTE* const pStart = pIn;
1032
+ const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);
1033
+
1034
+ while (pIn < pInLoopLimit) {
1035
+ size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
1036
+ if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
1037
+ pIn += ZSTD_NbCommonBytes(diff);
1038
+ return (size_t)(pIn - pStart);
1039
+ }
1040
+ if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
1041
+ if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
1042
+ if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
1043
+ return (size_t)(pIn - pStart);
1044
+ }
1045
+
1046
+ /** ZSTD_count_2segments() :
1047
+ * can count match length with `ip` & `match` in 2 different segments.
1048
+ * convention : on reaching mEnd, match count continue starting from iStart
1049
+ */
1050
+ static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
1051
+ {
1052
+ const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
1053
+ size_t matchLength = ZSTD_count(ip, match, vEnd);
1054
+ if (match + matchLength == mEnd)
1055
+ matchLength += ZSTD_count(ip+matchLength, iStart, iEnd);
1056
+ return matchLength;
1057
+ }
1058
+
1059
+
1060
+ /*-*************************************
1061
+ * Hashes
1062
+ ***************************************/
1063
+ static const U32 prime3bytes = 506832829U;
1064
+ static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
1065
+ MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
1066
+
1067
+ static const U32 prime4bytes = 2654435761U;
1068
+ static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
1069
+ static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
1070
+
1071
+ static const U64 prime5bytes = 889523592379ULL;
1072
+ static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
1073
+ static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
1074
+
1075
+ static const U64 prime6bytes = 227718039650203ULL;
1076
+ static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
1077
+ static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
1078
+
1079
+ static const U64 prime7bytes = 58295818150454627ULL;
1080
+ static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
1081
+ static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
1082
+
1083
+ //static const U64 prime8bytes = 58295818150454627ULL;
1084
+ static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
1085
+ static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
1086
+ static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
1087
+
1088
+ static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
1089
+ {
1090
+ switch(mls)
1091
+ {
1092
+ default:
1093
+ case 4: return ZSTD_hash4Ptr(p, hBits);
1094
+ case 5: return ZSTD_hash5Ptr(p, hBits);
1095
+ case 6: return ZSTD_hash6Ptr(p, hBits);
1096
+ case 7: return ZSTD_hash7Ptr(p, hBits);
1097
+ case 8: return ZSTD_hash8Ptr(p, hBits);
1098
+ }
1099
+ }
1100
+
1101
+
1102
+ /*-*************************************
1103
+ * Fast Scan
1104
+ ***************************************/
1105
+ static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
1106
+ {
1107
+ U32* const hashTable = zc->hashTable;
1108
+ const U32 hBits = zc->params.cParams.hashLog;
1109
+ const BYTE* const base = zc->base;
1110
+ const BYTE* ip = base + zc->nextToUpdate;
1111
+ const BYTE* const iend = ((const BYTE*)end) - 8;
1112
+ const size_t fastHashFillStep = 3;
1113
+
1114
+ while(ip <= iend) {
1115
+ hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
1116
+ ip += fastHashFillStep;
1117
+ }
1118
+ }
1119
+
1120
+
1121
+ FORCE_INLINE
1122
+ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
1123
+ const void* src, size_t srcSize,
1124
+ const U32 mls)
1125
+ {
1126
+ U32* const hashTable = cctx->hashTable;
1127
+ const U32 hBits = cctx->params.cParams.hashLog;
1128
+ seqStore_t* seqStorePtr = &(cctx->seqStore);
1129
+ const BYTE* const base = cctx->base;
1130
+ const BYTE* const istart = (const BYTE*)src;
1131
+ const BYTE* ip = istart;
1132
+ const BYTE* anchor = istart;
1133
+ const U32 lowestIndex = cctx->dictLimit;
1134
+ const BYTE* const lowest = base + lowestIndex;
1135
+ const BYTE* const iend = istart + srcSize;
1136
+ const BYTE* const ilimit = iend - 8;
1137
+ U32 offset_1=cctx->rep[0], offset_2=cctx->rep[1];
1138
+ U32 offsetSaved = 0;
1139
+
1140
+ /* init */
1141
+ ip += (ip==lowest);
1142
+ { U32 const maxRep = (U32)(ip-lowest);
1143
+ if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
1144
+ if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
1145
+ }
1146
+
1147
+ /* Main Search Loop */
1148
+ while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
1149
+ size_t mLength;
1150
+ size_t const h = ZSTD_hashPtr(ip, hBits, mls);
1151
+ U32 const current = (U32)(ip-base);
1152
+ U32 const matchIndex = hashTable[h];
1153
+ const BYTE* match = base + matchIndex;
1154
+ hashTable[h] = current; /* update hash table */
1155
+
1156
+ if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) { /* note : by construction, offset_1 <= current */
1157
+ mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
1158
+ ip++;
1159
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1160
+ } else {
1161
+ U32 offset;
1162
+ if ( (matchIndex <= lowestIndex) || (MEM_read32(match) != MEM_read32(ip)) ) {
1163
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
1164
+ continue;
1165
+ }
1166
+ mLength = ZSTD_count(ip+4, match+4, iend) + 4;
1167
+ offset = (U32)(ip-match);
1168
+ while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1169
+ offset_2 = offset_1;
1170
+ offset_1 = offset;
1171
+
1172
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1173
+ }
1174
+
1175
+ /* match found */
1176
+ ip += mLength;
1177
+ anchor = ip;
1178
+
1179
+ if (ip <= ilimit) {
1180
+ /* Fill Table */
1181
+ hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
1182
+ hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1183
+ /* check immediate repcode */
1184
+ while ( (ip <= ilimit)
1185
+ && ( (offset_2>0)
1186
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
1187
+ /* store sequence */
1188
+ size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
1189
+ { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
1190
+ hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
1191
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
1192
+ ip += rLength;
1193
+ anchor = ip;
1194
+ continue; /* faster when present ... (?) */
1195
+ } } }
1196
+
1197
+ /* save reps for next block */
1198
+ cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
1199
+ cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
1200
+
1201
+ /* Last Literals */
1202
+ { size_t const lastLLSize = iend - anchor;
1203
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
1204
+ seqStorePtr->lit += lastLLSize;
1205
+ }
1206
+ }
1207
+
1208
+
1209
+ static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
1210
+ const void* src, size_t srcSize)
1211
+ {
1212
+ const U32 mls = ctx->params.cParams.searchLength;
1213
+ switch(mls)
1214
+ {
1215
+ default:
1216
+ case 4 :
1217
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
1218
+ case 5 :
1219
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
1220
+ case 6 :
1221
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
1222
+ case 7 :
1223
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
1224
+ }
1225
+ }
1226
+
1227
+
1228
+ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
1229
+ const void* src, size_t srcSize,
1230
+ const U32 mls)
1231
+ {
1232
+ U32* hashTable = ctx->hashTable;
1233
+ const U32 hBits = ctx->params.cParams.hashLog;
1234
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
1235
+ const BYTE* const base = ctx->base;
1236
+ const BYTE* const dictBase = ctx->dictBase;
1237
+ const BYTE* const istart = (const BYTE*)src;
1238
+ const BYTE* ip = istart;
1239
+ const BYTE* anchor = istart;
1240
+ const U32 lowestIndex = ctx->lowLimit;
1241
+ const BYTE* const dictStart = dictBase + lowestIndex;
1242
+ const U32 dictLimit = ctx->dictLimit;
1243
+ const BYTE* const lowPrefixPtr = base + dictLimit;
1244
+ const BYTE* const dictEnd = dictBase + dictLimit;
1245
+ const BYTE* const iend = istart + srcSize;
1246
+ const BYTE* const ilimit = iend - 8;
1247
+ U32 offset_1=ctx->rep[0], offset_2=ctx->rep[1];
1248
+
1249
+ /* Search Loop */
1250
+ while (ip < ilimit) { /* < instead of <=, because (ip+1) */
1251
+ const size_t h = ZSTD_hashPtr(ip, hBits, mls);
1252
+ const U32 matchIndex = hashTable[h];
1253
+ const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
1254
+ const BYTE* match = matchBase + matchIndex;
1255
+ const U32 current = (U32)(ip-base);
1256
+ const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
1257
+ const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
1258
+ const BYTE* repMatch = repBase + repIndex;
1259
+ size_t mLength;
1260
+ hashTable[h] = current; /* update hash table */
1261
+
1262
+ if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
1263
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
1264
+ const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
1265
+ mLength = ZSTD_count_2segments(ip+1+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repMatchEnd, lowPrefixPtr) + EQUAL_READ32;
1266
+ ip++;
1267
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1268
+ } else {
1269
+ if ( (matchIndex < lowestIndex) ||
1270
+ (MEM_read32(match) != MEM_read32(ip)) ) {
1271
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
1272
+ continue;
1273
+ }
1274
+ { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
1275
+ const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
1276
+ U32 offset;
1277
+ mLength = ZSTD_count_2segments(ip+EQUAL_READ32, match+EQUAL_READ32, iend, matchEnd, lowPrefixPtr) + EQUAL_READ32;
1278
+ while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1279
+ offset = current - matchIndex;
1280
+ offset_2 = offset_1;
1281
+ offset_1 = offset;
1282
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1283
+ } }
1284
+
1285
+ /* found a match : store it */
1286
+ ip += mLength;
1287
+ anchor = ip;
1288
+
1289
+ if (ip <= ilimit) {
1290
+ /* Fill Table */
1291
+ hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
1292
+ hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1293
+ /* check immediate repcode */
1294
+ while (ip <= ilimit) {
1295
+ U32 const current2 = (U32)(ip-base);
1296
+ U32 const repIndex2 = current2 - offset_2;
1297
+ const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
1298
+ if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
1299
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
1300
+ const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
1301
+ size_t repLength2 = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch2+EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32;
1302
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
1303
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
1304
+ hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
1305
+ ip += repLength2;
1306
+ anchor = ip;
1307
+ continue;
1308
+ }
1309
+ break;
1310
+ } } }
1311
+
1312
+ /* save reps for next block */
1313
+ ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
1314
+
1315
+ /* Last Literals */
1316
+ { size_t const lastLLSize = iend - anchor;
1317
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
1318
+ seqStorePtr->lit += lastLLSize;
1319
+ }
1320
+ }
1321
+
1322
+
1323
+ static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
1324
+ const void* src, size_t srcSize)
1325
+ {
1326
+ const U32 mls = ctx->params.cParams.searchLength;
1327
+ switch(mls)
1328
+ {
1329
+ default:
1330
+ case 4 :
1331
+ ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
1332
+ case 5 :
1333
+ ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return;
1334
+ case 6 :
1335
+ ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return;
1336
+ case 7 :
1337
+ ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return;
1338
+ }
1339
+ }
1340
+
1341
+
1342
+ /*-*************************************
1343
+ * Double Fast
1344
+ ***************************************/
1345
+ static void ZSTD_fillDoubleHashTable (ZSTD_CCtx* cctx, const void* end, const U32 mls)
1346
+ {
1347
+ U32* const hashLarge = cctx->hashTable;
1348
+ const U32 hBitsL = cctx->params.cParams.hashLog;
1349
+ U32* const hashSmall = cctx->chainTable;
1350
+ const U32 hBitsS = cctx->params.cParams.chainLog;
1351
+ const BYTE* const base = cctx->base;
1352
+ const BYTE* ip = base + cctx->nextToUpdate;
1353
+ const BYTE* const iend = ((const BYTE*)end) - 8;
1354
+ const size_t fastHashFillStep = 3;
1355
+
1356
+ while(ip <= iend) {
1357
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base);
1358
+ hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base);
1359
+ ip += fastHashFillStep;
1360
+ }
1361
+ }
1362
+
1363
+
1364
+ FORCE_INLINE
1365
+ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
1366
+ const void* src, size_t srcSize,
1367
+ const U32 mls)
1368
+ {
1369
+ U32* const hashLong = cctx->hashTable;
1370
+ const U32 hBitsL = cctx->params.cParams.hashLog;
1371
+ U32* const hashSmall = cctx->chainTable;
1372
+ const U32 hBitsS = cctx->params.cParams.chainLog;
1373
+ seqStore_t* seqStorePtr = &(cctx->seqStore);
1374
+ const BYTE* const base = cctx->base;
1375
+ const BYTE* const istart = (const BYTE*)src;
1376
+ const BYTE* ip = istart;
1377
+ const BYTE* anchor = istart;
1378
+ const U32 lowestIndex = cctx->dictLimit;
1379
+ const BYTE* const lowest = base + lowestIndex;
1380
+ const BYTE* const iend = istart + srcSize;
1381
+ const BYTE* const ilimit = iend - 8;
1382
+ U32 offset_1=cctx->rep[0], offset_2=cctx->rep[1];
1383
+ U32 offsetSaved = 0;
1384
+
1385
+ /* init */
1386
+ ip += (ip==lowest);
1387
+ { U32 const maxRep = (U32)(ip-lowest);
1388
+ if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
1389
+ if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
1390
+ }
1391
+
1392
+ /* Main Search Loop */
1393
+ while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
1394
+ size_t mLength;
1395
+ size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
1396
+ size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
1397
+ U32 const current = (U32)(ip-base);
1398
+ U32 const matchIndexL = hashLong[h2];
1399
+ U32 const matchIndexS = hashSmall[h];
1400
+ const BYTE* matchLong = base + matchIndexL;
1401
+ const BYTE* match = base + matchIndexS;
1402
+ hashLong[h2] = hashSmall[h] = current; /* update hash tables */
1403
+
1404
+ if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) { /* note : by construction, offset_1 <= current */
1405
+ mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
1406
+ ip++;
1407
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1408
+ } else {
1409
+ U32 offset;
1410
+ if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
1411
+ mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;
1412
+ offset = (U32)(ip-matchLong);
1413
+ while (((ip>anchor) & (matchLong>lowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
1414
+ } else if ( (matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
1415
+ mLength = ZSTD_count(ip+4, match+4, iend) + 4;
1416
+ offset = (U32)(ip-match);
1417
+ while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1418
+ } else {
1419
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
1420
+ continue;
1421
+ }
1422
+
1423
+ offset_2 = offset_1;
1424
+ offset_1 = offset;
1425
+
1426
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1427
+ }
1428
+
1429
+ /* match found */
1430
+ ip += mLength;
1431
+ anchor = ip;
1432
+
1433
+ if (ip <= ilimit) {
1434
+ /* Fill Table */
1435
+ hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] =
1436
+ hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; /* here because current+2 could be > iend-8 */
1437
+ hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] =
1438
+ hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
1439
+
1440
+ /* check immediate repcode */
1441
+ while ( (ip <= ilimit)
1442
+ && ( (offset_2>0)
1443
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
1444
+ /* store sequence */
1445
+ size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
1446
+ { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
1447
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
1448
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
1449
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
1450
+ ip += rLength;
1451
+ anchor = ip;
1452
+ continue; /* faster when present ... (?) */
1453
+ } } }
1454
+
1455
+ /* save reps for next block */
1456
+ cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
1457
+ cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
1458
+
1459
+ /* Last Literals */
1460
+ { size_t const lastLLSize = iend - anchor;
1461
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
1462
+ seqStorePtr->lit += lastLLSize;
1463
+ }
1464
+ }
1465
+
1466
+
1467
+ static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1468
+ {
1469
+ const U32 mls = ctx->params.cParams.searchLength;
1470
+ switch(mls)
1471
+ {
1472
+ default:
1473
+ case 4 :
1474
+ ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); return;
1475
+ case 5 :
1476
+ ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5); return;
1477
+ case 6 :
1478
+ ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6); return;
1479
+ case 7 :
1480
+ ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7); return;
1481
+ }
1482
+ }
1483
+
1484
+
1485
+ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
1486
+ const void* src, size_t srcSize,
1487
+ const U32 mls)
1488
+ {
1489
+ U32* const hashLong = ctx->hashTable;
1490
+ const U32 hBitsL = ctx->params.cParams.hashLog;
1491
+ U32* const hashSmall = ctx->chainTable;
1492
+ const U32 hBitsS = ctx->params.cParams.chainLog;
1493
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
1494
+ const BYTE* const base = ctx->base;
1495
+ const BYTE* const dictBase = ctx->dictBase;
1496
+ const BYTE* const istart = (const BYTE*)src;
1497
+ const BYTE* ip = istart;
1498
+ const BYTE* anchor = istart;
1499
+ const U32 lowestIndex = ctx->lowLimit;
1500
+ const BYTE* const dictStart = dictBase + lowestIndex;
1501
+ const U32 dictLimit = ctx->dictLimit;
1502
+ const BYTE* const lowPrefixPtr = base + dictLimit;
1503
+ const BYTE* const dictEnd = dictBase + dictLimit;
1504
+ const BYTE* const iend = istart + srcSize;
1505
+ const BYTE* const ilimit = iend - 8;
1506
+ U32 offset_1=ctx->rep[0], offset_2=ctx->rep[1];
1507
+
1508
+ /* Search Loop */
1509
+ while (ip < ilimit) { /* < instead of <=, because (ip+1) */
1510
+ const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
1511
+ const U32 matchIndex = hashSmall[hSmall];
1512
+ const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
1513
+ const BYTE* match = matchBase + matchIndex;
1514
+
1515
+ const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);
1516
+ const U32 matchLongIndex = hashLong[hLong];
1517
+ const BYTE* matchLongBase = matchLongIndex < dictLimit ? dictBase : base;
1518
+ const BYTE* matchLong = matchLongBase + matchLongIndex;
1519
+
1520
+ const U32 current = (U32)(ip-base);
1521
+ const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
1522
+ const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
1523
+ const BYTE* repMatch = repBase + repIndex;
1524
+ size_t mLength;
1525
+ hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
1526
+
1527
+ if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
1528
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
1529
+ const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
1530
+ mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
1531
+ ip++;
1532
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
1533
+ } else {
1534
+ if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
1535
+ const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
1536
+ const BYTE* lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr;
1537
+ U32 offset;
1538
+ mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, lowPrefixPtr) + 8;
1539
+ offset = current - matchLongIndex;
1540
+ while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
1541
+ offset_2 = offset_1;
1542
+ offset_1 = offset;
1543
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1544
+ } else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
1545
+ const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
1546
+ const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
1547
+ U32 offset;
1548
+ mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
1549
+ while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
1550
+ offset = current - matchIndex;
1551
+ offset_2 = offset_1;
1552
+ offset_1 = offset;
1553
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
1554
+ } else {
1555
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
1556
+ continue;
1557
+ } }
1558
+
1559
+ /* found a match : store it */
1560
+ ip += mLength;
1561
+ anchor = ip;
1562
+
1563
+ if (ip <= ilimit) {
1564
+ /* Fill Table */
1565
+ hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
1566
+ hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
1567
+ hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
1568
+ hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
1569
+ /* check immediate repcode */
1570
+ while (ip <= ilimit) {
1571
+ U32 const current2 = (U32)(ip-base);
1572
+ U32 const repIndex2 = current2 - offset_2;
1573
+ const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
1574
+ if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
1575
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
1576
+ const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
1577
+ size_t const repLength2 = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch2+EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32;
1578
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
1579
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
1580
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
1581
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
1582
+ ip += repLength2;
1583
+ anchor = ip;
1584
+ continue;
1585
+ }
1586
+ break;
1587
+ } } }
1588
+
1589
+ /* save reps for next block */
1590
+ ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
1591
+
1592
+ /* Last Literals */
1593
+ { size_t const lastLLSize = iend - anchor;
1594
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
1595
+ seqStorePtr->lit += lastLLSize;
1596
+ }
1597
+ }
1598
+
1599
+
1600
+ static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
1601
+ const void* src, size_t srcSize)
1602
+ {
1603
+ const U32 mls = ctx->params.cParams.searchLength;
1604
+ switch(mls)
1605
+ {
1606
+ default:
1607
+ case 4 :
1608
+ ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); return;
1609
+ case 5 :
1610
+ ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5); return;
1611
+ case 6 :
1612
+ ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6); return;
1613
+ case 7 :
1614
+ ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7); return;
1615
+ }
1616
+ }
1617
+
1618
+
1619
+ /*-*************************************
1620
+ * Binary Tree search
1621
+ ***************************************/
1622
+ /** ZSTD_insertBt1() : add one or multiple positions to tree.
1623
+ * ip : assumed <= iend-8 .
1624
+ * @return : nb of positions added */
1625
+ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares,
1626
+ U32 extDict)
1627
+ {
1628
+ U32* const hashTable = zc->hashTable;
1629
+ const U32 hashLog = zc->params.cParams.hashLog;
1630
+ const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
1631
+ U32* const bt = zc->chainTable;
1632
+ const U32 btLog = zc->params.cParams.chainLog - 1;
1633
+ const U32 btMask= (1 << btLog) - 1;
1634
+ U32 matchIndex = hashTable[h];
1635
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
1636
+ const BYTE* const base = zc->base;
1637
+ const BYTE* const dictBase = zc->dictBase;
1638
+ const U32 dictLimit = zc->dictLimit;
1639
+ const BYTE* const dictEnd = dictBase + dictLimit;
1640
+ const BYTE* const prefixStart = base + dictLimit;
1641
+ const BYTE* match = base + matchIndex;
1642
+ const U32 current = (U32)(ip-base);
1643
+ const U32 btLow = btMask >= current ? 0 : current - btMask;
1644
+ U32* smallerPtr = bt + 2*(current&btMask);
1645
+ U32* largerPtr = smallerPtr + 1;
1646
+ U32 dummy32; /* to be nullified at the end */
1647
+ const U32 windowLow = zc->lowLimit;
1648
+ U32 matchEndIdx = current+8;
1649
+ size_t bestLength = 8;
1650
+ #ifdef ZSTD_C_PREDICT
1651
+ U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
1652
+ U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
1653
+ predictedSmall += (predictedSmall>0);
1654
+ predictedLarge += (predictedLarge>0);
1655
+ #endif /* ZSTD_C_PREDICT */
1656
+
1657
+ hashTable[h] = current; /* Update Hash Table */
1658
+
1659
+ while (nbCompares-- && (matchIndex > windowLow)) {
1660
+ U32* nextPtr = bt + 2*(matchIndex & btMask);
1661
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
1662
+ #ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
1663
+ const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
1664
+ if (matchIndex == predictedSmall) {
1665
+ /* no need to check length, result known */
1666
+ *smallerPtr = matchIndex;
1667
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1668
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
1669
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
1670
+ predictedSmall = predictPtr[1] + (predictPtr[1]>0);
1671
+ continue;
1672
+ }
1673
+ if (matchIndex == predictedLarge) {
1674
+ *largerPtr = matchIndex;
1675
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1676
+ largerPtr = nextPtr;
1677
+ matchIndex = nextPtr[0];
1678
+ predictedLarge = predictPtr[0] + (predictPtr[0]>0);
1679
+ continue;
1680
+ }
1681
+ #endif
1682
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
1683
+ match = base + matchIndex;
1684
+ if (match[matchLength] == ip[matchLength])
1685
+ matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
1686
+ } else {
1687
+ match = dictBase + matchIndex;
1688
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
1689
+ if (matchIndex+matchLength >= dictLimit)
1690
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
1691
+ }
1692
+
1693
+ if (matchLength > bestLength) {
1694
+ bestLength = matchLength;
1695
+ if (matchLength > matchEndIdx - matchIndex)
1696
+ matchEndIdx = matchIndex + (U32)matchLength;
1697
+ }
1698
+
1699
+ if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
1700
+ break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
1701
+
1702
+ if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */
1703
+ /* match is smaller than current */
1704
+ *smallerPtr = matchIndex; /* update smaller idx */
1705
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
1706
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1707
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
1708
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
1709
+ } else {
1710
+ /* match is larger than current */
1711
+ *largerPtr = matchIndex;
1712
+ commonLengthLarger = matchLength;
1713
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1714
+ largerPtr = nextPtr;
1715
+ matchIndex = nextPtr[0];
1716
+ } }
1717
+
1718
+ *smallerPtr = *largerPtr = 0;
1719
+ if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
1720
+ if (matchEndIdx > current + 8) return matchEndIdx - current - 8;
1721
+ return 1;
1722
+ }
1723
+
1724
+
1725
+ static size_t ZSTD_insertBtAndFindBestMatch (
1726
+ ZSTD_CCtx* zc,
1727
+ const BYTE* const ip, const BYTE* const iend,
1728
+ size_t* offsetPtr,
1729
+ U32 nbCompares, const U32 mls,
1730
+ U32 extDict)
1731
+ {
1732
+ U32* const hashTable = zc->hashTable;
1733
+ const U32 hashLog = zc->params.cParams.hashLog;
1734
+ const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
1735
+ U32* const bt = zc->chainTable;
1736
+ const U32 btLog = zc->params.cParams.chainLog - 1;
1737
+ const U32 btMask= (1 << btLog) - 1;
1738
+ U32 matchIndex = hashTable[h];
1739
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
1740
+ const BYTE* const base = zc->base;
1741
+ const BYTE* const dictBase = zc->dictBase;
1742
+ const U32 dictLimit = zc->dictLimit;
1743
+ const BYTE* const dictEnd = dictBase + dictLimit;
1744
+ const BYTE* const prefixStart = base + dictLimit;
1745
+ const U32 current = (U32)(ip-base);
1746
+ const U32 btLow = btMask >= current ? 0 : current - btMask;
1747
+ const U32 windowLow = zc->lowLimit;
1748
+ U32* smallerPtr = bt + 2*(current&btMask);
1749
+ U32* largerPtr = bt + 2*(current&btMask) + 1;
1750
+ U32 matchEndIdx = current+8;
1751
+ U32 dummy32; /* to be nullified at the end */
1752
+ size_t bestLength = 0;
1753
+
1754
+ hashTable[h] = current; /* Update Hash Table */
1755
+
1756
+ while (nbCompares-- && (matchIndex > windowLow)) {
1757
+ U32* nextPtr = bt + 2*(matchIndex & btMask);
1758
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
1759
+ const BYTE* match;
1760
+
1761
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
1762
+ match = base + matchIndex;
1763
+ if (match[matchLength] == ip[matchLength])
1764
+ matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
1765
+ } else {
1766
+ match = dictBase + matchIndex;
1767
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
1768
+ if (matchIndex+matchLength >= dictLimit)
1769
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
1770
+ }
1771
+
1772
+ if (matchLength > bestLength) {
1773
+ if (matchLength > matchEndIdx - matchIndex)
1774
+ matchEndIdx = matchIndex + (U32)matchLength;
1775
+ if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
1776
+ bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
1777
+ if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
1778
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
1779
+ }
1780
+
1781
+ if (match[matchLength] < ip[matchLength]) {
1782
+ /* match is smaller than current */
1783
+ *smallerPtr = matchIndex; /* update smaller idx */
1784
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
1785
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1786
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
1787
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
1788
+ } else {
1789
+ /* match is larger than current */
1790
+ *largerPtr = matchIndex;
1791
+ commonLengthLarger = matchLength;
1792
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1793
+ largerPtr = nextPtr;
1794
+ matchIndex = nextPtr[0];
1795
+ } }
1796
+
1797
+ *smallerPtr = *largerPtr = 0;
1798
+
1799
+ zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
1800
+ return bestLength;
1801
+ }
1802
+
1803
+
1804
+ static void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
1805
+ {
1806
+ const BYTE* const base = zc->base;
1807
+ const U32 target = (U32)(ip - base);
1808
+ U32 idx = zc->nextToUpdate;
1809
+
1810
+ while(idx < target)
1811
+ idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
1812
+ }
1813
+
1814
+ /** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
1815
+ static size_t ZSTD_BtFindBestMatch (
1816
+ ZSTD_CCtx* zc,
1817
+ const BYTE* const ip, const BYTE* const iLimit,
1818
+ size_t* offsetPtr,
1819
+ const U32 maxNbAttempts, const U32 mls)
1820
+ {
1821
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
1822
+ ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
1823
+ return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
1824
+ }
1825
+
1826
+
1827
+ static size_t ZSTD_BtFindBestMatch_selectMLS (
1828
+ ZSTD_CCtx* zc, /* Index table will be updated */
1829
+ const BYTE* ip, const BYTE* const iLimit,
1830
+ size_t* offsetPtr,
1831
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
1832
+ {
1833
+ switch(matchLengthSearch)
1834
+ {
1835
+ default :
1836
+ case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
1837
+ case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
1838
+ case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
1839
+ }
1840
+ }
1841
+
1842
+
1843
+ static void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
1844
+ {
1845
+ const BYTE* const base = zc->base;
1846
+ const U32 target = (U32)(ip - base);
1847
+ U32 idx = zc->nextToUpdate;
1848
+
1849
+ while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
1850
+ }
1851
+
1852
+
1853
+ /** Tree updater, providing best match */
1854
+ static size_t ZSTD_BtFindBestMatch_extDict (
1855
+ ZSTD_CCtx* zc,
1856
+ const BYTE* const ip, const BYTE* const iLimit,
1857
+ size_t* offsetPtr,
1858
+ const U32 maxNbAttempts, const U32 mls)
1859
+ {
1860
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
1861
+ ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
1862
+ return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
1863
+ }
1864
+
1865
+
1866
+ static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
1867
+ ZSTD_CCtx* zc, /* Index table will be updated */
1868
+ const BYTE* ip, const BYTE* const iLimit,
1869
+ size_t* offsetPtr,
1870
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
1871
+ {
1872
+ switch(matchLengthSearch)
1873
+ {
1874
+ default :
1875
+ case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
1876
+ case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
1877
+ case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
1878
+ }
1879
+ }
1880
+
1881
+
1882
+
1883
+ /* ***********************
1884
+ * Hash Chain
1885
+ *************************/
1886
+
1887
+ #define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
1888
+
1889
+
1890
+ /* Update chains up to ip (excluded)
1891
+ Assumption : always within prefix (ie. not within extDict) */
1892
+ FORCE_INLINE
1893
+ U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
1894
+ {
1895
+ U32* const hashTable = zc->hashTable;
1896
+ const U32 hashLog = zc->params.cParams.hashLog;
1897
+ U32* const chainTable = zc->chainTable;
1898
+ const U32 chainMask = (1 << zc->params.cParams.chainLog) - 1;
1899
+ const BYTE* const base = zc->base;
1900
+ const U32 target = (U32)(ip - base);
1901
+ U32 idx = zc->nextToUpdate;
1902
+
1903
+ while(idx < target) { /* catch up */
1904
+ size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
1905
+ NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
1906
+ hashTable[h] = idx;
1907
+ idx++;
1908
+ }
1909
+
1910
+ zc->nextToUpdate = target;
1911
+ return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
1912
+ }
1913
+
1914
+
1915
+
1916
+ FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
1917
+ size_t ZSTD_HcFindBestMatch_generic (
1918
+ ZSTD_CCtx* zc, /* Index table will be updated */
1919
+ const BYTE* const ip, const BYTE* const iLimit,
1920
+ size_t* offsetPtr,
1921
+ const U32 maxNbAttempts, const U32 mls, const U32 extDict)
1922
+ {
1923
+ U32* const chainTable = zc->chainTable;
1924
+ const U32 chainSize = (1 << zc->params.cParams.chainLog);
1925
+ const U32 chainMask = chainSize-1;
1926
+ const BYTE* const base = zc->base;
1927
+ const BYTE* const dictBase = zc->dictBase;
1928
+ const U32 dictLimit = zc->dictLimit;
1929
+ const BYTE* const prefixStart = base + dictLimit;
1930
+ const BYTE* const dictEnd = dictBase + dictLimit;
1931
+ const U32 lowLimit = zc->lowLimit;
1932
+ const U32 current = (U32)(ip-base);
1933
+ const U32 minChain = current > chainSize ? current - chainSize : 0;
1934
+ int nbAttempts=maxNbAttempts;
1935
+ size_t ml=EQUAL_READ32-1;
1936
+
1937
+ /* HC4 match finder */
1938
+ U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
1939
+
1940
+ for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
1941
+ const BYTE* match;
1942
+ size_t currentMl=0;
1943
+ if ((!extDict) || matchIndex >= dictLimit) {
1944
+ match = base + matchIndex;
1945
+ if (match[ml] == ip[ml]) /* potentially better */
1946
+ currentMl = ZSTD_count(ip, match, iLimit);
1947
+ } else {
1948
+ match = dictBase + matchIndex;
1949
+ if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
1950
+ currentMl = ZSTD_count_2segments(ip+EQUAL_READ32, match+EQUAL_READ32, iLimit, dictEnd, prefixStart) + EQUAL_READ32;
1951
+ }
1952
+
1953
+ /* save best solution */
1954
+ if (currentMl > ml) { ml = currentMl; *offsetPtr = current - matchIndex + ZSTD_REP_MOVE; if (ip+currentMl == iLimit) break; /* best possible, and avoid read overflow*/ }
1955
+
1956
+ if (matchIndex <= minChain) break;
1957
+ matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
1958
+ }
1959
+
1960
+ return ml;
1961
+ }
1962
+
1963
+
1964
+ FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS (
1965
+ ZSTD_CCtx* zc,
1966
+ const BYTE* ip, const BYTE* const iLimit,
1967
+ size_t* offsetPtr,
1968
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
1969
+ {
1970
+ switch(matchLengthSearch)
1971
+ {
1972
+ default :
1973
+ case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
1974
+ case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
1975
+ case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
1976
+ }
1977
+ }
1978
+
1979
+
1980
+ FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
1981
+ ZSTD_CCtx* zc,
1982
+ const BYTE* ip, const BYTE* const iLimit,
1983
+ size_t* offsetPtr,
1984
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
1985
+ {
1986
+ switch(matchLengthSearch)
1987
+ {
1988
+ default :
1989
+ case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
1990
+ case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
1991
+ case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
1992
+ }
1993
+ }
1994
+
1995
+
1996
+ /* *******************************
1997
+ * Common parser - lazy strategy
1998
+ *********************************/
1999
+ FORCE_INLINE
2000
+ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
2001
+ const void* src, size_t srcSize,
2002
+ const U32 searchMethod, const U32 depth)
2003
+ {
2004
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
2005
+ const BYTE* const istart = (const BYTE*)src;
2006
+ const BYTE* ip = istart;
2007
+ const BYTE* anchor = istart;
2008
+ const BYTE* const iend = istart + srcSize;
2009
+ const BYTE* const ilimit = iend - 8;
2010
+ const BYTE* const base = ctx->base + ctx->dictLimit;
2011
+
2012
+ U32 const maxSearches = 1 << ctx->params.cParams.searchLog;
2013
+ U32 const mls = ctx->params.cParams.searchLength;
2014
+
2015
+ typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
2016
+ size_t* offsetPtr,
2017
+ U32 maxNbAttempts, U32 matchLengthSearch);
2018
+ searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
2019
+ U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1], savedOffset=0;
2020
+
2021
+ /* init */
2022
+ ip += (ip==base);
2023
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
2024
+ { U32 const maxRep = (U32)(ip-base);
2025
+ if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
2026
+ if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
2027
+ }
2028
+
2029
+ /* Match Loop */
2030
+ while (ip < ilimit) {
2031
+ size_t matchLength=0;
2032
+ size_t offset=0;
2033
+ const BYTE* start=ip+1;
2034
+
2035
+ /* check repCode */
2036
+ if ((offset_1>0) & (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))) {
2037
+ /* repcode : we take it */
2038
+ matchLength = ZSTD_count(ip+1+EQUAL_READ32, ip+1+EQUAL_READ32-offset_1, iend) + EQUAL_READ32;
2039
+ if (depth==0) goto _storeSequence;
2040
+ }
2041
+
2042
+ /* first search (depth 0) */
2043
+ { size_t offsetFound = 99999999;
2044
+ size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
2045
+ if (ml2 > matchLength)
2046
+ matchLength = ml2, start = ip, offset=offsetFound;
2047
+ }
2048
+
2049
+ if (matchLength < EQUAL_READ32) {
2050
+ ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
2051
+ continue;
2052
+ }
2053
+
2054
+ /* let's try to find a better solution */
2055
+ if (depth>=1)
2056
+ while (ip<ilimit) {
2057
+ ip ++;
2058
+ if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
2059
+ size_t const mlRep = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-offset_1, iend) + EQUAL_READ32;
2060
+ int const gain2 = (int)(mlRep * 3);
2061
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
2062
+ if ((mlRep >= EQUAL_READ32) && (gain2 > gain1))
2063
+ matchLength = mlRep, offset = 0, start = ip;
2064
+ }
2065
+ { size_t offset2=99999999;
2066
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2067
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2068
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
2069
+ if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
2070
+ matchLength = ml2, offset = offset2, start = ip;
2071
+ continue; /* search a better one */
2072
+ } }
2073
+
2074
+ /* let's find an even better one */
2075
+ if ((depth==2) && (ip<ilimit)) {
2076
+ ip ++;
2077
+ if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
2078
+ size_t const ml2 = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-offset_1, iend) + EQUAL_READ32;
2079
+ int const gain2 = (int)(ml2 * 4);
2080
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
2081
+ if ((ml2 >= EQUAL_READ32) && (gain2 > gain1))
2082
+ matchLength = ml2, offset = 0, start = ip;
2083
+ }
2084
+ { size_t offset2=99999999;
2085
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2086
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2087
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
2088
+ if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
2089
+ matchLength = ml2, offset = offset2, start = ip;
2090
+ continue;
2091
+ } } }
2092
+ break; /* nothing found : store previous solution */
2093
+ }
2094
+
2095
+ /* catch up */
2096
+ if (offset) {
2097
+ while ((start>anchor) && (start>base+offset-ZSTD_REP_MOVE) && (start[-1] == start[-1-offset+ZSTD_REP_MOVE])) /* only search for offset within prefix */
2098
+ { start--; matchLength++; }
2099
+ offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
2100
+ }
2101
+
2102
+ /* store sequence */
2103
+ _storeSequence:
2104
+ { size_t const litLength = start - anchor;
2105
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
2106
+ anchor = ip = start + matchLength;
2107
+ }
2108
+
2109
+ /* check immediate repcode */
2110
+ while ( (ip <= ilimit)
2111
+ && ((offset_2>0)
2112
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
2113
+ /* store sequence */
2114
+ matchLength = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-offset_2, iend) + EQUAL_READ32;
2115
+ offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
2116
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
2117
+ ip += matchLength;
2118
+ anchor = ip;
2119
+ continue; /* faster when present ... (?) */
2120
+ } }
2121
+
2122
+ /* Save reps for next block */
2123
+ ctx->savedRep[0] = offset_1 ? offset_1 : savedOffset;
2124
+ ctx->savedRep[1] = offset_2 ? offset_2 : savedOffset;
2125
+
2126
+ /* Last Literals */
2127
+ { size_t const lastLLSize = iend - anchor;
2128
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
2129
+ seqStorePtr->lit += lastLLSize;
2130
+ ZSTD_statsUpdatePrices(&seqStorePtr->stats, lastLLSize, anchor, 0, 0);
2131
+ }
2132
+ }
2133
+
2134
+
2135
+ static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2136
+ {
2137
+ ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
2138
+ }
2139
+
2140
+ static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2141
+ {
2142
+ ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
2143
+ }
2144
+
2145
+ static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2146
+ {
2147
+ ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
2148
+ }
2149
+
2150
+ static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2151
+ {
2152
+ ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
2153
+ }
2154
+
2155
+
2156
+ FORCE_INLINE
2157
+ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
2158
+ const void* src, size_t srcSize,
2159
+ const U32 searchMethod, const U32 depth)
2160
+ {
2161
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
2162
+ const BYTE* const istart = (const BYTE*)src;
2163
+ const BYTE* ip = istart;
2164
+ const BYTE* anchor = istart;
2165
+ const BYTE* const iend = istart + srcSize;
2166
+ const BYTE* const ilimit = iend - 8;
2167
+ const BYTE* const base = ctx->base;
2168
+ const U32 dictLimit = ctx->dictLimit;
2169
+ const U32 lowestIndex = ctx->lowLimit;
2170
+ const BYTE* const prefixStart = base + dictLimit;
2171
+ const BYTE* const dictBase = ctx->dictBase;
2172
+ const BYTE* const dictEnd = dictBase + dictLimit;
2173
+ const BYTE* const dictStart = dictBase + ctx->lowLimit;
2174
+
2175
+ const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
2176
+ const U32 mls = ctx->params.cParams.searchLength;
2177
+
2178
+ typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
2179
+ size_t* offsetPtr,
2180
+ U32 maxNbAttempts, U32 matchLengthSearch);
2181
+ searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
2182
+
2183
+ U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1];
2184
+
2185
+ /* init */
2186
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
2187
+ ip += (ip == prefixStart);
2188
+
2189
+ /* Match Loop */
2190
+ while (ip < ilimit) {
2191
+ size_t matchLength=0;
2192
+ size_t offset=0;
2193
+ const BYTE* start=ip+1;
2194
+ U32 current = (U32)(ip-base);
2195
+
2196
+ /* check repCode */
2197
+ { const U32 repIndex = (U32)(current+1 - offset_1);
2198
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2199
+ const BYTE* const repMatch = repBase + repIndex;
2200
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2201
+ if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
2202
+ /* repcode detected we should take it */
2203
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2204
+ matchLength = ZSTD_count_2segments(ip+1+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
2205
+ if (depth==0) goto _storeSequence;
2206
+ } }
2207
+
2208
+ /* first search (depth 0) */
2209
+ { size_t offsetFound = 99999999;
2210
+ size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
2211
+ if (ml2 > matchLength)
2212
+ matchLength = ml2, start = ip, offset=offsetFound;
2213
+ }
2214
+
2215
+ if (matchLength < EQUAL_READ32) {
2216
+ ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
2217
+ continue;
2218
+ }
2219
+
2220
+ /* let's try to find a better solution */
2221
+ if (depth>=1)
2222
+ while (ip<ilimit) {
2223
+ ip ++;
2224
+ current++;
2225
+ /* check repCode */
2226
+ if (offset) {
2227
+ const U32 repIndex = (U32)(current - offset_1);
2228
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2229
+ const BYTE* const repMatch = repBase + repIndex;
2230
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2231
+ if (MEM_read32(ip) == MEM_read32(repMatch)) {
2232
+ /* repcode detected */
2233
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2234
+ size_t const repLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
2235
+ int const gain2 = (int)(repLength * 3);
2236
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
2237
+ if ((repLength >= EQUAL_READ32) && (gain2 > gain1))
2238
+ matchLength = repLength, offset = 0, start = ip;
2239
+ } }
2240
+
2241
+ /* search match, depth 1 */
2242
+ { size_t offset2=99999999;
2243
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2244
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2245
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
2246
+ if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
2247
+ matchLength = ml2, offset = offset2, start = ip;
2248
+ continue; /* search a better one */
2249
+ } }
2250
+
2251
+ /* let's find an even better one */
2252
+ if ((depth==2) && (ip<ilimit)) {
2253
+ ip ++;
2254
+ current++;
2255
+ /* check repCode */
2256
+ if (offset) {
2257
+ const U32 repIndex = (U32)(current - offset_1);
2258
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2259
+ const BYTE* const repMatch = repBase + repIndex;
2260
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2261
+ if (MEM_read32(ip) == MEM_read32(repMatch)) {
2262
+ /* repcode detected */
2263
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2264
+ size_t repLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
2265
+ int gain2 = (int)(repLength * 4);
2266
+ int gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
2267
+ if ((repLength >= EQUAL_READ32) && (gain2 > gain1))
2268
+ matchLength = repLength, offset = 0, start = ip;
2269
+ } }
2270
+
2271
+ /* search match, depth 2 */
2272
+ { size_t offset2=99999999;
2273
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
2274
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
2275
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
2276
+ if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
2277
+ matchLength = ml2, offset = offset2, start = ip;
2278
+ continue;
2279
+ } } }
2280
+ break; /* nothing found : store previous solution */
2281
+ }
2282
+
2283
+ /* catch up */
2284
+ if (offset) {
2285
+ U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
2286
+ const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
2287
+ const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
2288
+ while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
2289
+ offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
2290
+ }
2291
+
2292
+ /* store sequence */
2293
+ _storeSequence:
2294
+ { size_t const litLength = start - anchor;
2295
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
2296
+ anchor = ip = start + matchLength;
2297
+ }
2298
+
2299
+ /* check immediate repcode */
2300
+ while (ip <= ilimit) {
2301
+ const U32 repIndex = (U32)((ip-base) - offset_2);
2302
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
2303
+ const BYTE* const repMatch = repBase + repIndex;
2304
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
2305
+ if (MEM_read32(ip) == MEM_read32(repMatch)) {
2306
+ /* repcode detected we should take it */
2307
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
2308
+ matchLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
2309
+ offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
2310
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
2311
+ ip += matchLength;
2312
+ anchor = ip;
2313
+ continue; /* faster when present ... (?) */
2314
+ }
2315
+ break;
2316
+ } }
2317
+
2318
+ /* Save reps for next block */
2319
+ ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
2320
+
2321
+ /* Last Literals */
2322
+ { size_t const lastLLSize = iend - anchor;
2323
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
2324
+ seqStorePtr->lit += lastLLSize;
2325
+ }
2326
+ }
2327
+
2328
+
2329
+ void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2330
+ {
2331
+ ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
2332
+ }
2333
+
2334
+ static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2335
+ {
2336
+ ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
2337
+ }
2338
+
2339
+ static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2340
+ {
2341
+ ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
2342
+ }
2343
+
2344
+ static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2345
+ {
2346
+ ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
2347
+ }
2348
+
2349
+
2350
+ /* The optimal parser */
2351
+ #include "zstd_opt.h"
2352
+
2353
+ static void ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2354
+ {
2355
+ #ifdef ZSTD_OPT_H_91842398743
2356
+ ZSTD_compressBlock_opt_generic(ctx, src, srcSize);
2357
+ #else
2358
+ (void)ctx; (void)src; (void)srcSize;
2359
+ return;
2360
+ #endif
2361
+ }
2362
+
2363
+ static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2364
+ {
2365
+ #ifdef ZSTD_OPT_H_91842398743
2366
+ ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize);
2367
+ #else
2368
+ (void)ctx; (void)src; (void)srcSize;
2369
+ return;
2370
+ #endif
2371
+ }
2372
+
2373
+
2374
+ typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
2375
+
2376
+ static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
2377
+ {
2378
+ static const ZSTD_blockCompressor blockCompressor[2][7] = {
2379
+ { ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_btopt },
2380
+ { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_btopt_extDict }
2381
+ };
2382
+
2383
+ return blockCompressor[extDict][(U32)strat];
2384
+ }
2385
+
2386
+
2387
+ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2388
+ {
2389
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit);
2390
+ if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0; /* don't even attempt compression below a certain srcSize */
2391
+ ZSTD_resetSeqStore(&(zc->seqStore));
2392
+ blockCompressor(zc, src, srcSize);
2393
+ return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize);
2394
+ }
2395
+
2396
+
2397
+
2398
+
2399
+ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
2400
+ void* dst, size_t dstCapacity,
2401
+ const void* src, size_t srcSize)
2402
+ {
2403
+ size_t blockSize = cctx->blockSize;
2404
+ size_t remaining = srcSize;
2405
+ const BYTE* ip = (const BYTE*)src;
2406
+ BYTE* const ostart = (BYTE*)dst;
2407
+ BYTE* op = ostart;
2408
+ const U32 maxDist = 1 << cctx->params.cParams.windowLog;
2409
+ ZSTD_stats_t* stats = &cctx->seqStore.stats;
2410
+ ZSTD_statsInit(stats); /* debug only */
2411
+
2412
+ if (cctx->params.fParams.checksumFlag)
2413
+ XXH64_update(&cctx->xxhState, src, srcSize);
2414
+
2415
+ while (remaining) {
2416
+ size_t cSize;
2417
+ ZSTD_statsResetFreqs(stats); /* debug only */
2418
+
2419
+ if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
2420
+ if (remaining < blockSize) blockSize = remaining;
2421
+
2422
+ if ((U32)(ip+blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) {
2423
+ /* enforce maxDist */
2424
+ U32 const newLowLimit = (U32)(ip+blockSize - cctx->base) - maxDist;
2425
+ if (cctx->lowLimit < newLowLimit) cctx->lowLimit = newLowLimit;
2426
+ if (cctx->dictLimit < cctx->lowLimit) cctx->dictLimit = cctx->lowLimit;
2427
+ }
2428
+
2429
+ cSize = ZSTD_compressBlock_internal(cctx, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, ip, blockSize);
2430
+ if (ZSTD_isError(cSize)) return cSize;
2431
+
2432
+ if (cSize == 0) { /* block is not compressible */
2433
+ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize);
2434
+ if (ZSTD_isError(cSize)) return cSize;
2435
+ } else {
2436
+ op[0] = (BYTE)(cSize>>16);
2437
+ op[1] = (BYTE)(cSize>>8);
2438
+ op[2] = (BYTE)cSize;
2439
+ op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
2440
+ cSize += 3;
2441
+ }
2442
+
2443
+ remaining -= blockSize;
2444
+ dstCapacity -= cSize;
2445
+ ip += blockSize;
2446
+ op += cSize;
2447
+ }
2448
+
2449
+ ZSTD_statsPrint(stats, cctx->params.cParams.searchLength);
2450
+ return op-ostart;
2451
+ }
2452
+
2453
+
2454
+ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2455
+ ZSTD_parameters params, U64 pledgedSrcSize, U32 dictID)
2456
+ { BYTE* const op = (BYTE*)dst;
2457
+ U32 const dictIDSizeCode = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
2458
+ U32 const checksumFlag = params.fParams.checksumFlag>0;
2459
+ U32 const windowSize = 1U << params.cParams.windowLog;
2460
+ U32 const directModeFlag = params.fParams.contentSizeFlag && (windowSize > (pledgedSrcSize-1));
2461
+ BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2462
+ U32 const fcsCode = params.fParams.contentSizeFlag ?
2463
+ (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : /* 0-3 */
2464
+ 0;
2465
+ BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (directModeFlag<<5) + (fcsCode<<6) );
2466
+ size_t pos;
2467
+
2468
+ if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
2469
+
2470
+ MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2471
+ op[4] = frameHeaderDecriptionByte; pos=5;
2472
+ if (!directModeFlag) op[pos++] = windowLogByte;
2473
+ switch(dictIDSizeCode)
2474
+ {
2475
+ default: /* impossible */
2476
+ case 0 : break;
2477
+ case 1 : op[pos] = (BYTE)(dictID); pos++; break;
2478
+ case 2 : MEM_writeLE16(op+pos, (U16)(dictID)); pos+=2; break;
2479
+ case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break;
2480
+ }
2481
+ switch(fcsCode)
2482
+ {
2483
+ default: /* impossible */
2484
+ case 0 : if (directModeFlag) op[pos++] = (BYTE)(pledgedSrcSize); break;
2485
+ case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;
2486
+ case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;
2487
+ case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break;
2488
+ }
2489
+ return pos;
2490
+ }
2491
+
2492
+
2493
+ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
2494
+ void* dst, size_t dstCapacity,
2495
+ const void* src, size_t srcSize,
2496
+ U32 frame)
2497
+ {
2498
+ const BYTE* const ip = (const BYTE*) src;
2499
+ size_t fhSize = 0;
2500
+
2501
+ if (zc->stage==0) return ERROR(stage_wrong);
2502
+ if (frame && (zc->stage==1)) { /* copy saved header */
2503
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, zc->params, zc->frameContentSize, zc->dictID);
2504
+ if (ZSTD_isError(fhSize)) return fhSize;
2505
+ dstCapacity -= fhSize;
2506
+ dst = (char*)dst + fhSize;
2507
+ zc->stage = 2;
2508
+ }
2509
+
2510
+ /* Check if blocks follow each other */
2511
+ if (src != zc->nextSrc) {
2512
+ /* not contiguous */
2513
+ size_t const delta = zc->nextSrc - ip;
2514
+ zc->lowLimit = zc->dictLimit;
2515
+ zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2516
+ zc->dictBase = zc->base;
2517
+ zc->base -= delta;
2518
+ zc->nextToUpdate = zc->dictLimit;
2519
+ if (zc->dictLimit - zc->lowLimit < 8) zc->lowLimit = zc->dictLimit; /* too small extDict */
2520
+ }
2521
+
2522
+ /* preemptive overflow correction */
2523
+ if (zc->lowLimit > (1<<30)) {
2524
+ U32 const btplus = (zc->params.cParams.strategy == ZSTD_btlazy2) | (zc->params.cParams.strategy == ZSTD_btopt);
2525
+ U32 const chainMask = (1 << (zc->params.cParams.chainLog - btplus)) - 1;
2526
+ U32 const newLowLimit = zc->lowLimit & chainMask; /* preserve position % chainSize */
2527
+ U32 const correction = zc->lowLimit - newLowLimit;
2528
+ ZSTD_reduceIndex(zc, correction);
2529
+ zc->base += correction;
2530
+ zc->dictBase += correction;
2531
+ zc->lowLimit = newLowLimit;
2532
+ zc->dictLimit -= correction;
2533
+ if (zc->nextToUpdate < correction) zc->nextToUpdate = 0;
2534
+ else zc->nextToUpdate -= correction;
2535
+ }
2536
+
2537
+ /* if input and dictionary overlap : reduce dictionary (presumed modified by input) */
2538
+ if ((ip+srcSize > zc->dictBase + zc->lowLimit) && (ip < zc->dictBase + zc->dictLimit)) {
2539
+ zc->lowLimit = (U32)(ip + srcSize - zc->dictBase);
2540
+ if (zc->lowLimit > zc->dictLimit) zc->lowLimit = zc->dictLimit;
2541
+ }
2542
+
2543
+ zc->nextSrc = ip + srcSize;
2544
+ { size_t const cSize = frame ?
2545
+ ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize) :
2546
+ ZSTD_compressBlock_internal (zc, dst, dstCapacity, src, srcSize);
2547
+ if (ZSTD_isError(cSize)) return cSize;
2548
+ return cSize + fhSize;
2549
+ }
2550
+ }
2551
+
2552
+
2553
+ size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
2554
+ void* dst, size_t dstCapacity,
2555
+ const void* src, size_t srcSize)
2556
+ {
2557
+ return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 1);
2558
+ }
2559
+
2560
+
2561
+ size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2562
+ {
2563
+ size_t const blockSizeMax = MIN (ZSTD_BLOCKSIZE_MAX, 1 << zc->params.cParams.windowLog);
2564
+ if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
2565
+ ZSTD_LOG_BLOCK("%p: ZSTD_compressBlock searchLength=%d\n", zc->base, zc->params.cParams.searchLength);
2566
+ return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 0);
2567
+ }
2568
+
2569
+
2570
+ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
2571
+ {
2572
+ const BYTE* const ip = (const BYTE*) src;
2573
+ const BYTE* const iend = ip + srcSize;
2574
+
2575
+ /* input becomes current prefix */
2576
+ zc->lowLimit = zc->dictLimit;
2577
+ zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2578
+ zc->dictBase = zc->base;
2579
+ zc->base += ip - zc->nextSrc;
2580
+ zc->nextToUpdate = zc->dictLimit;
2581
+ zc->loadedDictEnd = (U32)(iend - zc->base);
2582
+
2583
+ zc->nextSrc = iend;
2584
+ if (srcSize <= 8) return 0;
2585
+
2586
+ switch(zc->params.cParams.strategy)
2587
+ {
2588
+ case ZSTD_fast:
2589
+ ZSTD_fillHashTable (zc, iend, zc->params.cParams.searchLength);
2590
+ break;
2591
+
2592
+ case ZSTD_dfast:
2593
+ ZSTD_fillDoubleHashTable (zc, iend, zc->params.cParams.searchLength);
2594
+ break;
2595
+
2596
+ case ZSTD_greedy:
2597
+ case ZSTD_lazy:
2598
+ case ZSTD_lazy2:
2599
+ ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.cParams.searchLength);
2600
+ break;
2601
+
2602
+ case ZSTD_btlazy2:
2603
+ case ZSTD_btopt:
2604
+ ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
2605
+ break;
2606
+
2607
+ default:
2608
+ return ERROR(GENERIC); /* strategy doesn't exist; impossible */
2609
+ }
2610
+
2611
+ zc->nextToUpdate = zc->loadedDictEnd;
2612
+ return 0;
2613
+ }
2614
+
2615
+
2616
+ /* Dictionary format :
2617
+ Magic == ZSTD_DICT_MAGIC (4 bytes)
2618
+ HUF_writeCTable(256)
2619
+ FSE_writeNCount(ml)
2620
+ FSE_writeNCount(off)
2621
+ FSE_writeNCount(ll)
2622
+ RepOffsets
2623
+ Dictionary content
2624
+ */
2625
+ /*! ZSTD_loadDictEntropyStats() :
2626
+ @return : size read from dictionary
2627
+ note : magic number supposed already checked */
2628
+ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
2629
+ {
2630
+ const BYTE* dictPtr = (const BYTE*)dict;
2631
+ const BYTE* const dictEnd = dictPtr + dictSize;
2632
+
2633
+ { size_t const hufHeaderSize = HUF_readCTable(cctx->hufTable, 255, dict, dictSize);
2634
+ if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
2635
+ dictPtr += hufHeaderSize;
2636
+ }
2637
+
2638
+ { short offcodeNCount[MaxOff+1];
2639
+ unsigned offcodeMaxValue = MaxOff, offcodeLog = OffFSELog;
2640
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
2641
+ if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
2642
+ { size_t const errorCode = FSE_buildCTable(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog);
2643
+ if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
2644
+ dictPtr += offcodeHeaderSize;
2645
+ }
2646
+
2647
+ { short matchlengthNCount[MaxML+1];
2648
+ unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
2649
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
2650
+ if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
2651
+ { size_t const errorCode = FSE_buildCTable(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
2652
+ if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
2653
+ dictPtr += matchlengthHeaderSize;
2654
+ }
2655
+
2656
+ { short litlengthNCount[MaxLL+1];
2657
+ unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
2658
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
2659
+ if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
2660
+ { size_t const errorCode = FSE_buildCTable(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog);
2661
+ if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
2662
+ dictPtr += litlengthHeaderSize;
2663
+ }
2664
+
2665
+ if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
2666
+ cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
2667
+ cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
2668
+ cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
2669
+ dictPtr += 12;
2670
+
2671
+ cctx->flagStaticTables = 1;
2672
+ return dictPtr - (const BYTE*)dict;
2673
+ }
2674
+
2675
+ /** ZSTD_compress_insertDictionary() :
2676
+ * @return : 0, or an error code */
2677
+ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
2678
+ {
2679
+ if ((dict==NULL) || (dictSize<=8)) return 0;
2680
+
2681
+ /* default : dict is pure content */
2682
+ if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) return ZSTD_loadDictionaryContent(zc, dict, dictSize);
2683
+ zc->dictID = zc->params.fParams.noDictIDFlag ? 0 : MEM_readLE32((const char*)dict+4);
2684
+
2685
+ /* known magic number : dict is parsed for entropy stats and content */
2686
+ { size_t const eSize = ZSTD_loadDictEntropyStats(zc, (const char*)dict+8 /* skip dictHeader */, dictSize-8) + 8;
2687
+ if (ZSTD_isError(eSize)) return eSize;
2688
+ return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
2689
+ }
2690
+ }
2691
+
2692
+
2693
+ /*! ZSTD_compressBegin_internal() :
2694
+ * @return : 0, or an error code */
2695
+ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* zc,
2696
+ const void* dict, size_t dictSize,
2697
+ ZSTD_parameters params, U64 pledgedSrcSize)
2698
+ {
2699
+ size_t const resetError = ZSTD_resetCCtx_advanced(zc, params, pledgedSrcSize, 1);
2700
+ if (ZSTD_isError(resetError)) return resetError;
2701
+
2702
+ return ZSTD_compress_insertDictionary(zc, dict, dictSize);
2703
+ }
2704
+
2705
+
2706
+ /*! ZSTD_compressBegin_advanced() :
2707
+ * @return : 0, or an error code */
2708
+ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
2709
+ const void* dict, size_t dictSize,
2710
+ ZSTD_parameters params, unsigned long long pledgedSrcSize)
2711
+ {
2712
+ /* compression parameters verification and optimization */
2713
+ { size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, pledgedSrcSize);
2714
+ if (ZSTD_isError(errorCode)) return errorCode; }
2715
+
2716
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, pledgedSrcSize);
2717
+ }
2718
+
2719
+
2720
+ size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
2721
+ {
2722
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
2723
+ ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin_usingDict compressionLevel=%d\n", cctx->base, compressionLevel);
2724
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, 0);
2725
+ }
2726
+
2727
+
2728
+ size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
2729
+ {
2730
+ ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin compressionLevel=%d\n", zc->base, compressionLevel);
2731
+ return ZSTD_compressBegin_usingDict(zc, NULL, 0, compressionLevel);
2732
+ }
2733
+
2734
+
2735
+ /*! ZSTD_compressEnd() :
2736
+ * Write frame epilogue.
2737
+ * @return : nb of bytes written into dst (or an error code) */
2738
+ size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
2739
+ {
2740
+ BYTE* op = (BYTE*)dst;
2741
+ size_t fhSize = 0;
2742
+
2743
+ /* not even init ! */
2744
+ if (cctx->stage==0) return ERROR(stage_wrong);
2745
+
2746
+ /* special case : empty frame */
2747
+ if (cctx->stage==1) {
2748
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, 0, 0);
2749
+ if (ZSTD_isError(fhSize)) return fhSize;
2750
+ dstCapacity -= fhSize;
2751
+ op += fhSize;
2752
+ cctx->stage = 2;
2753
+ }
2754
+
2755
+ /* frame epilogue */
2756
+ if (dstCapacity < 3) return ERROR(dstSize_tooSmall);
2757
+ { U32 const checksum = cctx->params.fParams.checksumFlag ?
2758
+ (U32)((XXH64_digest(&cctx->xxhState) >> 11) & ((1<<22)-1)) :
2759
+ 0;
2760
+ op[0] = (BYTE)((bt_end<<6) + (checksum>>16));
2761
+ op[1] = (BYTE)(checksum>>8);
2762
+ op[2] = (BYTE)checksum;
2763
+ }
2764
+
2765
+ cctx->stage = 0; /* return to "created but not init" status */
2766
+ return 3+fhSize;
2767
+ }
2768
+
2769
+
2770
+ /*! ZSTD_compress_usingPreparedCCtx() :
2771
+ * Same as ZSTD_compress_usingDict, but using a reference context `preparedCCtx`, where dictionary has been loaded.
2772
+ * It avoids reloading the dictionary each time.
2773
+ * `preparedCCtx` must have been properly initialized using ZSTD_compressBegin_usingDict() or ZSTD_compressBegin_advanced().
2774
+ * Requires 2 contexts : 1 for reference (preparedCCtx) which will not be modified, and 1 to run the compression operation (cctx) */
2775
+ static size_t ZSTD_compress_usingPreparedCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx,
2776
+ void* dst, size_t dstCapacity,
2777
+ const void* src, size_t srcSize)
2778
+ {
2779
+ { size_t const errorCode = ZSTD_copyCCtx(cctx, preparedCCtx);
2780
+ if (ZSTD_isError(errorCode)) return errorCode;
2781
+ }
2782
+ { size_t const cSize = ZSTD_compressContinue(cctx, dst, dstCapacity, src, srcSize);
2783
+ if (ZSTD_isError(cSize)) return cSize;
2784
+
2785
+ { size_t const endSize = ZSTD_compressEnd(cctx, (char*)dst+cSize, dstCapacity-cSize);
2786
+ if (ZSTD_isError(endSize)) return endSize;
2787
+ return cSize + endSize;
2788
+ } }
2789
+ }
2790
+
2791
+
2792
+ static size_t ZSTD_compress_internal (ZSTD_CCtx* ctx,
2793
+ void* dst, size_t dstCapacity,
2794
+ const void* src, size_t srcSize,
2795
+ const void* dict,size_t dictSize,
2796
+ ZSTD_parameters params)
2797
+ {
2798
+ BYTE* const ostart = (BYTE*)dst;
2799
+ BYTE* op = ostart;
2800
+
2801
+ /* Init */
2802
+ { size_t const errorCode = ZSTD_compressBegin_internal(ctx, dict, dictSize, params, srcSize);
2803
+ if(ZSTD_isError(errorCode)) return errorCode; }
2804
+
2805
+ /* body (compression) */
2806
+ { size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize);
2807
+ if(ZSTD_isError(oSize)) return oSize;
2808
+ op += oSize;
2809
+ dstCapacity -= oSize; }
2810
+
2811
+ /* Close frame */
2812
+ { size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity);
2813
+ if(ZSTD_isError(oSize)) return oSize;
2814
+ op += oSize; }
2815
+
2816
+ return (op - ostart);
2817
+ }
2818
+
2819
+ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
2820
+ void* dst, size_t dstCapacity,
2821
+ const void* src, size_t srcSize,
2822
+ const void* dict,size_t dictSize,
2823
+ ZSTD_parameters params)
2824
+ {
2825
+ size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, srcSize);
2826
+ if (ZSTD_isError(errorCode)) return errorCode;
2827
+ return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2828
+ }
2829
+
2830
+ size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel)
2831
+ {
2832
+ ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, dictSize);
2833
+ params.fParams.contentSizeFlag = 1;
2834
+ ZSTD_LOG_BLOCK("%p: ZSTD_compress_usingDict srcSize=%d dictSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, (int)dictSize, compressionLevel);
2835
+ return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2836
+ }
2837
+
2838
+ size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
2839
+ {
2840
+ ZSTD_LOG_BLOCK("%p: ZSTD_compressCCtx srcSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, compressionLevel);
2841
+ return ZSTD_compress_usingDict(ctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
2842
+ }
2843
+
2844
+ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
2845
+ {
2846
+ size_t result;
2847
+ ZSTD_CCtx ctxBody;
2848
+ memset(&ctxBody, 0, sizeof(ctxBody));
2849
+ memcpy(&ctxBody.customMem, &defaultCustomMem, sizeof(ZSTD_customMem));
2850
+ result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
2851
+ ctxBody.customMem.customFree(ctxBody.customMem.opaque, ctxBody.workSpace); /* can't free ctxBody, since it's on stack; just free heap content */
2852
+ return result;
2853
+ }
2854
+
2855
+
2856
+ /* ===== Dictionary API ===== */
2857
+
2858
+ struct ZSTD_CDict_s {
2859
+ void* dictContent;
2860
+ size_t dictContentSize;
2861
+ ZSTD_CCtx* refContext;
2862
+ }; /* typedef'd tp ZSTD_CDict within zstd.h */
2863
+
2864
+ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, ZSTD_parameters params, ZSTD_customMem customMem)
2865
+ {
2866
+ if (!customMem.customAlloc && !customMem.customFree)
2867
+ customMem = defaultCustomMem;
2868
+
2869
+ if (!customMem.customAlloc || !customMem.customFree) /* can't have 1/2 custom alloc/free as NULL */
2870
+ return NULL;
2871
+
2872
+ { ZSTD_CDict* const cdict = (ZSTD_CDict*) customMem.customAlloc(customMem.opaque, sizeof(*cdict));
2873
+ void* const dictContent = customMem.customAlloc(customMem.opaque, dictSize);
2874
+ ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
2875
+
2876
+ if (!dictContent || !cdict || !cctx) {
2877
+ customMem.customFree(customMem.opaque, dictContent);
2878
+ customMem.customFree(customMem.opaque, cdict);
2879
+ customMem.customFree(customMem.opaque, cctx);
2880
+ return NULL;
2881
+ }
2882
+
2883
+ memcpy(dictContent, dict, dictSize);
2884
+ { size_t const errorCode = ZSTD_compressBegin_advanced(cctx, dictContent, dictSize, params, 0);
2885
+ if (ZSTD_isError(errorCode)) {
2886
+ customMem.customFree(customMem.opaque, dictContent);
2887
+ customMem.customFree(customMem.opaque, cdict);
2888
+ customMem.customFree(customMem.opaque, cctx);
2889
+ return NULL;
2890
+ } }
2891
+
2892
+ cdict->dictContent = dictContent;
2893
+ cdict->dictContentSize = dictSize;
2894
+ cdict->refContext = cctx;
2895
+ return cdict;
2896
+ }
2897
+ }
2898
+
2899
+ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
2900
+ {
2901
+ ZSTD_customMem const allocator = { NULL, NULL, NULL };
2902
+ ZSTD_parameters params;
2903
+ memset(&params, 0, sizeof(params));
2904
+ params.cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
2905
+ params.fParams.contentSizeFlag = 1;
2906
+ return ZSTD_createCDict_advanced(dict, dictSize, params, allocator);
2907
+ }
2908
+
2909
+ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
2910
+ {
2911
+ ZSTD_freeFunction const cFree = cdict->refContext->customMem.customFree;
2912
+ void* const opaque = cdict->refContext->customMem.opaque;
2913
+ ZSTD_freeCCtx(cdict->refContext);
2914
+ cFree(opaque, cdict->dictContent);
2915
+ cFree(opaque, cdict);
2916
+ return 0;
2917
+ }
2918
+
2919
+ ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
2920
+ void* dst, size_t dstCapacity,
2921
+ const void* src, size_t srcSize,
2922
+ const ZSTD_CDict* cdict)
2923
+ {
2924
+ return ZSTD_compress_usingPreparedCCtx(cctx, cdict->refContext,
2925
+ dst, dstCapacity,
2926
+ src, srcSize);
2927
+ }
2928
+
2929
+
2930
+
2931
+ /*-===== Pre-defined compression levels =====-*/
2932
+
2933
+ #define ZSTD_DEFAULT_CLEVEL 1
2934
+ #define ZSTD_MAX_CLEVEL 22
2935
+ unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
2936
+
2937
+ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
2938
+ { /* "default" */
2939
+ /* W, C, H, S, L, TL, strat */
2940
+ { 18, 12, 12, 1, 7, 16, ZSTD_fast }, /* level 0 - not used */
2941
+ { 19, 13, 14, 1, 7, 16, ZSTD_fast }, /* level 1 */
2942
+ { 19, 15, 16, 1, 6, 16, ZSTD_fast }, /* level 2 */
2943
+ { 20, 16, 18, 1, 5, 16, ZSTD_dfast }, /* level 3 */
2944
+ { 20, 13, 17, 2, 5, 16, ZSTD_greedy }, /* level 4.*/
2945
+ { 20, 15, 18, 3, 5, 16, ZSTD_greedy }, /* level 5 */
2946
+ { 21, 16, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */
2947
+ { 21, 17, 20, 3, 5, 16, ZSTD_lazy }, /* level 7 */
2948
+ { 21, 18, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 8.*/
2949
+ { 21, 20, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 9 */
2950
+ { 21, 19, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
2951
+ { 22, 20, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
2952
+ { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
2953
+ { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 13 */
2954
+ { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 14 */
2955
+ { 22, 21, 21, 5, 5, 16, ZSTD_btlazy2 }, /* level 15 */
2956
+ { 23, 22, 22, 5, 5, 16, ZSTD_btlazy2 }, /* level 16 */
2957
+ { 23, 23, 22, 5, 5, 16, ZSTD_btlazy2 }, /* level 17.*/
2958
+ { 23, 23, 22, 6, 5, 24, ZSTD_btopt }, /* level 18.*/
2959
+ { 23, 23, 22, 6, 3, 48, ZSTD_btopt }, /* level 19.*/
2960
+ { 25, 26, 23, 7, 3, 64, ZSTD_btopt }, /* level 20.*/
2961
+ { 26, 26, 23, 7, 3,256, ZSTD_btopt }, /* level 21.*/
2962
+ { 27, 27, 25, 9, 3,512, ZSTD_btopt }, /* level 22.*/
2963
+ },
2964
+ { /* for srcSize <= 256 KB */
2965
+ /* W, C, H, S, L, T, strat */
2966
+ { 18, 12, 12, 1, 7, 4, ZSTD_fast }, /* level 0 - not used */
2967
+ { 18, 13, 14, 1, 6, 4, ZSTD_fast }, /* level 1 */
2968
+ { 18, 15, 17, 1, 5, 4, ZSTD_fast }, /* level 2 */
2969
+ { 18, 13, 15, 1, 5, 4, ZSTD_greedy }, /* level 3.*/
2970
+ { 18, 15, 17, 1, 5, 4, ZSTD_greedy }, /* level 4.*/
2971
+ { 18, 16, 17, 4, 5, 4, ZSTD_greedy }, /* level 5 */
2972
+ { 18, 17, 17, 5, 5, 4, ZSTD_greedy }, /* level 6 */
2973
+ { 18, 17, 17, 4, 4, 4, ZSTD_lazy }, /* level 7 */
2974
+ { 18, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
2975
+ { 18, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
2976
+ { 18, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
2977
+ { 18, 18, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 11.*/
2978
+ { 18, 18, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 12.*/
2979
+ { 18, 19, 17, 7, 4, 4, ZSTD_btlazy2 }, /* level 13 */
2980
+ { 18, 18, 18, 4, 4, 16, ZSTD_btopt }, /* level 14.*/
2981
+ { 18, 18, 18, 8, 4, 24, ZSTD_btopt }, /* level 15.*/
2982
+ { 18, 19, 18, 8, 3, 48, ZSTD_btopt }, /* level 16.*/
2983
+ { 18, 19, 18, 8, 3, 96, ZSTD_btopt }, /* level 17.*/
2984
+ { 18, 19, 18, 9, 3,128, ZSTD_btopt }, /* level 18.*/
2985
+ { 18, 19, 18, 10, 3,256, ZSTD_btopt }, /* level 19.*/
2986
+ { 18, 19, 18, 11, 3,512, ZSTD_btopt }, /* level 20.*/
2987
+ { 18, 19, 18, 12, 3,512, ZSTD_btopt }, /* level 21.*/
2988
+ { 18, 19, 18, 13, 3,512, ZSTD_btopt }, /* level 22.*/
2989
+ },
2990
+ { /* for srcSize <= 128 KB */
2991
+ /* W, C, H, S, L, T, strat */
2992
+ { 17, 12, 12, 1, 7, 4, ZSTD_fast }, /* level 0 - not used */
2993
+ { 17, 12, 13, 1, 6, 4, ZSTD_fast }, /* level 1 */
2994
+ { 17, 13, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
2995
+ { 17, 13, 14, 2, 5, 4, ZSTD_greedy }, /* level 3 */
2996
+ { 17, 13, 15, 3, 4, 4, ZSTD_greedy }, /* level 4 */
2997
+ { 17, 15, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
2998
+ { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
2999
+ { 17, 15, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 7 */
3000
+ { 17, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
3001
+ { 17, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
3002
+ { 17, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
3003
+ { 17, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
3004
+ { 17, 17, 17, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */
3005
+ { 17, 18, 17, 6, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
3006
+ { 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/
3007
+ { 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/
3008
+ { 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/
3009
+ { 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
3010
+ { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
3011
+ { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
3012
+ { 17, 18, 17, 9, 3,256, ZSTD_btopt }, /* level 20.*/
3013
+ { 17, 18, 17, 10, 3,256, ZSTD_btopt }, /* level 21.*/
3014
+ { 17, 18, 17, 11, 3,256, ZSTD_btopt }, /* level 22.*/
3015
+ },
3016
+ { /* for srcSize <= 16 KB */
3017
+ /* W, C, H, S, L, T, strat */
3018
+ { 14, 12, 12, 1, 7, 6, ZSTD_fast }, /* level 0 - not used */
3019
+ { 14, 14, 14, 1, 7, 6, ZSTD_fast }, /* level 1 */
3020
+ { 14, 14, 14, 1, 4, 6, ZSTD_fast }, /* level 2 */
3021
+ { 14, 14, 14, 1, 4, 6, ZSTD_dfast }, /* level 3.*/
3022
+ { 14, 14, 14, 4, 4, 6, ZSTD_greedy }, /* level 4.*/
3023
+ { 14, 14, 14, 3, 4, 6, ZSTD_lazy }, /* level 5.*/
3024
+ { 14, 14, 14, 4, 4, 6, ZSTD_lazy2 }, /* level 6 */
3025
+ { 14, 14, 14, 5, 4, 6, ZSTD_lazy2 }, /* level 7 */
3026
+ { 14, 14, 14, 6, 4, 6, ZSTD_lazy2 }, /* level 8.*/
3027
+ { 14, 15, 14, 6, 4, 6, ZSTD_btlazy2 }, /* level 9.*/
3028
+ { 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/
3029
+ { 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/
3030
+ { 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
3031
+ { 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
3032
+ { 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
3033
+ { 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
3034
+ { 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
3035
+ { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
3036
+ { 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
3037
+ { 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
3038
+ { 14, 15, 15, 8, 3,256, ZSTD_btopt }, /* level 20.*/
3039
+ { 14, 15, 15, 9, 3,256, ZSTD_btopt }, /* level 21.*/
3040
+ { 14, 15, 15, 10, 3,256, ZSTD_btopt }, /* level 22.*/
3041
+ },
3042
+ };
3043
+
3044
+ /*! ZSTD_getCParams() :
3045
+ * @return ZSTD_compressionParameters structure for a selected compression level, `srcSize` and `dictSize`.
3046
+ * Size values are optional, provide 0 if not known or unused */
3047
+ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSize, size_t dictSize)
3048
+ {
3049
+ ZSTD_compressionParameters cp;
3050
+ size_t const addedSize = srcSize ? 0 : 500;
3051
+ U64 const rSize = srcSize+dictSize ? srcSize+dictSize+addedSize : (U64)-1;
3052
+ U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
3053
+ if (compressionLevel <= 0) compressionLevel = ZSTD_DEFAULT_CLEVEL; /* 0 == default; no negative compressionLevel yet */
3054
+ if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
3055
+ cp = ZSTD_defaultCParameters[tableID][compressionLevel];
3056
+ if (MEM_32bits()) { /* auto-correction, for 32-bits mode */
3057
+ if (cp.windowLog > ZSTD_WINDOWLOG_MAX) cp.windowLog = ZSTD_WINDOWLOG_MAX;
3058
+ if (cp.chainLog > ZSTD_CHAINLOG_MAX) cp.chainLog = ZSTD_CHAINLOG_MAX;
3059
+ if (cp.hashLog > ZSTD_HASHLOG_MAX) cp.hashLog = ZSTD_HASHLOG_MAX;
3060
+ }
3061
+ cp = ZSTD_adjustCParams(cp, srcSize, dictSize);
3062
+ return cp;
3063
+ }
3064
+
3065
+ /*! ZSTD_getParams() :
3066
+ * same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`).
3067
+ * All fields of `ZSTD_frameParameters` are set to default (0) */
3068
+ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSize, size_t dictSize) {
3069
+ ZSTD_parameters params;
3070
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize);
3071
+ memset(&params, 0, sizeof(params));
3072
+ params.cParams = cParams;
3073
+ return params;
3074
+ }